如何在前台服务中将应用程序带到前台

3
我有一个ForegroundService,需要一些时间来运行。在此期间,用户可能会将应用程序移到后台,例如按下主页按钮或进入其他应用程序。当ForegroundService达到“触发器”时,它尝试启动一个新的意图。如果应用程序在前台运行,则这很好,但如果在后台运行,则无法正常工作。目标是当达到“触发器”时,应用程序将返回到前台,以便用户可以在新的意图中提供所需的输入。为此,我添加了FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_SINGLE_TOP标志,因为它们看起来可以完成此操作。但是,应用程序没有回到前台。是否可以做到这一点?
以下是相关的代码部分:
MainActivity.kt
...
private fun startService() {
    val serviceIntent = Intent(this, ForegroundService::class.java)
    ContextCompat.startForegroundService(this, serviceIntent)
}
...

ForegroundService.kt
...
//When trigger is reached, start the new activity and bring app to foreground if it was moved to background
private fun startNewActivity() {
    //First two lines are to shut down the foreground service since it has reached a trigger and is complete.
    super.onDestroy()
    stopSelf()
    //Start the new intent
    val startNewIntent = Intent(this, NewIntent:: class.java)
    startNewIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP //Assumption was these flags would bring app to foreground
    startActivity(startNewIntent)
}
...
2个回答

1
如果您正在使用 Android 10 及以上版本,您需要请求 android.permission.SYSTEM_ALERT_WINDOW 权限。可以使用以下方式授予权限。
// Check if the permission is granted
if (Settings.canDrawOverlays(this)) {
    // Permission is granted, start your service
    startService(new Intent(this, FloatingViewService.class));
} else {
    // Permission is not granted, ask the user to enable it
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
            Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, REQUEST_CODE);
}

// Handle the result of the user's action
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE) {
        // Check if the permission is granted
        if (Settings.canDrawOverlays(this)) {
            // Permission is granted, start your service
            startService(new Intent(this, FloatingViewService.class));
        } else {
            // Permission is denied, show a message
            Toast.makeText(this, "Please enable overlay permission", Toast.LENGTH_SHORT).show();
        }
    }
}

https://developer.android.com/reference/android/Manifest.permission#SYSTEM_ALERT_WINDOW


很好。这适用于使用Android 10和12的设备。targetSdkVersion为33。 - RudyF

0
为了使意图被注册到系统中,你需要使用一个PendingIntent而不是普通的Intent;当前台服务结束时(当触发器被触发时),你可以使用send()方法发送这个待定意图。
ForegroundService.kt
...
//When trigger is reached, start the new activity and bring app to foreground if it was moved to background
private fun startNewActivity() {
    //First two lines are to shut down the foreground service since it has reached a trigger and is complete.
    super.onDestroy()
    stopSelf()
    
    
    //Start the new intent

    val startNewIntent = Intent(this, NewIntent:: class.java)
    val pendingIntent = PendingIntent.getActivity(
        this, 0, startNewIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
                or PendingIntent.FLAG_ONE_SHOT
    )
    
    try {
        pendingIntent.send()  // this should start `NewIntent` activity
    } catch (e: CanceledException) {
        e.printStackTrace()
    }   
    
}
... 

谢谢你的帖子。我尝试实现了这个功能,但发现它的行为与之前一样。换句话说,即使调试日志显示pendingIntent.send()被调用,应用程序仍然无法通过PendingIntent返回到前台。我找到了这个参考链接,其中提到“在发送待定意图后的几秒钟内,应用程序可以启动活动”。听起来应该是可以工作的。 - Tom
此外,调用了pendingIntent.send(),但是直到我手动将应用程序重新聚焦,NewIntent中的onCreate才会被调用。这是通过日志记录确定的。 - Tom
好像有点奇怪...你能在另一台设备上测试一下,使用不同的API级别吗?也许你需要将BroadcastReceiver包装在PendingIntent中发送。并且在onReceive()方法中执行相同的代码。 - Zain
1
我在API v16中进行了测试,它运行正常。但是在模拟器和实际设备上使用API v30进行测试时,它无法工作。我想知道是否有新版本中的更改阻止了它的运行?你有使用包装了待定意图的BroadcastReceiver的示例吗? - Tom
@Tom,API级别29(Android 10)发生了变化,详细说明在这里:https://developer.android.com/guide/components/activities/background-starts 它列出了一系列条件,其中必须满足其中之一才能将应用推至前台。 - hotfire42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接