如何让一个前台应用程序持续运行24/7?

20

我正在研究如何让我的Android应用程序保持在前台。

这将是一个私人分发的应用程序,所以我可以尽可能地确保它在设备上不断运行(HDMI电视棒)

那么,我该如何确保无论如何都能让应用程序持续运行?该应用程序在资源使用方面相当轻量级,因此希望全天候运行不应该成为问题。

我了解到清单文件中的persistent参数,但似乎只适用于系统应用程序?

我应该把我的应用程序变成系统应用程序吗? 如何操作并且是否有帮助?


1
我相信只有在设备已经取得root权限的情况下,你才能将你的应用变成系统应用。你可以考虑将你的应用作为主屏幕替代品,就像一个专门的展示模式应用程序。请参阅我的答案这里 - TronicZomB
7个回答

15
  • 如果您想使用外部应用程序,请使用:Autostart and StaY!

  • 如果您想以编程方式执行此操作,可以使用一个服务,每隔 "x" 毫秒轮询以查看您的应用程序是否在前台。如果不是,则会启动/将您的应用程序带到前台。请按照以下方式操作:

  • 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();
        }
    }
    

以上代码还有"选项",可以强制屏幕始终保持开启状态!当然,您需要以下权限:

<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

不要忘记注册您的服务:

    <service android:name="YOURPACAKGE.PersistService" 
     android:enabled="true"/>

好的回答,那么这种方式会让应用程序保持运行状态,即使它是不可见的(另一个应用程序正在运行)吗? - Dania
1
如果程序根本没有运行或在后台运行,它将被恢复,即将其带到前台。 - Tanasis
好的回答,但是我唯一遇到的问题是当收到电子邮件通知时,例如,我可以选择该电子邮件并将其设置为前台应用程序。我如何禁用它? - Meir
看起来应用程序AutoStart和Stay不幸已经不存在了。 - FlorianB
1
@Tanasis 先生,如何声明 activityManager? - Jamebes
activityManager 没有声明。代码不起作用。添加:final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); - Fəqan Çələbizadə

3
使用这个:
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();
    }
}

在清单文件中:
<uses-permission android:name="android.permission.WAKE_LOCK" />

在此处看到:我的应用程序如何保持屏幕常亮?

1
这不是 OP 想要的。他想让他的应用程序永久运行,而这只会在他的应用程序运行时保持屏幕开启,但设备的用户将能够转到其他应用程序。 - Boardy
但是一旦它运行,它应该无限期地准确运行?否则,处理OnDestroy和一些broadcastReceivers以启动应用程序(如果它不在前台)可能是一个选项。 - Thkru
用户可以按下主页按钮并使用设备上可能安装的其他应用程序,因此将 OP 应用程序置于后台,没有任何阻止用户这样做的措施。 - Boardy
Thomas - 感谢您的建议,但正如Broady所说,您误解了。保持屏幕常亮是我的应用程序的一部分,但这与我需要解决的问题不同。遗憾的是,即使使用您的代码,如果系统需要内存,应用程序仍然可能被关闭。 - Mr Pablo

2
我通过运行一个粘性服务来解决这个问题,当活动被关闭时,该服务会重新启动应用程序。
//Your activity

@Override
public void onPause() {
    super.onPause();

    if (yourservice != null) {
        yourservice.validateActivityOnPause();
    }
}

在validateActivityOnPause()方法中,需要添加类似以下内容的代码:
//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);
}

2
这是一件不太容易实现的事情,因为前台应用程序从技术上讲不应该一直运行。此外,如果Android内存不足,它将开始杀死风险最小的应用程序,这将需要用户重新启动应用程序。
正如提到的,你可以将其制作成系统应用程序,但我认为你需要root设备或构建自己的ROM并使你的应用程序成为ROM的一部分。然而,这可能不是你所需的最佳解决方案,因为很少有人能够在他们的设备上刷入ROM。
我认为最简单的解决方案是在清单中添加你的应用程序是一个主屏幕替换程序,即启动器应用程序。我不知道精确的代码,但这将进入Android清单中的应用程序部分。这意味着一旦设备启动或用户按下主屏幕按钮,他们将被带到你的应用程序。

1
OP可能还需要记住的是,在使用自定义主屏替换后,可能会在启动后出现问题(至少我遇到了这个问题)。这是我的经验以及如何解决它的方法。 - TronicZomB

1

现在 activityManager.getRunningAppProcesses() 已经被弃用(从 API21 开始),您需要替换为:

RunningTaskInfo foregroundTaskInfo = activityManager.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();

使用:

List<ActivityManager.RunningAppProcessInfo> tasks = activityManager.getRunningAppProcesses();
String foregroundTaskPackageNameTest = tasks.get(0).processName;

不要忘记使用以下代码导入List:

import java.util.List;

作为一个旁注,我不确定 OP 保持屏幕常亮的方式是否有效。我不确定他所做的方式是否有效,但更重要的是,使用 Wake Locks 已经过时并且强烈建议不要使用,因为您需要添加权限,这会导致漏洞。相反,通常最好使用 Window Manager 标志:https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_KEEP_SCREEN_ON

0

你可以通过在<intent-filter>标签中添加以下2个类别标签,使你的应用程序成为一个启动器:

  <category android:name="android.intent.category.DEFAULT"/>
  <category android:name="android.intent.category.HOME"/>

那么你应该始终检查是否有其他应用程序在顶部运行,运行以下代码将用户引导到我们的应用程序:

  Intent startMain = new Intent(Intent.ACTION_MAIN);
  startMain.addCategory(Intent.CATEGORY_HOME);
  startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(startMain);

我尝试过这个解决方案,但它无法隐藏那些在顶部绘制的应用程序,比如Facebook Messenger的聊天头。


0

你可以尝试使用 startLockTask(); 更多信息,请点击此处


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