背景:
第三方应用在 /sdcard/content
中生成文件。
我的应用程序应该监视文件的更改,以便它可以打印内容;因此我需要它不断运行。
问题:
在升级到 10 (Galaxy A20e) 的 android 9 设备上,该服务不会被终止。
在我的主要活动中,我有一个微调器,当调用 onItemSelected
时,我启动服务(如果它尚未启动)并绑定到它:
if(ApplicationPersistence.isServiceStarted) {
refreshNotification()
} else {
startService(Intent(this, MyService::class.java))
bindService(Intent(this, MyService::class.java), this, Context.BIND_AUTO_CREATE or Context.BIND_IMPORTANT)
}
如果您想将其作为前台服务启动,我认为您不需要绑定到服务。
我看到了通知。如果我更改微调器选择,它会更新。
我看到调用了 MyService 的 onStartCommand
。
我看到调用了 MyActivity 的 onServiceConnected
,以及 MyService 的 onBind
。
MyService 的 onStartCommand
作用如下:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if(ApplicationPersistence.isServiceStarted) {
return Service.START_STICKY
}
ApplicationPersistence.fileObserver.startWatching()
// notification initialization here
startForeground(ApplicationPersistence.notificationID, ApplicationPersistence.notification)
ApplicationPersistence.isServiceStarted = true
return Service.START_STICKY
}
ApplicationPersistence
是存储最持久数据的类(它 : Application()
)。
这是我的清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="x.y.z">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:name="x.y.z.ApplicationPersistence"
android:directBootAware="true"
android:persistent="true"
android:persistableMode="persistAcrossReboots"
android:requestLegacyExternalStorage="true">
<activity android:name=".MyActivity">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:directBootAware="true"
android:description="@string/notif4"
android:stopWithTask="false"/>
<receiver android:name=".Receiver"></receiver>
</application>
</manifest>
由于 android 10 上的存储权限,我将标记为 19/21。
我尝试使用 PowerManager 无济于事。 WakefulReceiver 排除了我没有使用的 IntentService,因为它会在处理 Intent 后终止。我没有注意到任何 battery optimization 问题,因为我已经禁用了所有我能找到的。 WorkManager 有一个 15m minimum retry time 这使得它无用于此目的。使用 separate process 也不起作用,我丢失了我发布的信息 到通知。
我是否遗漏了一些明显的东西?音乐应用可以做到...
编辑 1
对于阿尔卡特,我在日志中看到的最后一个操作是当我点击主页按钮时调用 MyActivity
的 onPause()
。我刷的时候没有反应。
对于三星,当我滑动时,我看到
D/MyActivity: onDetachedFromWindow()
D/MyService: onTaskRemoved()
android.app.ServiceConnectionLeaked: Activity x.y.z.MyActivity has leaked ServiceConnection x.y.z.MyActivity@ce48f05 that was originally bound here
...
at x.y.z.MyActivity.onItemSelected(MyActivity.kt:201) // the bindService call
...
D/MyService: onUnbind(null)
Edit2
如果我检查服务 is foreground,它显然在两个设备上都不是,但是,adb 会说相反。
三星
* ServiceRecord{92e7bc9 u0 x.y.z/.MyService}
intent={cmp=x.y.z/.MyService}
packageName=x.y.z
processName=x.y.z
baseDir=/data/app/x.y.z-3i0pcMiZVFi-apzWGR-5hw==/base.apk
dataDir=/data/user/0/x.y.z
app=ProcessRecord{8f822ce 20490:x.y.z/u0a210}
isForeground=true foregroundId=1 foregroundNoti=Notification(channel=x.y.z pri=2 contentView=null vibrate=null sound=null defaults=0x0 flags=0x62 color=0x00000000 category=service vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0)
createTime=-13m56s837ms startingBgTimeout=--
lastActivity=-13m56s829ms restartTime=-13m56s837ms createdFromFg=true
startRequested=true delayedStop=false stopIfKilled=false callStart=true lastStartId=1
Bindings:
* IntentBindRecord{b830b66 CREATE}:
intent={cmp=x.y.z/.MyService}
binder=android.os.BinderProxy@b291ea7
requested=true received=true hasBound=true doRebind=false
* Client AppBindRecord{4031f54 ProcessRecord{8f822ce 20490:x.y.z/u0a210}}
Per-process Connections:
ConnectionRecord{8ee48fc u0 CR IMP x.y.z/.MyService:@595c5ef}
All Connections:
ConnectionRecord{8ee48fc u0 CR IMP x.y.z/.MyService:@595c5ef}
阿尔卡特
* ServiceRecord{7872f83 u0 x.y.z/.MyService}
intent={cmp=x.y.z/.MyService}
packageName=x.y.z
processName=x.y.z
baseDir=/data/app/x.y.z-tB_tv4YEDBranjBzPXNqeg==/base.apk
dataDir=/data/user/0/x.y.z
app=ProcessRecord{bc00038 7463:x.y.z/u0a182}
isForeground=true foregroundId=1 foregroundNoti=Notification(channel=x.y.z pri=2 contentView=null vibrate=null sound=null defaults=0x0 flags=0x62 color=0x00000000 category=service vis=PRIVATE)
createTime=-26m9s402ms startingBgTimeout=--
lastActivity=-26m9s397ms restartTime=-26m9s402ms createdFromFg=true
startRequested=true delayedStop=false stopIfKilled=false callStart=true lastStartId=1
Bindings:
* IntentBindRecord{5de8688 CREATE}:
intent={cmp=x.y.z/.MyService}
binder=android.os.BinderProxy@1ece821
requested=true received=true hasBound=true doRebind=false
* Client AppBindRecord{b1f1446 ProcessRecord{bc00038 7463:x.y.z/u0a182}}
Per-process Connections:
ConnectionRecord{3c96139 u0 CR IMP x.y.z/.MyService:@75b5500}
All Connections:
ConnectionRecord{3c96139 u0 CR IMP x.y.z/.MyService:@75b5500}
vis=PRIVATE
之后有区别,仅此而已。
编辑 3
在大多数情况下,该服务似乎在前台运行。
我还在服务的 Binder 中实现了一个方法,该方法只是等待随机时间(1-2 秒)并返回等待时间。
反过来,这由线程内的绑定类(我的 : Application()
)使用,该线程在调用 Binder 方法之前等待 3-4 秒。
这样我每 3 秒左右就会获得一次“服务器/客户端”交互,但是如果我滑动所有应用程序,该应用程序仍然会在 Android 10 上被杀死。
编辑 4
我还通过 我使用过 filter.addAction()
在我的 Activity 中注册了很多随机广播,以尝试使其保持活动状态。filter.addAction(Intent.ACTION_TIME_TICK)
但滑动总是会杀死应用。
这意味着日志停止,没有 onMethod (我已经覆盖)被调用;通知不见了;该服务不再运行。
答案 0 :(得分:0)
使用 startForeground(id, notification);
我希望它能在我的一个应用中正常工作。