Application abnormal behavior does not start activity mentioned in intent - android

I have 3 major class in the application
1) Intent service: where I receive push notification and open activity according to notification message and other two classes behavior. below is the code which does that
if(Global.isMainScreenRunning){
Intent intent = new Intent(this, MainScreen.class);
intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else if(!Global.NotificationScreenRunning){
Intent intent = new Intent(this, NotificationScreen.class);
intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
2) NotificationScreen : This is the mediator screen so if the application is not running this screen will be shown first and on click of yes button of this screen MainScreen will be opened and this screen will be finished.
3) Main screen: This is the main screen of the application which show map. its core behavior is that ts a launchmode="singletask" mentioned in menifest file, which means if this screen is running its hole data will be sent to onNewIntent() method rather than opening this screen again.
Now what is happening in flow is
Step 1: application is in background and push notification comes. condition run and the second condition gets success and notification screen intent is shot
step 2: In notification screen I click on ye button to move on to the next main screen
step 3: In Main screen I process this info and perform task or just close the application
Step 4: again a new notification is received and as the application is not running is goes to second condition and start the intent for notification screen but this time no notification screen is launched instead of providing its intent and main screen is launched which is wrong.
This is the abnormal behavior which I am facing that instead of providing class of notification screen for intent main screen is launched which is totally different behavior of application according to android.
Any help from any one who come across such problem will be greatly appreciated.
Edit
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.front" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.microphone" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.app.permission.C2D_MESSAGE" />
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true" />
<application
android:allowBackup="true"
android:icon="#drawable/android_app_icon"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".SplashScreen"
android:configChanges="keyboardHidden|orientation"
android:label="#string/app_name"
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=".MainScreen"
android:configChanges="keyboardHidden|orientation"
android:launchMode="singleTask"
android:excludeFromRecents="true"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".NotificationScreen"
android:configChanges="keyboardHidden|orientation"
android:excludeFromRecents="true"
android:screenOrientation="portrait" >
</activity>
<receiver
android:name=".pushnotification.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.selebrety.app" />
</intent-filter>
</receiver>
<service android:name=".pushnotification.GcmIntentService" />
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
Second Edit
The mobile in which I am testing is "YU Yureka" here is its specification link. Current it have android 5.0.2 OS
Third Edit
To test this behavior I have debugged the code from eclipse debugger. To check this I have put a break point in NotificationScreen onResume and onCreate but it was never hit instead of onResume of MainScreen is hit.
Also I added a logs in if and else condition but still logs for else condition is printed.
Fourth Edit
Global.isMainScreenRunning: is global boolean variable which is done false in onPause of MainScreen and done true in onResume of MainScreen.
Global.NotificationScreenRunning: is global boolean variable which is done false in onPause of NotificationScreen and done true in onResume of NotificationScreen.

Global state is evil, and this question demonstrates why. To understand what's happening, you'll have to look at every place where your global flags are set or cleared, and analyze all the possible execution paths that might lead there. That's way beyond the scope of the kind of help you can get on SO. And there's an extra complication on Android, since the entire VM might be destroyed (and all your globals cleared) any time your app is in the background. Just as bad, the VM and the Application instance might be retained after you exit the last activity. When that happens, Application#onCreate(...) will not be called again the next time you start the app, and all your static globals will still be set to whatever they were when you last ran the app.
Save yourself a lot of hair-pulling and stop using global state.

You can try add android:taskAffinity=":main" to your MainScreen activity in manifest.
Maybe because the MainScreen still in a same task with the NotificationScreen so it's was call up all the task when NotificationScreen called again.
You can try this demo for more visual:
play app and code
Hope it help.

As I got your point you want to resume Notification Screen every time when you get notification in the app.For this I can suggest a solution this will make the application runs and allows you to achieve expected behavior but when you press home button your Main screen will no longer active.It will be killed.As we all know android maintains activity stacks for all acticities.So if you press device back button then activity will be poped out from stack and you will not face this problem.
I think this is a standard behavior of activity stacks for more information you can go with this link:
http://www.slideshare.net/RanNachmany/manipulating-android-tasks-and-back-stack
You can try this code snippet:
Intent i = new Intent(NotificationFullScreen.this,
MainActivity.class);
i.putExtra("FROM", "Notification");
i.putExtra("bookingId", bookingId);
i.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_FROM_BACKGROUND);
startActivity(i);
NotificationFullScreen.this.finish();

Hi #Abhinbav Singh Maurya
I think the problem is that main screen is getting called from your splash screen declared in the manifest as the application launch screen, so when the app is killed and you are calling the intent this will get called.
Instead of that what can you do is broadcast the message to the splash screen and receive it in splash screen and based on condition call the intent from there.
Again here there is a thing that you should take care of, you have to broad cast the intent only after the receiver is registered in the SplahScreen, else it will never be received. so try to user handler.postDelayed method and broadcast after 1000 ms or 700 ms.
Intent mIntent = new Intent(context, SplashScreen.class);
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
broadcastMessage(context, message);
I have answered a similar question in the following thread.
here
I think this is what you are looking for. Please let me know if this met your requirement or not, if you find the answer useful, if my answer helps you, up vote the answer so that it will be useful to others.
Cheers :)
Edit
I have did a bit research on it.
You can have two launcher activities according to this link.
Try it and let me know. Hope this helps you. :)

