У меня проблема с приемником трансляции, который получил трансляцию от AlarmManager
. Моя настройка включает в себя активность, службу переднего плана и приемник вещания. Когда широковещание получено, Android убивает мой процесс и обрабатывает широковещание в новом.
Чтобы воспроизвести проблему, I:
- запустите приложение;
- нажмите кнопку в главном окне, чтобы установить будильник;
- нажмите кнопку «Домой» (в этот момент запускается служба переднего плана и отображается уведомление);
- удаляет приложение из последних записей (служба переднего плана продолжает работать);
- В момент трансляции Через 10 секунд android убивает процесс (можно увидеть в Logcat) и немедленно запускает новый, где обрабатывается передача).
Если пропустить шаг 4 ( то есть я не удаляю приложение из последних записей), тогда вещание обрабатывается в том же процессе.
Я наблюдаю это поведение только в API 21 и 22. В настоящее время я по какой-то причине не могу загрузить изображения Marshmallow, поэтому Я не могу протестировать в API 23.
Однако в API 24 и выше широковещательная передача всегда принимается в одном и том же процессе.
Я не могу найти объяснение в документации. В моем понимании трансляция должна обрабатываться в моем основном потоке, если я явно не установлю process
для получателя.
Вот код моего приложения:
class MainActivity : AppCompatActivity() {
//...
override fun onResume() {
super.onResume()
val intent = Intent(this, ForegroundService::class.java)
stopService(intent)
}
override fun onPause() {
super.onPause()
val intent = Intent(this, ForegroundService::class.java)
ContextCompat.startForegroundService(this, intent)
}
fun onClick(view: View) {
val alarmManager = ContextCompat.getSystemService(this, AlarmManager::class.java)!!
val intent = Intent(this, SampleReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0,intent, 0)
val time = System.currentTimeMillis() + 10_000
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, RTC_WAKEUP, time, pendingIntent)
}
}
class ForegroundService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
val notificationManager = ContextCompat.getSystemService(this, NotificationManager::class.java)!!
val channelId = "mychannel"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, "alarm", NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(this, channelId)
.setContentTitle("Title")
.setContentText("Text")
.setSmallIcon(R.drawable.ic_access_alarms_black_24dp)
.build()
Log.d("ForegroundService", "Starting foreground service")
startForeground(1, notification)
return START_STICKY
}
//...
}
class SampleReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("SampleReceiver", "onReceive called")
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testbr">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver
android:name=".SampleReceiver"
android:enabled="true"
android:exported="false" />
<service
android:name=".ForegroundService"
android:enabled="true"
android:exported="false" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>