uni-app如何实现前台service以做到应用保活
uni-app如何实现前台service以做到应用保活
启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification,用来让用户知道有这样一个App在运行着,哪怕当前的App退到了后台。也能在通知栏看到app运行着,做到app 保活
最简单的保活,后台循环播放一个无声的mp3,如果用背景音乐播放在通知栏也会有提示,无声的mp3网上可以下载
兄弟,你是真牛,这个方法很好使,解决了我的问题,简单便捷有效。
非常感谢
回复 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>
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的功能。