I'm building a corporate app for android TV that I need to have always in the foreground. Every now and then the app will crash along with the service that will relaunch it. Is there a best practice to ensure the app is always running. What I can't figure out is how to launch after a force stop. The app can be side loaded so we don't have to worry about App Store approval.
The problem is when I use a service worker it will also die since it is attached to the original process https://developer.android.com/reference/android/app/Service
Same issue with the https://developer.android.com/topic/libraries/architecture/workmanager
Any ideas on an approach to basically check if the app is running and if it isn't start it up ? Is there any other event that I can hook into to launch the app ?
If a crash happens the app will rerun itself:
class AppExceptionHandler(private val context: Context, private val myActivityClass: Class<*>) :
Thread.UncaughtExceptionHandler {
override fun uncaughtException(thread: Thread, exception: Throwable) {
Logger.d(exception.javaClass.simpleName)
exception.printStackTrace()
val intent = Intent(context, myActivityClass)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
context.startActivity(intent)
//restarting the Activity
Process.killProcess(Process.myPid())
System.exit(0)
}
}
and call from your main activity:
Thread.setDefaultUncaughtExceptionHandler(
AppExceptionHandler(
applicationContext,
MainActivity::class.java
)
)
In this way, I don't think you need to know whether the app is now in the foreground and running but you can get the top running package name in a running service. Also making your app a default launcher could be a workaround.
fun topPackageNameObservable(): Observable<String?>? {
return Observable.fromCallable {
var topPackageName = ""
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val mUsageStatsManager =
getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val stats =
mUsageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_DAILY,
System.currentTimeMillis() - TimeUnit.DAYS.toMillis(
1
),
System.currentTimeMillis() + TimeUnit.DAYS.toMillis(
1
)
)
if (stats != null) {
val mySortedMap: SortedMap<Long, UsageStats> =
TreeMap()
for (usageStats in stats) {
mySortedMap[usageStats.lastTimeUsed] = usageStats
}
if (!mySortedMap.isEmpty()) {
topPackageName = mySortedMap[mySortedMap.lastKey()]!!.packageName
}
} else {
topPackageName = activityManager.getRunningAppProcesses().get(0).processName
}
} else {
topPackageName =
activityManager.getRunningTasks(1).get(0).topActivity.getPackageName()
}
} catch (e: Exception) {
e.printStackTrace()
}
topPackageName
}
}
Try using PackageManager
and getLaunchIntentForPackage()