uni-app如何实现前台service以做到应用保活

发布于 1周前 作者 eggper 来自 Uni-App

uni-app如何实现前台service以做到应用保活

启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification,用来让用户知道有这样一个App在运行着,哪怕当前的App退到了后台。也能在通知栏看到app运行着,做到app 保活

23 回复

最简单的保活,后台循环播放一个无声的mp3,如果用背景音乐播放在通知栏也会有提示,无声的mp3网上可以下载


兄弟,你是真牛,这个方法很好使,解决了我的问题,简单便捷有效。

回复 h***@163.com: 会不会很耗电?

回复 h***@163.com: 安卓不行吧,ios倒是没问题。

你好,这个方法我用了。ios下确实是可以的。你是否试过安卓,我试了,最多保活20分钟。

给大家提供一个详细的,自己的实现过程哈,android端完美前台保活: 1.首先需要实现一个原生插件,原生插件需要拉起一个前台service,然后uniapp侧引入,执行暴露给js的方法即可,下面是详细配置+代码:希望帮助到大家

android 原生侧:基于官方sdk,app模块目录下assets下的uniplus那个json文件: { “hooksClass”: “包名.你的那个module类名”, “plugins”: [ { “type”: “module”, “name”: “随便起一个service的名字”, “class”: “包名.你的那个module类名” } ] }

然后是你自己新建的模块:比如你要实现一个Module,叫做MyModule(可以基于sdk那个module直接拷贝过来改),mainfest权限文件

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.github.alexkitc.xxxservice(包名)">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application> <service android:name=".实现service接口的类名(注意前面的点)" android:exported="true" /> </application>

</manifest> 4。然后是实现UniModule的类 public class xxxPluginModule extends UniModule { public Context context;

public xxxPluginModule () {
super();
}

@UniJSMethod(uiThread = true)
public void startxxxService(UniJSCallback callback) {

if (context == null && mUniSDKInstance != null) {  
    context = mUniSDKInstance.getContext();  
}  

try {  
    Intent intent = new Intent(context, xxxService.class);  

    //开启前台service(非activity需要使用this.mUniSDKInstance.getContext()上下文间接启动)  
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {  
        context.startForegroundService(intent);  
    } else {  
        // 安卓7兼容  
        context.startService(intent);  
    }  
} catch (Exception e) {  
    Log.e("err", e.getMessage());  
}  

}
}

xxxService 需要实现Service,比如我的场景 public class xxxService extends Service { 里面实现一个本地的socket(使用单独的线程开启监听)内部逻辑换成你自己的即可 }

然后android studio右侧的gradle打包(other的assebleRelase)即可得到build目录下xxx.aar文件,拷贝到hbuilder那边的uniapp工程,具体目录为工程下的nativeplugins下的xxxModule/android下,aar放这儿,然后还需要一个package.json放在xxxModule根目录,跟android目录同级,内容如下
{ “name”: “xxxModule”, “id”: “xxxModule”, “version”: “1.0.0”, “description”: “xxx service”, “_dp_type”:“nativeplugin”, “_dp_nativeplugin”:{ “android”: { “plugins”: [ { “type”: “module”, “name”: “xxxModule”, “class”: “io.github.alexkitc.xxx实现unimodule的那个类名” } ], “abis”: [ “armeabi-v7a”, “arm64-v8a”, //注意这儿可能影响pc模拟器运行 “x86” ], “integrateType”: “aar”
}

}
}
然后hbuilder这边mainfest选择本地插件,然后制作自定义基座,然后运行后,在js需要的地方 const xxxService = uni.requireNativePlugin(“xxxModule”) const result = xxxService.startxxxService() 就可以拉起原生的service啦, 亲测通过,其实核心就是非activity上下文,context的处理。有了context就好办了。有不懂的再跟哈,我也是第一次给uniapp写原生插件,感觉二者之间的调试日志不是很直观

我也遇到这样的问题,麻烦能给个完整的代码吗,尤其是 xxxService 需要实现Service,比如我的场景 public class xxxService extends Service { 里面实现一个本地的socket(使用单独的线程开启监听)内部逻辑换成你自己的即可 } 这一块不太明白

可以写一个原生插件。不过通知栏也不一定有权限可以写入。unipush是目前推送信息送达率最高的方案

个人对安卓技术是小白。。。这个难搞了

大神可以给个例子指导下么

回复 CJ7235: 哥们这个问题有眉目了吗? 我也有这个需求,不行的话可以一起找人写安卓原生插件

回复 5***@qq.com: 需求被我推掉了,我个人没实现出来

回复 CJ7235: 保活需求本来就是流氓需求,我们改变策略了,只要安卓实现离线推送就好了。

回复 5***@qq.com: 兄弟,那你们实现了安卓离线推送了吗

回复 CJ7235: 我现在被要求做进程辅助保活之类。。无从下手

回复 5***@qq.com: 我们有一个通话录音的问题,估计是需要设置应用处于前台,也是挺麻烦。要不然录音的根本就没声音。

后台保活、不保证所有场景下有效(ios) :https://ext.dcloud.net.cn/plugin?id=9118

uniapp的权限配置压根没有android.permission.FOREGROUND_SERVICE这个权限,前台保活也用不了吧,android9以上都需要有这个权限

在uniapp权限配置,额外添加权限那边硬写。我是写在最后了,目前测试后台保活还行(取消省电策略之后),能保持后台,锁屏运行一个半小时。(应该能更长时间,但是我半路没忍住点进去了) <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

默认系统应用呢?

在uni-app中实现前台Service以尝试做到应用保活是一个复杂且需谨慎处理的问题。由于操作系统的限制,特别是在iOS上,后台长时间运行任务受到严格限制。而在Android上,虽然相对宽松,但也存在电池优化和内存管理等机制来限制后台行为。

不过,为了尽量延长应用在前台的活跃时间,可以通过一些技术手段来模拟或增强前台Service的行为。以下是一个简化的示例,展示如何在uni-app中结合原生插件来实现一个类似前台Service的功能,主要适用于Android平台。

步骤1:创建原生插件

首先,你需要创建一个Android原生插件。这里假设你已经熟悉如何创建和集成uni-app原生插件。

Android插件代码示例(ForegroundServicePlugin.java)

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import androidx.core.app.NotificationCompat;

public class ForegroundServicePlugin extends Service {
    private static final int NOTIFICATION_ID = 1;
    private static final String CHANNEL_ID = "ForegroundServiceChannel";

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
        startForeground(NOTIFICATION_ID, getNotification());
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                CHANNEL_ID,
                "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
            );
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(serviceChannel);
        }
    }

    private Notification getNotification() {
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

        return new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("App is running")
            .setContentText("In foreground service")
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentIntent(pendingIntent)
            .build();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

步骤2:在uni-app中调用原生插件

在uni-app中,你可以通过plus.android.importClass等方法调用这个插件,启动前台Service。

uni-app调用示例

const main = plus.android.runtimeMainActivity();
const Intent = plus.android.importClass('android.content.Intent');
const serviceIntent = new Intent(main, plus.android.importClass('com.yourpackage.ForegroundServicePlugin'));
main.startService(serviceIntent);

请注意,这只是一个基础示例,实际开发中可能需要处理更多细节,比如生命周期管理、权限请求、以及在不同Android版本上的兼容性处理等。此外,iOS上由于系统限制,无法实现类似Android前台Service的功能。

回到顶部