package com.nolanlawson.apptracker; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import com.nolanlawson.apptracker.db.AppHistoryDbHelper; import com.nolanlawson.apptracker.helper.PreferenceHelper; import com.nolanlawson.apptracker.helper.ServiceHelper; import com.nolanlawson.apptracker.util.UtilLogger; public class AppTrackerWidgetProvider extends AppWidgetProvider { private static UtilLogger log = new UtilLogger( AppTrackerWidgetProvider.class); public static String ACTION_UPDATE_PAGE_FORWARD = "com.nolanlawson.apptracker.action.PAGE_UPDATE_FORWARD"; public static String ACTION_UPDATE_PAGE_BACK = "com.nolanlawson.apptracker.action.PAGE_UPDATE_BACK"; public static String ACTION_RESTART_SERVICE = "com.nolanlawson.apptracker.action.RESTART_SERVICE"; public static final String URI_SCHEME = "app_tracker_widget"; @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); log.d("deleting appWidgetIds: %s", appWidgetIds); for (int appWidgetId : appWidgetIds) { PreferenceHelper.deletePreferences(context, appWidgetId); } log.d("onDeleted()"); } @Override public void onDisabled(Context context) { super.onDisabled(context); log.d("onDisabled()"); } @Override public void onEnabled(Context context) { super.onEnabled(context); log.d("onEnabled()"); ServiceHelper.startBackgroundServiceIfNotAlreadyRunning(context); } @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); log.d("onReceive(); intent is: %s",intent); ServiceHelper.startBackgroundServiceIfNotAlreadyRunning(context); // did the user click the button to update the widget? if (ACTION_UPDATE_PAGE_FORWARD.equals(intent.getAction()) || ACTION_UPDATE_PAGE_BACK.equals(intent.getAction())) { int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); int newPageNumber = intent.getIntExtra(WidgetUpdater.NEW_PAGE_NUMBER, 0); PreferenceHelper.setCurrentPageNumber(context, newPageNumber, appWidgetId); log.d("moving to new page for appWidgetId %d; pageNumber is now %d", appWidgetId, newPageNumber); updateWidget(context, appWidgetId); } else if (ACTION_RESTART_SERVICE.equals(intent.getAction())) { log.d("Simply restarted the service, because it was killed"); } else if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { log.d("package change event: %s", intent); if (intent.getData() != null) { String packageName = intent.getData().getEncodedSchemeSpecificPart(); clearIconAndLabel(context, packageName); if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { // have to add a dummy entry in case it gets updated - stupid // android market removes and then installs apps so you can't tell // that they're being RE-installed packageRemoveEvent(context, packageName); } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) { packageInstallEvent(context, packageName); } else if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) { packageReplaceEvent(context, packageName); } } updateWidget(context); } } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); log.d("onUpdate() for appWidgetIds %s", appWidgetIds); log.d("appWidgetIds are %s", appWidgetIds); ServiceHelper.startBackgroundServiceIfNotAlreadyRunning(context); doPeriodicUpdate(context); AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); WidgetUpdater.updateWidget(context, dbHelper); dbHelper.close(); } private void packageRemoveEvent(Context context, String packageName) { log.d("package removed: %s", packageName); // package has been removed AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); synchronized (AppHistoryDbHelper.class) { dbHelper.addEmptyPackageStubIfNotExists(packageName); } dbHelper.close(); } private void packageReplaceEvent(Context context, String packageName) { log.d("package reinstalled: %s", packageName); // package has been reinstalled AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); synchronized (AppHistoryDbHelper.class) { dbHelper.updateUpdateDate(packageName, System.currentTimeMillis()); } dbHelper.close(); updateActivityLog(context, packageName); } private void packageInstallEvent(Context context, String packageName) { log.d("new package installed: %s", packageName); // new package installed! make a note of this date AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); synchronized (AppHistoryDbHelper.class) { dbHelper.updateInstallDate(packageName, System.currentTimeMillis()); } dbHelper.close(); updateActivityLog(context, packageName); } private void updateActivityLog(Context context, String packageName) { PackageManager packageManager = context.getPackageManager(); Intent launchIntent = null; try { launchIntent = packageManager.getLaunchIntentForPackage(packageName); } catch (Exception ex) { log.w(ex, "package name not found: %s", packageName); } log.d("launchIntent is %s", launchIntent); if (launchIntent == null) { log.w("launchIntent is null - maybe this package doesn't have one?: package %s", packageName); return; } ComponentName componentName = launchIntent.getComponent(); log.d("componentName is '%s' / '%s'", componentName.getPackageName(), componentName.getShortClassName()); AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); synchronized (AppHistoryDbHelper.class) { dbHelper.addEmptyPackageAndProcessIfNotExists(componentName.getPackageName(), componentName.getShortClassName()); } dbHelper.close(); } private void clearIconAndLabel(Context context, String packageName) { log.d("Package was changed; need to clear labels and icon for: %s", packageName); AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); try { synchronized (AppHistoryDbHelper.class) { dbHelper.clearIconAndLabel(packageName); } } finally { dbHelper.close(); } } private static void updateWidget(final Context context) { AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); WidgetUpdater.updateWidget(context, dbHelper); dbHelper.close(); } private static void updateWidget(final Context context, final int appWidgetId) { AppHistoryDbHelper dbHelper = new AppHistoryDbHelper(context); WidgetUpdater.updateWidget(context, dbHelper, appWidgetId); dbHelper.close(); } /* * update all app widget ids in the background */ private static void doPeriodicUpdate(final Context context) { if (!ServiceHelper.checkIfUpdateAppStatsServiceIsRunning(context)) { Intent intent = new Intent(context, UpdateAppStatsService.class); context.startService(intent); } } }