Invoking activity from a service - java

I have a situation with the intent flag FLAG_ACTIVITY_NEW_TASK
The Scenario
I have a service which launches an activity. This service is used by my android wear application. When I launch the activity I specify the FLAG ACTIVITY NEW TASK flag as mandated by android OS (When you call an activity from a service , it is necessary to apply the NEW TASK flag).
Intent intent = new Intent(this, GoodOlActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Supposedly My application is already running and I access my service and get GoodOlActivity to launch , it would be launched on the top of the task stack (NO NEW TASK WILL BE CREATED , BECAUSE OF AFFINITIES). If i keep on launching this activity , it will keep on having its copies made on the task stack .
The Problem
Supposedly my application is not in the history stack and I have pressed home and removed it. In such a situation a user uses the android wear application and invokes the service. The service in turn invokes GoodOlActivity. Okay Good . However subsequently GoodOlActivity is never launched and remains the only activity in the task stack .
Presumption
I believe that in the first case , the multiple activites were launched on top of another because the new task was not actually created. The reason being that a task for the target activity existed.
However in the second case a new task was created , hence the constraints of that come into play . The constraints being that if an activity is already in the task stack, just that activity would be brought to the foreground.
Target
Well both the scenarios (one with the application running , and the other with it being swiped out) should be the same . I should be able to run GoodOl multiple times. Helppp ?

Related

Android Studio - Using Service to call final() vs. FLAG_ACTIVITY_NEW_TASK

I have been scouting around for a while, but cannot locate any information for calling final() using started services... or rather, when not using bound services. There is tons of info for bound services, but I already have two pretty large "started services" without binding, so I didn't want to modify the existing services more than absolutely necessary.
My app works by reading bluetooth data every 10 seconds, and depending on the data read, the Service will change to a new activity. However, I cannot call final() from my services, so I fear that I might be endlessly stacking activities while the application/services are running.
To change activities, I had to add Intent.FLAG_ACTIVITY_NEW_TASK. Considering the below image/definition from the developer's page, this flag looks like it might already handle my stacking issue? I do NOT allow for users to use the back button on their phones as everything is handled via confirm/cancel buttons and the services. My app MUST be this way for a few reasons. Thus, keeping the stack order isn't important to my application.
Key Points -
I want to ensure i'm not stacking up activities endlessly when starting new activities
Flagging "new task" when starting activities via my services
Stack order is not important to my app
Below is a very small cut of my code with comments to explain what i'm trying to do. Please make sure to look to the onDestroy() method of this service.
public class AlertService extends Service {
final class Threader implements Runnable{
// Scans bluetooth advertisement packets every 10 seconds
// Thread Runs until interrupted
// Stops service via service ID
stopSelf(this.serviceID);
}
#Override
public void onCreate(){
super.onCreate();
}
// Runs a thread until alert is found.
// Alert calls thread.interrupt()
#Override
public int onStartCommand(Intent intent, int flags, int startID){
enableBluetooth();
// Start Thread
thread = new Thread(new Threader(startID));
thread.start();
return START_STICKY;
}
#Override
public void onDestroy(){
thread.interrupt();
Intent alertActivity = new Intent(this, AlertActivity.class)
alertActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(alertActivity);
}
// Unused Method - We will not be binding
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
EDIT via recommendation to use android:taskAffinity -
Using android:taskAffinity won't help me in this situation. By default, all activities in an application have the same affinity. When I create a new task by setting Intent.FLAG_ACTIVITY_NEW_TASK in the intent flags, the new activity will STILL be started in the same task if the activity has the same taskAffinity of the root activity in the task. Since I am just using the default affinity, everything should have the normal stack flow. I just cannot call finish(), which means that I am stacking up tons of activities.
To answer my own question, each new activity called via Intent.FLAG_ACTIVITY_NEW_TASK, was creating a new instance of each activity and putting it on the stack. This is true. However, each activity is NOT making a new Task, which was one of my fears as well.
When I create a new task by setting Intent.FLAG_ACTIVITY_NEW_TASK in the intent flags, the new activity will STILL be started in the same task (not in a new task) if the new activity has the same taskAffinity of the root activity in the task. Since I am just using the default affinity, every activity I create is being put into the same task. This means that nothing is acting any differently than the normal flow of creating activities and such.
Though, since I have disable the back button for my application, these activities created by flagging a new task are not finished, destroyed, or removed from the stack. To solve this, I will use FLAG_ACTIVITY_CLEAR_TOP, which finds a running instance of an activity in the stack (if there is one) and closes all of the activities above it.
Since my application always starts with the home screen, then ends with the home screen, flagging "clear top" will always close all activities above my home screen. So, upon return to the home screen, the only item on the stack will be the home screen.
I will have to test this, but it seems that I will not call finish() from my home activity to achieve this result - Otherwise, upon returning to the home activity, not all of the stack will be cleared.

How to run a background service even the app is killed in MI devices

Hi i am running a background service using alaram manager its working fine but for some mi devices background service is not working.I used sevices but it is not working how to run my background service in mi ?
MI UI has its own security options, so what you need to is not just above mentioned sticky Service,
you need to
Enable Autostart
go to power setting make changes as per these youtube videos
https://www.youtube.com/watch?v=-Ffgir-QgsU, or refer for this for more suggestions
https://www.quora.com/How-do-I-keep-an-app-running-in-the-background-in-MIUI
then you have created a custom broadcast receiver which will start the service when your service is destroyed
as per this example https://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android
If the 3rd option doesn't work onDestroy recall of the service call the custom broadcast receiver on
w
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.e(TAG, " In recieve Custome Broadcast receiver");
Intent broadcastIntent = new Intent("ac.in.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.android.settings","com.android.settings.Settings$HighPowerApplicationsActivity"));
startActivity(intent);
try this code
it will open one setting page
then find your app and then tap "Don't Optimize"
it will turn off battery optimization and your background services run without problem
When you start a service by extending an Service class than you will get the call inside OnStartCommand() this method has three types of return type on the basis of this return type operating system itself manage when to start a service.
So suppose if your service gets killed in between due to low memory or any other issue when you return a correct type from onStartCommand() than os will take care of when to start service again.
Three return types are:
START_STICKY : When this is the return type than os takes the guarantee to restart the service again if its get killed it will definitely start you service again even if there is no pending intent it will start the service by passing intent as null.
START_NOT_STICKY: says that, after returning from onStartCreated(), if the process is killed with no remaining start commands to deliver, then the service will be stopped instead of restarted. This makes a lot more sense for services that are intended to only run while executing commands sent to them. For example, a service may be started every 15 minutes from an alarm to poll some network state. If it gets killed while doing that work, it would be best to just let it be stopped and get started the next time the alarm fires.
START_REDELIVER_INTENT is like START_NOT_STICKY, except if the service's process is killed before it calls stopSelf() for a given intent, that intent will be re-delivered to it until it completes (unless after some number of more tries it still can't complete, at which point the system gives up). This is useful for services that are receiving commands of work to do, and want to make sure they do eventually complete the work for each command sent.

