I've got an app that registers itself as the default launcher and pins itself automatically when started.
This all works fine when installing the app. It pins itself and only the back button is visible.
The problem is that when the device first boots up, it does not pin properly. I see a series of toasts "Screen pinned" and "Screen unpinned" multiple times. The "Home" and "Recent Tasks" buttons are still visible as well.
--
Running "adb shell dumpsys activity activities" - the last lines indicate that it is not pinned:
mLockTaskModeState=NONE mLockTaskPackages (userId:packages)=
0:[com.example.myapp]
mLockTaskModeTasks[]
--
Testing device Asus ZenPad running Marshmallow/6.0/23
I'm relying on the MainActivity manifest attribute "lockTaskMode" to pin (rather than activity.startLockTask()):
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="#string/launcher_main"
android:launchMode="singleTask"
android:lockTaskMode="if_whitelisted"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
Any help or pointers would be appreciated
I had the same problem and I could really only find one solution. I'm not sure why but yeah, something in android prevents task locking when booting up which boggles my mind since the task lock was designed to create these "kiosk" type of applications. The only solution I could find was to detect for a case when it didn't lock then restart the application. Its a little "hacky" but what else can you do?
To detect for the case where it didn't lock I created a state variable and assigning states (Locking, Locked, Unlocking, Unlocked). Then in the device admin receiver in onTaskModeExiting if the state isn't "Unlocking" then I know it unlocked on its own. So if this case happened where it failed, I then restart the application using this method (which schedules the application in the alarm manager then kills the application):
how to programmatically "restart" android app?
Here is some sample code:
DeviceAdminReceiver
#Override
public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
super.onLockTaskModeEntering(context, intent, pkg);
Lockdown.LockState = Lockdown.LOCK_STATE_LOCKED;
}
#Override
public void onLockTaskModeExiting(Context context, Intent intent) {
super.onLockTaskModeExiting(context, intent);
if (Lockdown.LockState != Lockdown.LOCK_STATE_UNLOCKING) {
MainActivity.restartActivity(context);
}
Lockdown.LockState = Lockdown.LOCK_STATE_UNLOCKED;
}
MainActivity
public static void restartActivity(Context context) {
if (context != null) {
PackageManager pm = context.getPackageManager();
if (pm != null) {
Intent intent = pm.getLaunchIntentForPackage(context.getPackageName());
if (intent != null) {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int pendingIntentId = 223344;
PendingIntent pendingIntent = PendingIntent.getActivity(context, pendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
System.exit(0);
}
}
}
}
private void lock() {
Lockdown.LockState = Lockdown.LOCK_STATE_LOCKING;
startLockTask();
}
private void unlock() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (am.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
Lockdown.LockState = Lockdown.LOCK_STATE_UNLOCKING;
stopLockTask();
}
}
In truth this is a simplified version of what I implemented. But it should hopefully get you pointed towards a solution.
The only solution I found as for now : make another launcher app, without locktask, which will trigger main app every time when launcher appears. This prevent user for waiting few more seconds before LockTasked app is being called with on BOOT_COMPLETED receiver. So we can meet this problem only when lockTask app has launcher properties for some activity in manifest.
Sorry for late answering, but...
Anyone has this problem can do this tricky work in first (LAUNCHER/HOME) activity (e.g. MainActivity):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mSharedPreferences.getBoolean(KEY_PREF_RECREATED, false)) {
mSharedPreferences.edit().putBoolean(KEY_PREF_RECREATED, false).apply();
// start LOCK TASK here
} else {
mSharedPreferences.edit().putBoolean(KEY_PREF_RECREATED, true).apply();
finish(); // close the app
startActivity(new Intent(this, MainActivity.class)); // reopen the app
return;
}
setContentView(R.layout.activity_main);
// other codes
}
Related
I have the following service declared in the manifest:
<application
...
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.android.test.TestService"
android:process=":Remote"
android:permission="android.permission.WAKE_LOCK"/>
<receiver android:name="com.example.android.test.TestService">
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
</intent-filter>
</receiver>
</application>
and this is the Service class
public class TestService extends Service implements SensorEventListener {
public class BatteryReceiver_andFileChecker extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//TODO
}
// constructor
public BatteryReceiver_andFileChecker(){
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
//TODO
return START_STICKY;
}
#SuppressLint("WakelockTimeout")
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Logging service started new", Toast.LENGTH_SHORT).show();
//Acquire wake lock
PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WLTAG:MyWakelockTag");
wakeLock.acquire();
//Display notification
this.notIntent = new Intent(this, MainActivity.class);
this.pendingIntent = PendingIntent.getActivity(this, 0, this.notIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, this.channelID).setSmallIcon(R.drawable.ic_launcher_background).setContentTitle("Test").setContentText("Sensor is recording").setPriority(NotificationCompat.PRIORITY_DEFAULT).setContentIntent(this.pendingIntent);
startForeground(this.NOTIFICATION, builder.build());
//BatteryCheck
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
mReceiver = new BatteryReceiver_andFileChecker();
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
super.onDestroy();
//cancel notification
stopForeground(true);
//Unregister battery receiver
unregisterReceiver(mReceiver);
//release wakeLock
wakeLock.release();
//Stop Service
stopSelf();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
// super.onBind(intent);
return null;
}
#Override
public void onSensorChanged(SensorEvent event) {
//TODO
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
And this services is created and terminated on two different "onclick" functions from the MainActivity
public class MainActivity extends AppCompatActivity {
...
public void onClickStart(View v) {
// Start Service
this.intent = new Intent(getApplicationContext(), TestService.class);
this.intent.putExtra("foo",foo);
startService(this.intent);
}
public void onClickStopAcquisition(View v) {
// Stop Service
stopService(this.intent);
}
}
This code runs as expecten in Android 6.0.1 and does not work on Android 10...
When I debug de app, no errors are fired when pressed the Start and Stop buttons in both OS, nevertheless, android 6.0.1 fires the service and android 10 does not...
Any reason why?
Just to keep in mind when understanding my implementation, my intention is to make a service which keeps running and doing stuff even if the user is not active in the application. Since I implementen the SensorEventListener to record data from sensors, my intention is to record data while the user might be interacting with the phone or even doing nothing (after he presses the power button of the phone, the service keeps running acquiring data and performing actions)
Then, the service should be terminated either when the user clicks the stop button or either when the MainActivity is terminated.
Thank you!
i guess you should read more about background services and broadcast in android API 26 or higher
From the official documentation available here
If an app registers to receive broadcasts, the app's receiver consumes resources every time the broadcast is sent. This can cause problems if too many apps register to receive broadcasts based on system events; a system event that triggers a broadcast can cause all of those apps to consume resources in rapid succession, impairing the user experience. To mitigate this problem, Android 7.0 (API level 24) placed limitations on broadcasts, as described in Background Optimization. Android 8.0 (API level 26) makes these limitations more stringent.
Apps that target Android 8.0 or higher can no longer register
broadcast receivers for implicit broadcasts in their manifest. An
implicit broadcast is a broadcast that does not target that app
specifically. For example, ACTION_PACKAGE_REPLACED is an implicit
broadcast, since it is sent to all registered listeners, letting them
know that some package on the device was replaced. However,
ACTION_MY_PACKAGE_REPLACED is not an implicit broadcast, since it is
sent only to the app whose package was replaced, no matter how many
other apps have registered listeners for that broadcast. Apps can
continue to register for explicit broadcasts in their manifests. Apps
can use Context.registerReceiver() at runtime to register a receiver
for any broadcast, whether implicit or explicit.
Broadcasts that require a signature permission are exempted from this restriction, since these broadcasts are only sent to apps that are signed with the same certificate, not to all the apps on the device
you should work with JobScheduler
Important Update
to answer your question in comment : use WorkManager for deferrable background tasks.
This library is backward compatible
It use JobScheduler,FirebaseJobDispatcher or AlarmManager
No Need to depend on play service library.
Recommended by Google for deferrable background work.
Can use features like chaining, constraints etc.
I am trying to create a scheduling application. I am using Alarm manager. It is working fine when app is alive. If I removed the app from recent applications Alarm is not triggering. Please let me any idea to resolve my issue. Herewith I attached my code.
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(SettingsPage.this, AlarmManagerForSettings.class);
i.putExtra("requestCode", "100");
i.putExtra("AlarmTag",id);
PendingIntent pi = PendingIntent.getBroadcast(SettingsPage.this, (int)id, i, 0);
am.cancel(pi); // cancel any existing alarms RTC_WAKEUP
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_DAY, pi);
ComponentName receiver = new ComponentName(SettingsPage.this, AlarmManagerForSettings.class);
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
Broadcast Receiver:-
public class AlarmManagerForSettings extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
String requestCode = "";
String alarmTag = "";
if (bundle != null) {
requestCode = bundle.get("requestCode").toString();
alarmTag = bundle.get("AlarmTag").toString();
}
//Rest of code I wrote here
}
}
Manifest:-
<receiver
android:name=".AlarmManagerForSettings"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
Some of the mobile Broadcast Receiver is not running..if Broadcast is not running follow below steps:
In Xiaomi devices, you just have to add your app to Autostart list, to do so, follow these simple steps given below:
1.Open Security app on your phone.
2.Tap on Permissions, it'll show you two options: Autostart and Permissions
3.Tap on Autostart, it'll show you list of apps with on or off toggle buttons.
4.Turn on toggle of your app, you're done!
How to get MIUI Security app auto start permission programmatically?
Write your alarm manager code in sticky server class and start this service as per yours functionality. Check after killing of app is updating.
I have implemented a NotificationListenerService, yet it is not working. Here is the service:
public class NotificationListener extends NotificationListenerService {
#Override
public void onCreate() {
Log.d("MYAPP", "Created");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
Log.d("MYAPP", "Notification");
}
}
I have implemented this in my manifest file:
<service android:name="com.rodrigopontes.whatsappbubbles.NotificationListener"
android:label="Test"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
This is how I initialize it from my MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
startService(new Intent(this, NotificationListener.class));
}
Thank you for the help!
After many wasted hours I found the answer for this. This is an issue with Android see here
Welcome to Android :)
I had the same problem. It turned out my app was not allowed to receive notification as it did not have permission. So I enabled the notification permission by following-
Intent intent=new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(intent);
Above code opens a notification permission page then select your app and allow.
Maybe you haven't provided the Notification Access to your app. Try doing that and it should work
In my case the NotificationListner was not working after reboot. I am working with android 10 i have find out solution on this.
#Override
public void onListenerConnected() {
super.onListenerConnected();
Log.i("tag","Listner conneted");
tryReconnectService();
}
public void tryReconnectService() {
toggleNotificationListenerService();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
ComponentName componentName =
new ComponentName(getApplicationContext(), Whatsapp_recorder.class);
//It say to Notification Manager RE-BIND your service to listen notifications again inmediatelly!
requestRebind(componentName);
}
}
private void toggleNotificationListenerService() {
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(this, Whatsapp_recorder.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(new ComponentName(this, Whatsapp_recorder.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
Try this it is working for me
Some comments here mention other solutions, some of which led me to this:
https://gist.github.com/xinghui/b2ddd8cffe55c4b62f5d8846d5545bf9
The problem is, if I understand it correctly, that the service process is running, but is completely disconnected from, well, anything.
The gist is a service class which checks if your NotificationListenerService process is actually running and "connected" to whatever takes care of notifications inside the OS and if it isn't, restarts it (or rather enables the component, as starting it the usual way is exactly what's broken).
I've tried this solution on Android 7.1.1, where I was unable to use the NotificationListenerService, and it worked.
I am starting a service (or re-starting the running service) when an activity is launched, using :
Intent intent = new Intent(this, MyService.class);
startService(intent);
Later on based on certain actions, the same activity binds to the service using
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
And when the activity is destroyed, I call
unbindService(mConnection);
Earlier, the service used to restart when I killed the same activity/application from the application tray and showed the "message 1 process 1 service running" under running apps.
Now, the service does not restart on killing the same activity/application.
And I get the message "0 process 1 service running", which means the service is actually not running.
The service does not restart on application being closed. My application consists of one activity. Also the service is successfully started when launched after a system boot.
Why does the process of the service gets killed when I start it using startService() ??
edit
The service used to re-start earlier after i closed the app from the application tray. But now suddenly with the SAME code, it doesn't. It happens with other apps too when i close them. eg.
Here is a workaround I came across and works well for re-starting a service if its process is killed on closing the application. In your service, add the following code.
I came across this workaround in this thread.
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
Seems to be a bug that the process of the application is killed. There is no point for a service to run if its process is killed.
Please be aware of that: onDestroy is not always called. You should not put code that way.
When activity forced closed or closed by system abnormally, onDestroy is not getting called.
Unfortunately, this is a complicated problem due to the way Android works. There are a number of strategies that each work around different parts of the problem. For best results, combine multiple strategies together.
Note that some of these strategies may no longer be necessary in more recent Android versions.
1. Start an activity
What to do
Taken from Foreground service killed when receiving broadcast after acitivty swiped away in task list:
In the foreground service:
#Override
public void onTaskRemoved( Intent rootIntent ) {
Intent intent = new Intent( this, DummyActivity.class );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
}
In the manifest:
<activity
android:name=".DummyActivity"
android:theme="#android:style/Theme.NoDisplay"
android:enabled="true"
android:allowTaskReparenting="true"
android:noHistory="true"
android:excludeFromRecents="true"
android:alwaysRetainTaskState="false"
android:stateNotNeeded="true"
android:clearTaskOnLaunch="true"
android:finishOnTaskLaunch="true"
/>
(If your service is in a different process then set this activity's process to the same one.)
In DummyActivity.java:
public class DummyActivity extends Activity {
#Override
public void onCreate( Bundle icicle ) {
super.onCreate( icicle );
finish();
}
}
Side effects
Causes the recents activity to close. Normally, swiping away an app doesn't close the recents activity.
Disadvantages
This only takes effect when the dummy activity starts, which may take half a second or more, so this still leaves the service open to being killed for a bit.
Explanation
When you remove/swipe your app away, a flag called waitingToKill is set. While this flag is set, Android may kill the process at any point in the future, such as when you receive a broadcast. Starting an activity clears this flag.
2. Spam a BroadcastReceiver with foreground broadcasts
What to do
Merge this into your service code:
if (Build.VERSION.SDK_INT >= 16) {
Intent intent = new Intent(this, DummyReceiver.class);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//This seems to be timing-related; the more times we do this,
//the less likely the process gets killed
for (int i = 0; i < 50; ++i)
sendBroadcast(intent);
}
Create a dummy broadcast receiver:
public class DummyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {}
}
Add the receiver to your manifest:
<receiver android:name=".DummyReceiver" />
Side effects
May cause a slight (~250ms) delay/hang when the task is removed from the recents screen.
Disadvantages
This only keeps the process alive while it is receiving the broadcasts. the waitingToKill flag is still set, so the process may still be killed afterwards, such as when a broadcast is received.
Explanation
If your process isn't running in foreground priority, Android will try to kill it immediately. Receiving foreground broadcasts temporarily prevents this, resulting in the waitingToKill flag being set instead.
3. Don't bind to services
Binding to a service seems to increase the likelihood of the service's process being killed immediately when a task is removed.
I know this question is old but I recently encountered this problem and suddenly my service get stopped on closing app. Earlier it was working fine. This problem wasted my lot of time. To others who have similar problem make sure that YOUR BACKGROUND DATA RESTRICTION IS OFF.
This was the problem I had and it actually makes sense as when background data is Restricted background process won't run.
onDestroy is not always called. The Main problem in your case is ur unable to start the service when app closed,that time android OS(In Some OS) will kill the service, If you are not able to restart the service then call a alarm manger to start the reciver like this,
Manifest is,
<service
android:name=".BackgroundService"
android:description="#string/app_name"
android:enabled="true"
android:label="Notification" />
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="REFRESH_THIS" />
</intent-filter>
</receiver>
IN Main Activty start alarm manger in this way,
String alarm = Context.ALARM_SERVICE;
AlarmManager am = (AlarmManager) getSystemService(alarm);
Intent intent = new Intent("REFRESH_THIS");
PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0);
int type = AlarmManager.RTC_WAKEUP;
long interval = 1000 * 50;
am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi);
this will call reciver and reciver is,
public class AlarmReceiver extends BroadcastReceiver {
Context context;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
System.out.println("Alarma Reciver Called");
if (isMyServiceRunning(this.context, BackgroundService.class)) {
System.out.println("alredy running no need to start again");
} else {
Intent background = new Intent(context, BackgroundService.class);
context.startService(background);
}
}
public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
if (services != null) {
for (int i = 0; i < services.size(); i++) {
if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) {
return true;
}
}
}
return false;
}
}
And this Alaram reciver calls once when android app is opened and when app is closed.SO the service is like this,
public class BackgroundService extends Service {
private String LOG_TAG = null;
#Override
public void onCreate() {
super.onCreate();
LOG_TAG = "app_name";
Log.i(LOG_TAG, "service created");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "In onStartCommand");
//ur actual code
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// Wont be called as service is not bound
Log.i(LOG_TAG, "In onBind");
return null;
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i(LOG_TAG, "In onTaskRemoved");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroyed");
}
}
when there is no binding to a service or well established foreground then android system recognize the service as unused overloading service that should be shut down. Here is the best way to maintain your service even if the app is closed: AlarmManager or Service
I am looking into how to keep my Android app running in the foreground.
It will be a privately distributed app, so I can do anything possible to make sure it runs constantly on the device (HDMI TV Stick)
So, how can I make sure that the app stays running no matter what? The app is pretty light weight in terms of resource usage, so having it run 24/7 should hopefully not be a problem.
I read about the persistent parameter in the manifest, but it looks like it might only apply to system apps?
Should I make my app a system app? How would I do that and would it help?
If you want an external app use: Autostart and StaY!
If you want to do this programmatically you can use a service that polls every "x" milliseconds to see if your app is in the foreground. If it is not, it will start/bring your app in the foreground. Do it like this:
public class PersistService extends Service {
private static final int INTERVAL = 3000; // poll every 3 secs
private static final string YOUR_APP_PACKAGE_NAME = "YOUR_APP_PACKAGE_NAME";
private static boolean stopTask;
private PowerManager.WakeLock mWakeLock;
#Override
public void onCreate() {
super.onCreate();
stopTask = false;
// Optional: Screen Always On Mode!
// Screen will never switch off this way
mWakeLock = null;
if (settings.pmode_scrn_on){
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "a_tag");
mWakeLock.acquire();
}
// Start your (polling) task
TimerTask task = new TimerTask() {
#Override
public void run() {
// If you wish to stop the task/polling
if (stopTask){
this.cancel();
}
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = activityManager.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
// Check foreground app: If it is not in the foreground... bring it!
if (!foregroundTaskPackageName.equals(YOUR_APP_PACKAGE_NAME)){
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(YOUR_APP_PACKAGE_NAME);
startActivity(LaunchIntent);
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, 0, INTERVAL);
}
#Override
public void onDestroy(){
stopTask = true;
if (mWakeLock != null)
mWakeLock.release();
super.onDestroy();
}
}
The above code has also the "option" to force the Screen to stay always on! Of course you will need the following permissions:
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
and do not also forget to register your service:
<service android:name="YOURPACAKGE.PersistService"
android:enabled="true"/>
use this:
import android.os.PowerManager;
public class MyActivity extends Activity {
protected PowerManager.WakeLock mWakeLock;
/** Called when the activity is first created. */
#Override
public void onCreate(final Bundle icicle) {
setContentView(R.layout.main);
/* This code together with the one in onDestroy()
* will make the screen be always on until this Activity gets destroyed. */
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
this.mWakeLock.acquire();
}
#Override
public void onDestroy() {
this.mWakeLock.release();
super.onDestroy();
}
}
And in the manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Seen here: How do I keep the screen on in my App?
This is something not too easy to achieve as foreground apps are technically not supposed to be running non stop. Also if android is running out of memory it will start killing apps that pose the least risk which would then require the app to be restarted by the user.
As mentioned you could either make it a system app, but I think you do need to root the device or build your own ROM and make your app part of the ROM. Probably not the best solution for your needs though as few people will be able to flash a ROM on to their devices.
I think the easiest solution would be to put in the manifest that your app is a home screen replacement, i.e. a launcher app. I don't know the exact code from the top of my head but this would go into the application section within the android manifest. This would mean that as soon as the device boots, or the user presses the home button, they will be taken to your app.
I solved that issue by having a sticky service running that relaunches the app when the activity is getting closed.
//Your activity
#Override
public void onPause() {
super.onPause();
if (yourservice != null) {
yourservice.validateActivityOnPause();
}
}
and in the validateActivityOnPause() have something like:
//Your service
public void validateLynxActivityOnPause() {
//Do some stuff here
Intent startActivityIntent = new Intent(this, LynxActivity.class);
startActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(startActivityIntent);
}
Now that activityManager.getRunningAppProcesses() is deprecated( as of API21 ), you will want to replace :
RunningTaskInfo foregroundTaskInfo = activityManager.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
with:
List<ActivityManager.RunningAppProcessInfo> tasks = activityManager.getRunningAppProcesses();
String foregroundTaskPackageNameTest = tasks.get(0).processName;
do not forget to import List with:
import java.util.List;
As a side note, I am not sure about OP's way of keeping the screen always on. I'm not sure that it works the way he's done it, but more importantly, it is deprecated and very much advised against to be using Wake Locks as you need to add permissions, which opens the door to bugs. Rather, it is generally better practice to use Window manager flags:
https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_KEEP_SCREEN_ON
You could make your app become a launcher, by adding 2 following category tags into <intent-filter> tags:
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.HOME"/>
then you should always check if there's another app run on top, run following code to direct user to our app:
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
I have tried this solution, but it cannot hide apps that draw on top, like Facebook Messenger chat head.
You may try startLockTask();
For More info, visit here