if(Global.isMainScreenRunning){
Intent intent = new Intent(this, MainScreen.class);
intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(Intent);//here is the problem change Intent to intent
} else if(!Global.NotificationScreenRunning){
Intent intent = new Intent(this, NotificationScreen.class);
intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}

Related

crash new android process stops entire application

I have a android application, which has mainctivty and it starts other activity "secondactivity", this secondactivity I am starting in a new process by adding android:process=":SecondProcess" in manifestfile.
I am starting second activity using below code.
Intent ssIntent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(ssIntent);
below is my manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test">
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.test.SecondActivity"
android:process=":SecondProcess"
android:label="#string/title_activity_basic"
android:theme="#style/AppTheme.NoActionBar">
</activity>
</application>
There is crash(I added for testing) in the Secondactivity, now as per my understanding only secondprocess Should gets killed whenever crash happens in secondactivity as its running in separate process , but in my test entire android application gets stopped .
Could you please let me know is there a way to handle such a way that only second process should killed and it should not disturb the complete application.
I can handle with try catch, but my goal is to make sure first Activity will be still alive even after second one crashes..
User try/catch to handle the error in SecondActivity...so that it won't crash the whole app.
try {
//Code that creates error in SecondActivity
}catch(Exception e) {
//Close the activity after exception
finish();
}

Unable to resume state of activity on clicking notification