android - resuming from last visited page in my app

I have login page (activity) which is my first activity (landing page) of the app.
Only after user gives correct username and password, the app allow you go to other pages to work with.
Now my question is, now the user is at the fourth page and he is working on it, And he minimize the app and use other app like messaging etc..
so when he come back to click my app icon again, my app starts from the first landing page, which is the login page,
how can I make my app to resume from the fourth page?
Android 4.4.4, Kit Kat, Samsung
Regards,
Nay TK
Add this in android manifest of loginActivity,
android:launchMode="singleTask"
more on android:launchMode
An instruction on how the activity should be launched. There are four modes that work in conjunction with activity flags (FLAG_ACTIVITY_* constants) in Intent objects to determine what should happen when the activity is called upon to handle an intent. They are:
"standard"
"singleTop"
"singleTask"
"singleInstance"
The system creates the activity at the root of a new task and routes
the intent to it. However, if an instance of the activity already
exists, the system routes the intent to existing instance through a
call to its onNewIntent() method, rather than creating a new one.
go through official link for more detail
You can make your fourth activity as your launch activity.
In the Resume of your Activity, you check if the user is logged in. If not, you start your Login activity.

Application lose current activity after 1 hour

My application is quite simple, I have a few activities (a LoginActivity which is the launcher and the main activity). Then I have some other activities and finally an activity RouteActivity which launches a service.
The LocationService extends Service and startForeground with a notification. The service just starts a LocationListener and register every new GPS location point.
The service appears to work just fine, if I touch the notification icon it bring me back to my application activity from where it was started (not from the Login activity).
Now here is the problem, if I touch the application icon (on the Android launcher) it sometimes lauch my app to the right and current activty RouteActivity, but after around 1 hour, if I touch the application icon it just restart the application from the beginning and start the LoginActivity.
But if I touch my service notification if bring me back to the right and background activity.
Also my service is not killed, never, so it seems to work just fine, objects and variable tied to the application are still there.
So what ? I have 2 instances of my application running ? I'm kinda lost on this one, especially that it seems to be time related.
This "bug" is produced on Android 2.X, I can't reproduce it on Android 4.X. It is kinda hard to debug because I have to let the application run for around 1 hour. And after that time I have no special message in logcat.
I noted something:
The ActivityManager messages are quite strange, if I launch my application through the service notification in the notification center it log:
Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x14000000 cmp=com.wayzup.wayzupapp/com.wayzup.activity.RouteActivity bnds=[0,149][320,213]
While if I launch it trough the application icon it's logged, but the actual activity shown is not the login one but the actual RouteActivity which actually launched the service. (After around 1 hour it is effectively the LoginActivity which is started).
Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.wayzup.wayzupapp/com.wayzup.activity.LoginActivity bnds=[3,338][77,417]
Each time I launch the RouteActivity I also have this log
Activity idle timeout for HistoryRecord{44e78808 com.wayzup.wayzupapp/com.wayzup.activity.RouteActivity}
This is related to my other question: Android foreground service lose context
But I think this one is the real problem and more accurate.
I can post some code if you want to.
It sounds like you're relying on an activity task stack to maintain all your state. I suggest you use instead use something like PreferenceManager.getDefaultSharedPreferences() to maintain the logged in / logged out state. That way your can survive if its activities are terminated and recreated.
The way I tend to do it is have your main activity be the one you want the user to see once they're logged in. In its onCreate() check to see if the user is logged in and if not, startActivityForResult() to send them off to the login activity. Persist the logged in state somewhere so that you can check it in the main activity's onCreate().
I finally resolved my problem.
Now it does not matter if the activity is killed or not, as long as the service is alive it's fine.
In my LoginActivity I check for if my service, if it's running I start the RouteActivity which is bound to it and singleTop. Si I always have the single and same instance of it.
#Override
public void onResume(){
super.onResume();
if (checkMyServiceRunningOrNot()){
restoreAcitivty();
}
}
public void restoreAcitivty(){
Intent intent = new Intent(this, RouteActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}

Android, Opening app only if it is closed through intent action

I am working on a phonegap application, with some native pieces.
So far I have notifications running natively, to make sure javascript and phonegap is not required at all. The problem I am having however, is when the notification is clicked I'd like to open the app, or otherwise just bring the app to the front.
How do I do this? I tried setting the main activity in the intent, but it restarts my application every time.
Intent notificationIntent = new Intent(context, main.app.class);
notificationIntent.putExtra(NOTIF_RESPOND, runThis);
notificationIntent.setAction(Intent.ACTION_VIEW);
notificationIntent = notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Actually in Android there is almost no such thing as "restarting application". Basically the Application - is a bundle of all your services/activities/providers etc. It's either running or not.
If user starts a new Activity - system will check, if application is running - it will create this activity inside the application. If no - will create new Application instance.
So I think you mean that if you set intent for your Main activity - another instance of Activity is launching, am I right?
If so - take a look at the following flag for activity, you should try to set in in the Manifest(or whatever in PhoneGap, sorry). http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
<activity android:name=".YourActivity"
android:launchMode="singleTask"
...
This flag will tell the system not to create a new Activity each type it will be needed, but to reuse already-existing one. Be careful, you should properly implement onNewIntent method in this case to handle this "relaunches", and I'm not 100% sure that it's implemented in PhoneGap.
Good luck

Categories