This question already has answers here:
How to bring an activity to foreground (top of stack)?
(10 answers)
Closed 4 years ago.
I have an app that needs to run 24/7.
I know that android OS kills the process of my app after some time in the background, so i have a Foreground service which is sticky.
Now the thing is, that i want the service to check if my app is running, and if it is not, then i want the service to start the app. Is it possible?
After onStop your activity will be invisible. If you want to see that your activity running, i.e., on the foreground;
public boolean isForeground(String myPackage) {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.getRunningTasks(1);
ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
return componentInfo.getPackageName().equals(myPackage);
}
If it is not in the foreground, you can use below otherwise;
Intent i = new Intent(this, MyMainActivity.class);
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
Note; another method, you can send message to your service from your activity about its status
or, use idolon's idea]2;
What kind of app is it? I think such types of apps can be very annoying for users.
I am not sure what exactly functionality your app have, but are you sure that you can't achieve that same functionality with using AlarmManger or JobScheduler ?
Related
This question already has answers here:
How to get the sender of an Intent?
(8 answers)
Closed 3 years ago.
Is there a way to find out, if my Android App was opened by the launcher or by some third party app?
Something like this maybe?
click
I am trying to build an app that can toggle torch. Which already works (I am new to Java and Android). But I want Bixby Button on my Samsung phone to open the app and then toggle torch automatically. Bixby is able to open a app since the newest version.
I found out, that if I open the app from the launcher and resume, it's the same instance. But if Bixby opens the app, it seems to be a new instance every time.
And I don't want to use Availability Service to receive bixby button event.
kind regards
#Vladyslav Matviienko, thank you for this link:
This seems to work:
protected void onResume() {
super.onResume();
Uri uri = this.getReferrer();
if (uri==null) textView.append("Host: null");
else textView.append("Host: " + uri.toString());
}
When opened by launcher, uri is "null", but when opened by bixby, it is "android-app://com.samsung.android.bixby.agent"
EDIT: On a second try launcher is "android-app://com.sec.android.app.launcher".
This is a known bug.
NotificationListenerService gets killed during app updates and sometimes even randomly and it isn't restarted automatically. Further, it can't even be started manually but we have to prompt the user to reboot the device, since the service only seems to be able to be started on device boot.
The following doesn't work (trying to start the service manually):
startService(new Intent(this, NotificationService.class));
Are there any workarounds for this? I need the service to be constantly running and getting the OnNotificationPosted events.
This might not solve your problem completely but it might help with the service being killed randomly. I had a similar problem with my own app. Although I worked around the problem in another way, I found out about foreground services.
Apparently, Android kills your notification service to save memory and that explains the seemingly random kills.
To work around this, you can use a foreground service that will not be killed by Android and the service will be running at all times. See Running a Service on Foreground.
Do you try setting START_STICKY?
More information about it: https://developer.android.com/reference/android/app/Service.html#START_STICKY
May be my answer can help you too. Please take a look at
https://stackoverflow.com/a/35435065/1554094
Try this code to manually disable & re-enable the service
private void toggleNotificationListenerService() {
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(this, your.NotificationListenerServiceImpl.class), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(new ComponentName(this, your.NotificationListenerServiceImpl.class), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
You can catch the broadcast Intent.ACTION_PACKAGE_CHANGED to know when the service gets disabled.
And you can use this code to check if your notification service is enabled.
private static boolean isNotificationListenerServiceEnabled(Context context) {
Set<String> packageNames = NotificationManagerCompat.getEnabledListenerPackages(context);
if (packageNames.contains(context.getPackageName())) {
return true;
}
return false;
}
Solved,
Set the notificationListenerServer to be foreground service. Then the service would be alive.
createNotificationChannel();
startForeground(NOTIFICATION_ID, getNotification());
In Android, how does one know an app has been started. I want to detect all apps installed when it starts, and range apps' priority according to its using times. Is there a solution to suggest to do this?
I know using broadcast, but is there some Intent send out from ActivityManager when app had been started, and how to detect this Intent in code? Any other solution is welcome, too.
First part:
If you know the package name of your app, try this (put this following snippet in the onCreate method of your app):
ActivityManager am= (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
Then,
boolean exit = false;
while(!exit)
{
List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if(componentInfo.getPackageName().equals("Your package name"))
{
//Do your work here
exit = true;
}
}
When you start your app, this will be put into componentInfo. The taskInfo.get(0).topActivity will return the activity in the foreground. Hence you can know that your app has been started by comparing package using the second code snippet.
Note:Put this second code snippet in an Asynctask so that the checking of whether the app has started can be done in the background.
Second part:
To get the priorities, I think you can do it by checking the list TaskInfo which will contain all the running apps.
This question already has answers here:
start a remote service and receive a result in Android
(2 answers)
Closed 9 years ago.
How I can get response from Activity, which start from my Service?
I start my Activity in Service's code:
Intent intent = new Intent( context, ActivityMy.class);
intent.putExtra( "iii", iii);
context.startActivity( intent);
startActivityForResult available from Activity but no Service.
How I can get response from Activity?
Update: I need not only send one value from Activity to Service, I need run immediately my code when Activity is finished and return result.
You can create a custom Class that extends of Application and set it in Manifest (just set the android:name attribute in <application>). In this class you can put a static variable called activity and set everytime you change the activity. So in your Service you will can access the activity by using MyApp.activity
The simplest way is to use BroadcastReceiver to send broadcast from Activity to Service.
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);
}