/*
* Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner,
* Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain,
* Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter,
* Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann,
* Samuel Zweifel
*
* This file is part of Jukefox.
*
* Jukefox is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or any later version. Jukefox is
* distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Jukefox. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.ethz.dcg.pancho3.model;
import java.io.File;
import java.util.Random;
import android.app.Activity;
import android.app.Application;
import android.app.KeyguardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Handler;
import android.os.PowerManager;
import android.telephony.TelephonyManager;
import ch.ethz.dcg.jukefox.commons.AndroidConstants;
import ch.ethz.dcg.jukefox.commons.utils.AndroidLogPrinter;
import ch.ethz.dcg.jukefox.commons.utils.Log;
import ch.ethz.dcg.jukefox.commons.utils.Log.LogLevel;
import ch.ethz.dcg.jukefox.commons.utils.RandomProvider;
import ch.ethz.dcg.jukefox.controller.Controller;
import ch.ethz.dcg.jukefox.controller.player.AndroidPlayerController;
import ch.ethz.dcg.jukefox.manager.AndroidDirectoryManager;
import ch.ethz.dcg.jukefox.manager.AndroidSettingsManager;
import ch.ethz.dcg.jukefox.model.AbstractPlayerModelManager;
import ch.ethz.dcg.jukefox.model.AndroidCollectionModelManager;
import ch.ethz.dcg.jukefox.model.AndroidPlayerModelManager;
import ch.ethz.dcg.pancho3.R;
import ch.ethz.dcg.pancho3.commons.settings.ISettingsEditor;
import ch.ethz.dcg.pancho3.commons.settings.ISettingsReader;
import ch.ethz.dcg.pancho3.commons.utils.AndroidUtils;
import ch.ethz.dcg.pancho3.controller.JukefoxIntentReceiver;
import ch.ethz.dcg.pancho3.view.commons.JukefoxNotificationManager;
public class JukefoxApplication extends Application {
private final static String TAG = JukefoxApplication.class.getSimpleName();
public static String unknownTitleAlias;
public static String unknownArtistAlias;
public static String unknownAlbumAlias;
public static String albumArtistAlias;
private static String uniqueId;
private static Context appCtx;
private static JukefoxApplication instance;
private static PowerManager powerManager;
private static boolean screenOn;
private static Random random = RandomProvider.getRandom();
private static AndroidCollectionModelManager collectionModel;
private static AndroidPlayerModelManager playerModel;
private static AndroidPlayerController playerController;
private static Controller controller;
private JukefoxIntentReceiver intentReceiver;
private static AndroidDirectoryManager directoryManager;
@SuppressWarnings("unused")
private static JukefoxNotificationManager notificationManager;
// private Timer playlistSaveTimer;
private static Handler handler;
private static WakeLockManager wakeLockManager;
private static KeyguardManager keyguardManager;
// private static KeyguardLock lock = null;
public static long ignoreEventsUntil = 0;
@Override
public void onCreate() {
super.onCreate();
Log.createLogPrinter(new AndroidLogPrinter());
directoryManager = new AndroidDirectoryManager();
Log.setLogFileBasePath(directoryManager.getLogFileBasePath());
Log.setLogLevel(LogLevel.VERBOSE); // FIXME debug only; should be LogLevel.ERROR
appCtx = this;
instance = this;
// Initialize the wake lock before the model and the controller because
// they could be used by them
powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLockManager = new WakeLockManager(powerManager);
collectionModel = new AndroidCollectionModelManager(this, directoryManager);
playerModel = (AndroidPlayerModelManager) collectionModel
.getPlayerModelManager(AndroidConstants.PLAYER_MODEL_NAME);
playerController = new AndroidPlayerController(this, collectionModel, playerModel);
uniqueId = generateUniqueDeviceInstallationId();
controller = new Controller(this, playerController, collectionModel, playerModel);
if (!AndroidSettingsManager.getAndroidSettingsReader().isFirstStart()) {
controller.startStartupManager();
} else {
// ensure clean start...
directoryManager.deleteDirectories();
directoryManager.createAllDirectories();
}
notificationManager = new JukefoxNotificationManager(this, playerController);
keyguardManager = (KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE);
unknownTitleAlias = getString(R.string.unknown_title_alias);
unknownAlbumAlias = getString(R.string.unknown_album_alias);
unknownArtistAlias = getString(R.string.unknown_artist_alias);
albumArtistAlias = getString(R.string.album_artist_alias);
handler = new Handler();
JukefoxIntentReceiver.updateJukefoxIntentReceiver(this);
// Send logs async
new Thread(new Runnable() {
@Override
public void run() {
playerModel.getLogManager().sendLogs();
}
}).start();
// startPlaylistSaveTimer();
Log.d(TAG, "JukefoxApplication.onCreate() finished.");
}
public static void setIgnoreEventsTime(long time) {
ignoreEventsUntil = time;
}
public static WakeLockManager getWakeLockManager() {
return wakeLockManager;
}
public static Handler getHandler() {
return handler;
}
public static String getUniqueId() {
return uniqueId;
}
public static Context getAppContext() {
return appCtx;
}
/**
* TODO: should we make sure this function can only be called by some classes (views that are no activities?)
*
* @return the application object (singleton)
*/
public static JukefoxApplication getInstance() {
return instance;
}
@Override
public void onLowMemory() {
super.onLowMemory();
}
@Override
public void onTerminate() {
super.onTerminate();
if (intentReceiver != null) {
unregisterReceiver(intentReceiver);
}
collectionModel.onTerminate();
Log.v(TAG, "onTerminate()");
}
// swelten: I think the following 5 methods are not needed
// public IModelViewApplicationState getApplicationStateReader() {
// return model;
// }
// public IModelViewData getDataReader() {
// return model;
// }
//
// public ISettingsReader getSettingsReader() {
// return model.getSettingsReader();
// }
//
// public IModelControllerApplicationState getApplicationController() {
// return model;
// }
// public IModelControllerData getDataController() {
// return model;
// }
public JukefoxIntentReceiver getIntentReceiver() {
return intentReceiver;
}
public void setIntentReceiver(JukefoxIntentReceiver intentReceiver) {
this.intentReceiver = intentReceiver;
}
public Controller getController() {
return controller;
}
public static AndroidPlayerController getPlayerController() {
return playerController;
}
public static AndroidCollectionModelManager getCollectionModel() {
return collectionModel;
}
public static AndroidDirectoryManager getDirectoryManager() {
return directoryManager;
}
public static AbstractPlayerModelManager getPlayerModel() {
return playerModel;
}
private String generateUniqueDeviceInstallationId() {
String uniqueId;
try {
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// Compute a user id which has a first part that is unique for the
// device and one that is unique for the installation
String imei = tm.getDeviceId();
uniqueId = Integer.toString(imei.hashCode(), 16);
uniqueId = getPaddedId(uniqueId, 8);
imei = imei.substring(1, imei.length() - 1);
Integer imeiHash = imei.hashCode();
if (imeiHash == Integer.MIN_VALUE) {
imeiHash = imeiHash + 1;
}
Integer absHash = Math.abs(imeiHash);
uniqueId = uniqueId + getPaddedId(Integer.toString(absHash, 16), 8);
} catch (Exception e) {
Log.w(TAG, e);
uniqueId = "0000000000000000";
}
try {
ISettingsReader settingsReader = AndroidSettingsManager.getAndroidSettingsReader();
Long randomNr = settingsReader.getRandomUserHash();
if (randomNr == null) {
ISettingsEditor settingsEditor = AndroidSettingsManager.getAndroidSettingsEditor();
randomNr = Math.abs(random.nextLong());
if (randomNr < 0) {
randomNr = 0L;
}
settingsEditor.setRandomUserHash(randomNr);
}
uniqueId = uniqueId + getPaddedId(Long.toString(randomNr, 16), 16);
} catch (Exception e) {
Log.w(TAG, e);
}
Log.v(TAG, "Hash: " + uniqueId);
return uniqueId;
}
private String getPaddedId(String id, int len) {
StringBuilder sb = new StringBuilder();
int cnt = len - id.length();
for (int i = 0; i < cnt; i++) {
sb.append("0");
}
sb.append(id);
return sb.toString();
}
public static void setScreenOn(boolean b) {
screenOn = b;
}
public static boolean isScreenOn() {
return screenOn;
}
public static String getJukefoxVersion() {
try {
ComponentName comp = new ComponentName(appCtx, JukefoxApplication.class);
PackageInfo pinfo = appCtx.getPackageManager().getPackageInfo(comp.getPackageName(), 0);
return pinfo.versionName;
} catch (Exception e) {
Log.wtf(TAG, e);
return e.getMessage();
}
}
public static boolean ignoreMediaButtons() {
if (!AndroidUtils.isSdCardOk()) {
return true;
}
File f = directoryManager.getIgnoreMediaButtonsFile();
if (f.exists()) {
return true;
}
return false;
}
public static boolean isScreenLocked() {
if (keyguardManager != null) {
return keyguardManager.inKeyguardRestrictedInputMode();
}
return false;
}
public static void reregisterSensors() {
playerModel.getContextProvider().reregisterSensors();
}
public static JukefoxNotificationManager getNotificationManager() {
return notificationManager;
}
public void updateJukefoxIntentReceiver() {
JukefoxIntentReceiver.updateJukefoxIntentReceiver(this);
}
}