Context: There is a toggleButton which toggles between 'Record' and 'Stop'. When record is clicked, a notification is created to tell the user that there is a background service running, even if the user has hit the home button etc. and moved out of the app. On clicking the notification, the user should be able to come to the activity and 'Stop' the recording and save the file.
The problem: If i click record (and thus toggling the button), then hit the home button, and then click the notification, it comes to the activity, but the toggleButton is in 'Record' instead of 'Stop'. i.e. it has not retained the previous state. I presume this is because a new instance of the activity is created instead of reusing the existing one.
The code:
public void showRecordingNotification(){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
mBuilder.setContentTitle("Recording in progress!");
mBuilder.setContentText("Go to the app to stop.");
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent appPendingIntent=PendingIntent.getActivity(this,0,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(appPendingIntent);
Notification notification= mBuilder.build();
notification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
mNotificationManager.notify(NOTIFICATION_ID, notification);
}
The android manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="space.wavicle.sensorvector2d" >
<uses-feature
android:name="android.hardware.sensor.accelerometer"
android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name">
<service android:name=".DataLogger"/>
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
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=".ReplayActivity"
android:label="#string/title_activity_replay"
android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="space.wavicle.sensorvector2d.MainActivity" />
</activity>
</application>
</manifest>
What I've tried: Googling around and hunting around SO, i found many people having similar sounding problems, and all solutions seemed to revolve around flags of the intents, of which i tried all the combinations that made sense. I also have android:launchMode="singleTask" (also tried android:launchMode="singleInstance") in the manifest. None of them seems to do the job.
you should ask yourself a different question in my opinion.
why does it matter for that button, if the activity is a new instance or not?
how exactly do you know your recording state? if you are saving the state in the activity, that means if the activity is somehow lost(crash) or killed, you lose your state. that's bad.
you say you have a service running in the background, I would let the service hold my state.
EDIT :
as for the instance issue, first of all, here's a link to google documentation so you can read further regarding that topic:
http://developer.android.com/guide/components/tasks-and-back-stack.html#ManifestForTasks
in short, there are 4 launchModes states, standard, singleTop, singleTask, singleInstance.
you can read the differences in the docs.
The way I see it I would recommend you to go with the "singleTask" state.
basically, in singleTask, if you open that activity again thru a notification for example, it will resume the current activity that is already open, you can debug it and see that you won't enter the usual onCreate, you will go thru onResume (and OnNewIntent ofc..)

java.lang.SecurityException: Not allowed to start service Intent without permission BIND_INPUT_SERVICE

Hi I am working on soft keyboard.
I am getting exception of permission when I am accessing my service
class from my simple activity class.
Stack Trace of exception is shown below,
In above image InputServiceMethod class = Underlined by Green color.
Activity class = Underlined by Blue color.
I am getting this exception when I am calling InputServiceMethod class
from activity class.
For this I used the below code which gives me exception,
Intent intent = new Intent(v.getContext(),SoftKeyboard.class);
startService(intent);
finish();
My manifest file as shown below,
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.softkeyboard"
android:installLocation="preferExternal">
<uses-permission android:name="android.permission.VIBRATE" />
<!-- <permission android:name="android.permission.BIND_INPUT_SERVICE" -->
<!-- android:exported="true"></permission> -->
<application android:label="#string/ime_name">
<service
android:name="com.example.android.softkeyboard.SoftKeyboard"
android:permission="android.permission.BIND_INPUT_METHOD"
android:exported="true">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data
android:name="android.view.im"
android:resource="#xml/method" />
</service>
<activity
android:name="com.configuration.Configuration"
android:label="#string/title_activity_configuration" >
</activity>
</application>
I don't understand as even if I give permission about BIND_INPUT_METHOD it is throwing exception.
How to fix it? Thanks
It looks like you are binding service to action android.view.InputMethod while it is protected by permission android.permission.BIND_INPUT_METHOD which is used to ensure that only the system can bind to it by its protection level. So According to Android you can only define the keyboard handling service but can't call it explicitly, it will be called automatically by system whenever a input method is required. So there are two ways to solve it:
1. Let it be called by system, don't call it explicit, or
2. Sign your application with system's signature you are running on, which makes your application platform dependent. (Not advised if your building generic application).
Hope you understand the situation.
The permission you are using i.e:
permission about BIND_INPUT_METHOD
is only for system apps and mostly will work only on rooted devices,
it wont accept on unrooted devices.

Android Application not running at startup

I have a basic Android application that is supposed to reboot the phone continuously a set number of times. In order to do this, I need the application to be started upon phone startup. In order to that, I essentially followed the instructions found here, adding the permissions to the manifest and creating a BroadcastReceiver class that starts the activity. Here is some of my relevant code:
public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("StartMyServiceAtBootReceiver called.");
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
// Intent activityIntent = new Intent("com.example.rebooter.MainActivity");
Intent activityIntent = new Intent(context,MainActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
}
}
}
From the manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rebooter"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</activity>
<service
android:name=".RebootManager"
android:label="Reboot Manager" >
<action android:name="com.example.rebooter.RebootManager" />
</service>
<receiver android:name=".StartMyServiceAtBootReceiver"
android:enabled="true"
android:exported="true"
android:label="StartMyServiceAtBootReceiver" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</receiver>
</application>
In the Eclipse emulator, the application appears to be working properly. That is, though my emulator isn't rooted and the phone doesn't execute the reboot commands correctly, I do see that, upon startup, the correct activity is started.
Now, when I'm trying it on a particular system running Android 4.0.4, everything in the application is working properly EXCEPT boot upon startup. Any ideas?
I tried to eliminate the possibility of any hardware problems (since I'm not using a commercially-released phone) by installing another application that boots upon startup and confirming that it does indeed boot upon startup, and it does indeed show up under running apps as a cached process after startup.
I would appreciate any help. Let me know if you need any additional information.
There are a number of issues here.
First, you neglected to post StartMyServiceAtBootReceiver, the component you are expecting to get control at boot time, so we cannot comment on whether there are any particular problems with it.
Second, unless something has explicitly executed one of your components (e.g., the user launched MainActivity from the home screen), StartMyServiceAtBootReceiver will never be invoked, on Android 3.1+. Make sure you run your activity before trying a reboot, and see if that helps.
Third, you implemented a constructor on StartupManager, which is a bad idea. Please move this logic to onCreate().
Fourth, your code will likely crash in that constructor, as getApplication() will not return a valid value at this point in the code, particularly since you failed to chain to the superclass' constructor. Again, moving this code to onCreate() will help here.
Fifth, starting an activity from onCreate() of a service (let alone its constructor) is very unusual and may not be appreciated by the user. Moreover, if that service is not doing anything else, you could just as easily start that activity from StartMyServiceAtBootReceiver and skip StartupManager entirely.
Sixth, you have <intent-filter> elements on your services, as if you are expecting third party developers to invoke those services. If that is the case, fine. If not, please remove the <intent-filter> elements and use explicit Intents within the rest of your app code to refer to them (e.g., new Intent(this, StartupManager.class)), for better security. Or, add android:exported="false" to those services, though that is automatic if you remove the <intent-filter> elements.

Why doesn't setting clearTaskOnLaunch="true" cause OnCreate to be called?

My application works fine, once it is initialized in the OnCreate method of my View class. However, when I open my app after the Droid phone has been sitting idle all night, the OnCreate method is not being called.
I use the OnCreate to initialize data, and that in turn initializes the GUI. The GUI clearly shows that OnCreate was not called.
I tried setting clearTaskOnLaunch="true" in my Manifest. My Manifest is:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hedgetools.trin"
android:versionCode="2"
android:versionName="1.02">
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:clearTaskOnLaunch="true">
<activity android:name=".Trin"
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>
<uses-sdk android:minSdkVersion="6" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
This did not help. My OnCreate method is not being call after the Droid phone sits idle all night.
Why doesn’t clearTaskOnLaunch cause OnCreate to be called?
Any help or suggestions will be greatly appreciated.
Charles
OnCreate gets called only when the application is launched as a fresh one. Subsequently the OnResume function gets called.
See http://developer.android.com/reference/android/app/Activity.html for a description of the application life cycle.
clearTaskOnLaunch tells android to remove any activities other than the main one from the history stack when you launch it from home. it has nothing to do with triggering onCreate.
Sidharth has it right, for that you need to put your initialization in onResume, not onCreate. see the diagram in http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle for a very quick explanation of the different activity states.

Categories

Resources