diff --git a/app/build.gradle b/app/build.gradle index c980eeb..b6e7b8f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { applicationId 'com.ryansteckler.nlpunbounce' minSdkVersion 16 targetSdkVersion 20 - versionCode 38 - versionName '2.0.2' + versionCode 40 + versionName '2.0.3' } buildTypes { release { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 77bb95a..61de21a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,7 +34,9 @@ + + diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java b/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java index fd8d4c0..154a4dc 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java @@ -25,6 +25,7 @@ public class ActivityReceiver extends BroadcastReceiver { public static final String STATS_REFRESHED_ACTION = "com.ryansteckler.nlpunbounce.STATS_REFRESHED_ACTION"; public static final String CREATE_FILES_ACTION = "com.ryansteckler.nlpunbounce.CREATE_FILES_ACTION"; + public static final String RESET_FILES_ACTION = "com.ryansteckler.nlpunbounce.RESET_FILES_ACTION"; public static final String PUSH_NETWORK_STATS = "com.ryansteckler.nlpunbounce.PUSH_NETWORK_STATS"; public ActivityReceiver() { @@ -35,6 +36,8 @@ public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(CREATE_FILES_ACTION)) { UnbounceStatsCollection.getInstance().createFiles(context); + } else if (action.equals(RESET_FILES_ACTION)) { + UnbounceStatsCollection.getInstance().recreateFiles(context); } else if (action.equals(PUSH_NETWORK_STATS)) { UnbounceStatsCollection.getInstance().pushStatsToNetworkInternal(context); } diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java index 23803c1..b39fa05 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java @@ -46,6 +46,7 @@ import com.ryansteckler.nlpunbounce.helpers.RootHelper; import com.ryansteckler.nlpunbounce.helpers.SettingsHelper; import com.ryansteckler.nlpunbounce.helpers.ThemeHelper; +import com.ryansteckler.nlpunbounce.hooks.Wakelocks; import com.ryansteckler.nlpunbounce.models.UnbounceStatsCollection; @@ -64,9 +65,10 @@ public class HomeFragment extends Fragment { private int mSetupFailureStep = SETUP_FAILURE_NONE; //We're optimists :) private final static int SETUP_FAILURE_NONE = 0; //We're good. The service is running. private final static int SETUP_FAILURE_SERVICE = 1; //The service isn't running, but Xposed is installed. - private final static int SETUP_FAILURE_XPOSED_RUNNING = 2; //Xposed isn't running ("installed") - private final static int SETUP_FAILURE_XPOSED_INSTALL = 3; //Xposed isn't installed - private final static int SETUP_FAILURE_ROOT = 4; //There's no root access. + private final static int SETUP_FAILURE_VERSION = 2; //The service isn't running, but Xposed is installed. + private final static int SETUP_FAILURE_XPOSED_RUNNING = 3; //Xposed isn't running ("installed") + private final static int SETUP_FAILURE_XPOSED_INSTALL = 4; //Xposed isn't installed + private final static int SETUP_FAILURE_ROOT = 5; //There's no root access. /** @@ -88,6 +90,20 @@ public void onCreate(Bundle savedInstanceState) { ThemeHelper.onActivityCreateSetTheme(this.getActivity()); setHasOptionsMenu(true); + SharedPreferences prefs = getActivity().getSharedPreferences("com.ryansteckler.nlpunbounce" + "_preferences", Context.MODE_WORLD_READABLE); + String lastVersion = prefs.getString("file_version", "0"); + if (!lastVersion.equals(Wakelocks.FILE_VERSION)) { + //Reset stats + UnbounceStatsCollection.getInstance().recreateFiles(getActivity()); + Intent intent = new Intent(XposedReceiver.RESET_ACTION); + intent.putExtra(XposedReceiver.STAT_TYPE, UnbounceStatsCollection.STAT_CURRENT); + try { + getActivity().sendBroadcast(intent); + } catch (IllegalStateException ise) { + + } + + } } @Override @@ -129,21 +145,24 @@ private void handleSetup(final View view) { final SharedPreferences prefs = getActivity().getSharedPreferences("com.ryansteckler.nlpunbounce" + "_preferences", Context.MODE_WORLD_READABLE); boolean firstRun = prefs.getBoolean("first_launch", true); - if (!isUnbounceServiceRunning() || firstRun) { + if (!getAmplifyKernelVersion().equals(Wakelocks.VERSION) || firstRun) { //Show the banner final LinearLayout banner = (LinearLayout)view.findViewById(R.id.banner); banner.setVisibility(View.VISIBLE); //Let's find out why the service isn't running: - if (!isUnbounceServiceRunning()) { - mSetupFailureStep = SETUP_FAILURE_SERVICE; - if (!isXposedRunning()) { - mSetupFailureStep = SETUP_FAILURE_XPOSED_RUNNING; - if (!isXposedInstalled()) { - mSetupFailureStep = SETUP_FAILURE_XPOSED_INSTALL; - if (!RootHelper.isDeviceRooted()) { - mSetupFailureStep = SETUP_FAILURE_ROOT; + if (!getAmplifyKernelVersion().equals(Wakelocks.VERSION)) { + mSetupFailureStep = SETUP_FAILURE_VERSION; + if (!isUnbounceServiceRunning()) { + mSetupFailureStep = SETUP_FAILURE_SERVICE; + if (!isXposedRunning()) { + mSetupFailureStep = SETUP_FAILURE_XPOSED_RUNNING; + if (!isXposedInstalled()) { + mSetupFailureStep = SETUP_FAILURE_XPOSED_INSTALL; + if (!RootHelper.isDeviceRooted()) { + mSetupFailureStep = SETUP_FAILURE_ROOT; + } } } } @@ -271,6 +290,9 @@ public void onClick(View view) { } else if (mSetupFailureStep == SETUP_FAILURE_SERVICE) { //Service isn't running handleServiceFailure(problemText, nextButtonText, nextButton); + } else if (mSetupFailureStep == SETUP_FAILURE_VERSION) { + //Service is the wrong version + handleVersionFailure(problemText, nextButtonText, nextButton); } else if (mSetupFailureStep == SETUP_FAILURE_XPOSED_RUNNING) { //Xposed isn't running handleXposedRunningFailure(problemText, nextButtonText, nextButton); @@ -392,6 +414,19 @@ public void onClick(View view) { }); } + private void handleVersionFailure(TextView problemText, TextView nextButtonText, LinearLayout nextButton) { + nextButtonText.setText(getActivity().getResources().getString(R.string.welcome_banner_button_fixit)); + String errorText = getResources().getString(R.string.welcome_banner_problem_version); + problemText.setText(Html.fromHtml(errorText)); + problemText.setMovementMethod(LinkMovementMethod.getInstance()); + nextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + getActivity().finish(); + } + }); + } + private void handleServiceFailure(TextView problemText, TextView nextButtonText, LinearLayout nextButton) { nextButtonText.setText(getActivity().getResources().getString(R.string.welcome_banner_button_fixit)); String errorText = getResources().getString(R.string.welcome_banner_problem_service); @@ -858,6 +893,13 @@ public boolean isUnbounceServiceRunning() { return false; } + public String getAmplifyKernelVersion() { + //The Unbounce hook changes this to true. + return "0"; + } + + + public boolean isXposedRunning() { return new File("/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar").exists(); } diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java b/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java index c0975e4..55e3f2e 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java @@ -37,7 +37,8 @@ public class Wakelocks implements IXposedHookLoadPackage { private static final String TAG = "Amplify: "; - private static final String VERSION = "2.0.2"; //This needs to be pulled from the manifest or gradle build. + public static final String VERSION = "2.0.3"; //This needs to be pulled from the manifest or gradle build. + public static final String FILE_VERSION = "2"; //This needs to be pulled from the manifest or gradle build. private HashMap mLastWakelockAttempts = null; //The last time each wakelock was allowed. private HashMap mLastAlarmAttempts = null; //The last time each alarm was allowed. // private HashMap mLastServiceAttempts = null; //The last time each wakelock was allowed. @@ -73,11 +74,28 @@ public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { hookAlarms(lpparam); hookWakeLocks(lpparam); hookServices(lpparam); + resetFilesIfNeeded(null); } else if (lpparam.packageName.equals("com.ryansteckler.nlpunbounce")) { hookAmplifyClasses(lpparam); } } + private void resetFilesIfNeeded(Context context) { + //Get the version number and compare it to our app version. + String lastVersion = m_prefs.getString("file_version", "0"); + if (!lastVersion.equals(FILE_VERSION)) { + //Reset stats + defaultLog("Resetting stat files on version upgrade."); + if (context != null) { + Intent intent = new Intent(ActivityReceiver.CREATE_FILES_ACTION); + try { + context.sendBroadcast(intent); + } catch (IllegalStateException ise) { + } + } + UnbounceStatsCollection.getInstance().resetLocalStats(UnbounceStatsCollection.STAT_CURRENT); + } + } private void hookAmplifyClasses(LoadPackageParam lpparam) { findAndHookMethod("com.ryansteckler.nlpunbounce.HomeFragment", lpparam.classLoader, "isUnbounceServiceRunning", new XC_MethodHook() { @Override @@ -85,6 +103,13 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.setResult(true); } }); + findAndHookMethod("com.ryansteckler.nlpunbounce.HomeFragment", lpparam.classLoader, "getAmplifyKernelVersion", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + param.setResult(VERSION); + } + }); + } private void setupReceiver(XC_MethodHook.MethodHookParam param) { @@ -448,6 +473,8 @@ private void updateStatsIfNeeded(Context context) { long timeSinceLastUpdateStats = now - mLastUpdateStats; if (timeSinceLastUpdateStats > mUpdateStatsFrequency) { + resetFilesIfNeeded(context); + if (!UnbounceStatsCollection.getInstance().saveNow(context)) { //Request the activity to create the files. Intent intent = new Intent(ActivityReceiver.CREATE_FILES_ACTION); diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java b/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java index 2942b94..369f585 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java @@ -16,6 +16,7 @@ import com.ryansteckler.nlpunbounce.ActivityReceiver; import com.ryansteckler.nlpunbounce.XposedReceiver; import com.ryansteckler.nlpunbounce.helpers.NetworkHelper; +import com.ryansteckler.nlpunbounce.hooks.Wakelocks; import java.io.File; import java.io.FileInputStream; @@ -73,6 +74,7 @@ public static UnbounceStatsCollection getInstance() } private UnbounceStatsCollection() { + mRunningSince = System.currentTimeMillis(); } public Long getRunningSince() { @@ -80,7 +82,7 @@ public Long getRunningSince() { } public String getRunningSinceFormatted() { - long now = SystemClock.elapsedRealtime(); + long now = System.currentTimeMillis(); long running = now - mRunningSince; long years = TimeUnit.MILLISECONDS.toDays(running) / 365; @@ -577,7 +579,7 @@ public void resetStats(Context context, int statType) { if (statType == STAT_CURRENT) { mCurrentStats.clear(); - mRunningSince = SystemClock.elapsedRealtime(); + mRunningSince = System.currentTimeMillis(); clearStatFile(context, STATS_FILENAME_CURRENT); } else if (statType == STAT_PUSH) { @@ -589,8 +591,9 @@ else if (statType == STAT_PUSH) { public void resetLocalStats(int statType) { if (statType == STAT_CURRENT) { + mCurrentStats.clear(); - mRunningSince = SystemClock.elapsedRealtime(); + mRunningSince = System.currentTimeMillis(); } else if (statType == STAT_PUSH) { mSincePushStats.clear(); @@ -643,6 +646,7 @@ private void clearStatFile(Context context, String filename) { } public boolean saveNow(Context context) { + if (!saveStatsToFile(STATS_FILENAME_CURRENT, mCurrentStats)) { return false; } @@ -820,6 +824,14 @@ public void refreshPrefs(XSharedPreferences prefs) { mGlobalParticipation = prefs.getBoolean("global_participation", true); } + public void recreateFiles(Context context) { + Log.d("Amplify: ", "Removing file: " + STATS_DIRECTORY + STATS_FILENAME_CURRENT); + new File(STATS_DIRECTORY + STATS_FILENAME_CURRENT).delete(); + new File(STATS_DIRECTORY + STATS_FILENAME_GLOBAL).delete(); + new File(STATS_DIRECTORY + STATS_FILENAME_PUSH).delete(); + createFiles(context); + } + public void createFiles(Context context) { try { if (!new File(STATS_DIRECTORY + STATS_FILENAME_CURRENT).exists()) { @@ -843,6 +855,11 @@ public void createFiles(Context context) { } catch (IOException e) { e.printStackTrace(); } - + Log.d("Amplify: ", "Writing creation version"); + SharedPreferences prefs = context.getSharedPreferences("com.ryansteckler.nlpunbounce" + "_preferences", Context.MODE_WORLD_READABLE); + SharedPreferences.Editor edit = prefs.edit(); + edit.putString("file_version", Wakelocks.FILE_VERSION); + edit.apply(); + mRunningSince = System.currentTimeMillis(); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2a87c78..6c08127 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -161,9 +161,9 @@ May you have a long [battery] life! "Something went wrong. Let's find out what and get it fixed..." "We've setup some battery saving defaults for you. Enjoy your new battery life!" "It looks like you haven't enabled the Amplify module. Click \"FIX IT\", make sure Amplify is checked, then reboot." +"It looks like you just upgraded Amplify but haven't rebooted yet. Click \"FIX IT\", then reboot." "Xposed isn't running. Click \"FIX IT\", then click \"Install/Update\" and reboot your device." -"Xposed isn't installed. Xposed is required for Amplify and many other root applications. Once the download is finished, click INSTALL, then launch Amplify again. -If you'd like to learn more about Xposed, visit %1$s." +"Xposed isn't installed. Xposed is required for Amplify and many other root applications. Once the download is finished, click INSTALL, then launch Amplify again. If you'd like to learn more about Xposed, visit %1$s." "It looks like your device isn't rooted. Amplify requires a rooted device to function properly. If you're interested in rooting your device, please visit %1$s." "NEXT" "FIX IT" diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index a8de8db..2744312 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -62,7 +62,7 @@ android:key="about_author" android:editable="false" android:defaultValue="0" - android:summary="Version: 2.0.2" + android:summary="Version: 2.0.3" />