I've been trying to implement an custom UncaughtExceptionHandler into my application and I've discovered the library Ereza/CustomActivityOnCrash.
I have added all the code as described in the README (https://github.com/Ereza/CustomActivityOnCrash) but I still can't seem to get it to work. When I force my app to crash, a white screen pops up and then immediately disappears.
Any ideas what might be causing this? below is some of my code
AndroidManifest
<activity
android:name="com.test.SplashActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.test.MainActivity"
android:label="MainActivity"
android:screenOrientation="portrait"
android:theme="#style/AppTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="cat.ereza.customactivityoncrash.RESTART" />
</intent-filter>
</activity>
<activity
android:name="com.test.ErrorActivity"
android:label="Error"
android:screenOrientation="portrait"
android:theme="#style/AppTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="cat.ereza.customactivityoncrash.ERROR" />
</intent-filter>
</activity>
Application class
public class TestApplication extends Application {
private static TestApplication mInstance;
private TimeZone usersDefaultTimeZone;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
//Customization for CustomActivityOnCrash
//Show (TRUE) or Hide (FALSE) the stack trace on the error activity
CustomActivityOnCrash.setShowErrorDetails(false);
//Enable Restart (TRUE) 'Restart App' button
//Disable Restart (FALSE) 'Close App' button
CustomActivityOnCrash.setEnableAppRestart(true);
//This sets a custom error activity class instead of the default one.
CustomActivityOnCrash.setErrorActivityClass(ErrorActivity.class);
//This sets a EventListener to be notified of events regarding the error activity,
//CustomActivityOnCrash.setEventListener(new CustomEventListener());
//Specify the Activity to to restart the application
CustomActivityOnCrash.setRestartActivityClass(MainActivity.class);
//Install CustomActivityOnCrash
CustomActivityOnCrash.install(this);
//Now initialize your error handlers as normal
Fabric.with(this, new Crashlytics());
}
public static synchronized TestApplication getInstance() {
return mInstance;
}
static class CustomEventListener implements CustomActivityOnCrash.EventListener{
#Override
public void onLaunchErrorActivity() {
Log.i("BookingApp", "onLaunchErrorActivity()");
Crashlytics.logException(new Exception("Unknown Exception Caught & Error screen displayed to user"));
}
#Override
public void onRestartAppFromErrorActivity() {
Log.i("BookingApp", "onRestartAppFromErrorActivity()");
Answers.getInstance().logCustom(new CustomEvent("Restart After Crash"));
}
#Override
public void onCloseAppFromErrorActivity() {
Log.i("BookingApp", "onCloseAppFromErrorActivity()");
Answers.getInstance().logCustom(new CustomEvent("Close After Crash"));
}
}
}
Hi put following code in Application class and modify as you want for handeling unhandled exceptions:
#Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e);
}
});
}
public void handleUncaughtException(Thread thread, Throwable e) {
e.printStackTrace(); // not all Android versions will print the stack trace automatically
//Work what you want to do....
//start new activity with clearing task
Intent intent = new Intent(this, ActivityClass.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
//end
System.exit(2); // kill off the crashed app
}
Hope this help, I am using in my app... works.
After some more investigation I discovered that this library/code doesn't like being run in debug mode. If I installed the application on my device and launched it from there (rather than using Debug from Android Studio), it seemed to work fine.
This is most likely caused by the ErrorActivity not being specified as part of another process.
From the library documentation, regarding the usage of a custom error activity:
If you use this, the activity must be declared in your AndroidManifest.xml, with process set to :error_activity.
Related
I'm learning how to handle OneSignal Push Notifications on Android devices. The problem is, while the application is closed, when I receive a notification, even though I defined the neccessary functions (I guess) it still opens the "Splash Activity", which is defined as MAIN LAUNCHER in manifest. I need to open a different activity with the payload data in it. The link I've referenced from creating these codes is this and I've seen the reference on this answer. I'm only showing the relevant code since this project is classified.
Here is my Manifest file.
<application
android:name="packageName.CustomAppName"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT"
android:value="DISABLED"/>
<activity
android:name="anotherPackageName.SplashActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="anotherPackageName.PaymentActivity"
android:screenOrientation="portrait" />
<service
android:name="somepackagename.NotificationsForPayment"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE">
<intent-filter>
<action android:name="com.onesignal.NotificationExtender" />
</intent-filter>
</service>
</application>
Here is my application class where I define OneSignal service.
public class CustomAppName extends Application {
private static CustomAppName instance;
public static CustomAppName getInstance() {
return instance;
}
public void onCreate() {
super.onCreate();
OneSignal.startInit(this)
.setNotificationOpenedHandler(new CustomNotificationOpening())
.init();
instance = this;
}
}
Here is my CustomNotificationOpening class.
public class CustomNotificationOpening implements OneSignal.NotificationOpenedHandler {
#Override
public void notificationOpened(OSNotificationOpenResult notification) {
notification.notification.payload.additionalData.names();
JSONObject data = notification.notification.payload.additionalData;
Intent intent = new Intent(CustomAppName.getInstance(), PaymentActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("paymentModel", data);
CustomAppName.getInstance().startActivity(intent);
}
And here is my NotificationsForPayment class which extends from NotificationExtenderService.
public class NotificationsForPayment extends NotificationExtenderService {
#Override
protected boolean onNotificationProcessing(OSNotificationReceivedResult notification) {
NotificationExtenderService.OverrideSettings overrideSettings = new NotificationExtenderService.OverrideSettings();
overrideSettings.extender = new NotificationCompat.Extender() {
#Override
public NotificationCompat.Builder extend(NotificationCompat.Builder builder) {
// Sets the background notification color to Red on Android 5.0+ devices.
Bitmap icon = BitmapFactory.decodeResource(CustomAppName.getInstance().getResources(),
R.drawable.ic_os_notification_fallback_white_24dp);
builder.setLargeIcon(icon);
return builder.setColor(new BigInteger("FF0000FF", 16).intValue());
}
};
OSNotificationDisplayedResult displayedResult = displayNotification(overrideSettings);
}
I don't really know where I'm doing wrong. While the application is open, when I click the notification I can see that "notificationOpened" function is firing. But when it's closed, since I can't debug the program and the notification opens the splash activity, I knew the time for me was to ask this question because none of the answers I've found worked. Is there any way to open the other activity with specific data from the notification while the application was closed? Any help is appreciated, thank you so much.
Found where the error was.
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT"
android:value="DISABLED"/>
The value was supposed to be "DISABLE", not "DISABLED".
so, the updated code is:-
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT"
android:value="DISABLE"/>
I am trying to achieve following case on Android, but no success:
1) Launch Application (Launcher Activity which is a subclass of Base Activity). The Base Activity has code as follows:
///This is in BaseActivity
#Override
public void onCreate(Bundle instance)
{
super.onCreate(instance);
//Config.isLoggedIn() is a static function.
if(! Config.isLoggedIn())
{
////Config.startLoginActivity is a static function
Config.startLoginActivity(this, getIntent());
finish();
}
}
The Config.startLoginActivity functions is defined as
public static void startLoginActivity(final Context ctx, final Intent finishIntent)
{
Intent i = new Intent(ctx, ItemListActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("FINISH_INTENT", finishIntent);
ctx.startActivity(i);
}
Now, the ItemListActivity contains a list of Items as {Item1, Item2, Item3}. In ItemListActivity, I am saving the passed "finishIntent" as
///This is ItemListActivity onCreate Method
if(getIntent().hasExtra("FINISH_INTENT"))
mFinishIntent = getIntent().getParcelableExtra("FINISH_INTENT");
and the onItemListSelected method is described as follows :
#Override
public void onItemSelected(String id) {
Config.setLogInState(true);
if(mFinishIntent != null)
{
Log.i("ITEMLISTACTIVITY", "Class Name = " + mFinishIntent.getClass().getName());
Log.i("ITEMLISTACTIVITY", "Starting mFinishIntent Activity");
startActivity(mFinishIntent);
finish();
}
}
But the issue is the Main Activity is not being launched again, Android takes me to the home screen instead. While looking for a solution, I saw that Google I/O app has the same implementation and that works flawlessly but in my case it is not. I am unable to figure it out. Please help.
Thanks in Advance.
Manifest File is as follows :
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.app.myapplication.ItemListActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.app.myapplication.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Ok Here is a quick help which works for 100 percent which I'm using not mostly but EVERYTIME! you must past it through intent and in your case here it is how it must look like.
Intent intent = new intent(//name of your activity in which you are at the moment.this, //name of activity to which you want to go.class);
startActivity(intent);
Hope this will help
I want to consume an IntentService for my app to laod data from server in the background thread without intracting with or disturbing application activities.
here is my simple IntentService
public class SearchService extends IntentService {
public SearchService() {
super("SearchService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("Tag","service started");
}
}
i start this service in the main Activity of my application
public class ChannelsActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this , SearchService.class);
startService(intent);
}
I also define service attribute in manifest file but it does't work for me i don't know what is the problem
<application
<activity
android:name=".ChannelsActivity"
android:screenOrientation="landscape"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".SearchService"/>
</application>
I am stuck with this problem any help will really helpful for me.
The code you have posted should work. Do you see the debug log "service started" in the logcat window? Although it sounds stupid, the SearchService will run and immediately will shut down because there is no extensive work to do and you will not see the Service in Running Services if that is your goal.
Hope it helps.
This is an example of splash screen but facing difficulty with it as I couldn't view my MainActivity class, couldn't be able to recognize the issue.Tried in manifest file by changing the action and the category name as well but could not be able to resolve to it.
Basically changed my Intent intent = new Intent(); as well but still the same goes on.
public class SplashActivity extends Activity
{
MediaPlayer player;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
player = MediaPlayer.create(SplashActivity.this, R.raw.splash);
player.start();
Thread timer = new Thread()
{
#Override
public void run()
{
try
{
sleep(4000);
}catch(InterruptedException e)
{
e.printStackTrace();
}
finish();
Intent intent = new Intent();
intent.setClass(SplashActivity.this, MainActivity.class);
startActivity(intent);
stop();
}
};
timer.start();
}
#Override
protected void onPause()
{
super.onPause();
player.release();
finish();
}
}
====>And here is my manifest file --
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mainsplashcreen"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="#drawable/android_splash"
android:label="#string/app_name" >
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".SplashActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I would guess, that your problem is, that you finish your activity before you start the new one. If you call finish() on your activity, it will be destroyed, and so the startActivity() won't be called anymore (or if it will be called, it won't get a valid context anymore). So try to move the finish() method, at the end of your run method, that should solve the problem.
Another Very Short,Simple and Effective way of Implementing Flash Screen is as below:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Handler handler=new Handler();
Runnable gotoMain=new Runnable() {
public void run()
{
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}
};
handler.postDelayed(gotoMain, 4000);
}
You just Replace you OnCreate Method with this one.
There are a few things which you should take care of:
1. The usage of stop() and the place it is being used are not encouraged. Besides being deprecated, it will also give you UnsupportedOperationExcecption.
2. Is your MediaPlayer being initialized correctly without any errors? Check the logs.
3. What is the reason you are using finish() in onPause() method? It is not recommended.
4. You are assigning MAIN action to both your activities. While it is allowed, it should be for a specific reason.
However, all these things should not avoid your application to go to the main activity. There may be the reasons with your main activity code.
I have an activity that starts the system browser via Intent. Short before it does that I do a HTTP GET to some other URL. This GET will be answered as soon as the user finishes his task in the browser (logging in using OAuth).
I'd like to be able to close down the browser and / or get my application's activity back to the front.
I do not want to use a WebView because I'd like to avoid the perception that I might be trying to spy on passwords.
Any idea how to solve this? Is it possible at all?
Thanks a bunch!
Daniel
Make sure OAuth opens up URL which is something like yourapp://success
Next you add a intent filter to handle this custom protocol and address. More details are at http://developer.android.com/guide/topics/intents/intents-filters.html#ifs
Here's what did the trick in my project.
The application manifest is pretty standard:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Here's a code snippet of the background thread that sends the intent to re-show the activity:
public class AlarmThread extends Thread {
private int mSleepTime;
public AlarmThread(int sleepSeconds) {
super("AlarmThread");
mSleepTime = sleepSeconds * 1000;
}
#Override
public void run() {
Log.i("thread", "started sleeping for " + mSleepTime + " milliseconds");
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException e) {
// ignored
}
Log.i("thread", "creating intent to bring activity to foreground");
Intent intent = new Intent(MainActivity.getContext(), MainActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainActivity.getContext().getApplicationContext().startActivity(intent);
}
}
Note that the trick is in the MainActivity.getContext().getApplicationContext().startActivity(intent); part (last line above).
In the MainActivity, I added the getContext method:
public static Context getContext() {
return mInstance;
}
And the member 'mInstance' is set in the 'onCreate':
private static MainActivity mInstance = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Other code....
mInstance = this;
}