Skip to content

Commit

Permalink
-Fixed Ereza#8. Now the process is only used on API<17, and when rest…
Browse files Browse the repository at this point in the history
…arting the app, the error process is killed. This should avoid multiprocess issues.

-Updated gradle version and readme.
  • Loading branch information
Ereza committed Jul 31, 2015
1 parent 79d0254 commit 098ef37
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 10 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ This method allows you to set a custom error activity to be launched, instead of
Use it if you need further customization that is not just strings, colors or themes (see below).
If you don't set it (or set it to null), the library will use first activity on your manifest that has an intent-filter with action
cat.ereza.customactivityoncrash.ERROR, and if there is none, a default error activity from the library.
If you use this, the activity **must** be declared in your `AndroidManifest.xml`, with `process` set to `@string/customactivityoncrash_process`.

Example:
```xml
<activity
android:name="cat.ereza.sample.customactivityoncrash.activity.CustomErrorActivity"
android:label="@string/error_title"
android:process="@string/customactivityoncrash_process" />
```

As noted, you can also use the following intent-filter to specify the error activity:
```xml
Expand Down Expand Up @@ -154,6 +163,18 @@ CustomActivityOnCrash.getRestartActivityClassFromIntent(getIntent());
```
Returns the class of the activity you have to launch to restart the app, or null if not set.

```java
CustomActivityOnCrash.restartApplicationWithIntent(activity, intent);
```
Kills the current process and restarts the app again with an `startActivity()` to the passed intent.
You **MUST** call this to restart the app, or you will end up having several Application class instances and experience multiprocess issues in API<17.

```java
CustomActivityOnCrash.closeApplication(activity);
```
Closes the app and kills the current process.
You **MUST** call this to close the app, or you will end up having several Application class instances and experience multiprocess issues in API<17.

*The `sample` project module includes an example of a custom error activity. If in doubt, check the code in that module.*

## Using Proguard?
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.android.tools.build:gradle:1.3.0'
}
}

Expand Down
2 changes: 1 addition & 1 deletion library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<activity
android:name="cat.ereza.customactivityoncrash.activity.DefaultErrorActivity"
android:process=":error_activity"
android:process="@string/customactivityoncrash_process"
android:theme="@style/CustomActivityOnCrashTheme" />

</application>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
Expand Down Expand Up @@ -149,8 +150,7 @@ public void uncaughtException(Thread thread, final Throwable throwable) {
lastActivity.finish();
lastActivityCreated.clear();
}
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
killCurrentProcess();
}
});
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
Expand Down Expand Up @@ -279,6 +279,33 @@ public static Class<? extends Activity> getRestartActivityClassFromIntent(Intent
}
}

/**
* Given an Intent, restarts the app and launches a startActivity to that intent.
* Must only be used from your error activity.
*
* @param activity The current error activity. Must not be null.
* @param intent The Intent. Must not be null.
*/
public static void restartApplicationWithIntent(Activity activity, Intent intent) {
activity.finish();
activity.startActivity(intent);
if (isRunningOnErrorProcess(activity)) {
killCurrentProcess();
}
}

/**
* Closes the app. Must only be used from your error activity.
*
* @param activity The current error activity. Must not be null.
*/
public static void closeApplication(Activity activity) {
activity.finish();
if (isRunningOnErrorProcess(activity)) {
killCurrentProcess();
}
}


/// SETTERS AND GETTERS FOR THE CUSTOMIZABLE PROPERTIES

Expand Down Expand Up @@ -592,4 +619,37 @@ private static Class<? extends Activity> getErrorActivityClassWithIntentFilter(C

return null;
}

/**
* INTERNAL method used to know if the error activity is running on the error activity process.
* If you have implemented CustomActivityonCrash correctly, this should only be true on API<17.
*
* @param context A valid context. Must not be null.
* @return true if the current process is running on the error activity process, false otherwise.
*/
private static boolean isRunningOnErrorProcess(Context context) {
String currentProcName = "";
int pid = android.os.Process.myPid();
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
if (processInfo.pid == pid) {
currentProcName = processInfo.processName;
break;
}
}

String caocProcessName = context.getString(R.string.customactivityoncrash_process);

//We check for caocProcessName.startsWith(":") because if we don't, substring will crash when a process is specified but it's on API>=17
return (caocProcessName.startsWith(":") && currentProcName.contains(":") && currentProcName.split(":")[1].equals(caocProcessName.substring(1)));
}

/**
* INTERNAL method that kills the current process.
* It is used after restarting or killing the app.
*/
private static void killCurrentProcess() {
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,14 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onClick(View v) {
Intent intent = new Intent(DefaultErrorActivity.this, restartActivityClass);
finish();
startActivity(intent);
CustomActivityOnCrash.restartApplicationWithIntent(DefaultErrorActivity.this, intent);
}
});
} else {
restartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
CustomActivityOnCrash.closeApplication(DefaultErrorActivity.this);
}
});
}
Expand Down
19 changes: 19 additions & 0 deletions library/src/main/res/values-v17/internal_strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2015 Eduard Ereza Martínez
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~
~ You may obtain a copy of the License at
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<resources>
<string name="customactivityoncrash_process"></string>
</resources>
19 changes: 19 additions & 0 deletions library/src/main/res/values/internal_strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2015 Eduard Ereza Martínez
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~
~ You may obtain a copy of the License at
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<resources>
<string name="customactivityoncrash_process">:error_activity</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,14 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onClick(View v) {
Intent intent = new Intent(CustomErrorActivity.this, restartActivityClass);
finish();
startActivity(intent);
CustomActivityOnCrash.restartApplicationWithIntent(CustomErrorActivity.this, intent);
}
});
} else {
restartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
CustomActivityOnCrash.closeApplication(CustomErrorActivity.this);
}
});
}
Expand Down

0 comments on commit 098ef37

Please sign in to comment.