无法使用Alarmmanager定期在后台工作 [英] Cannot do work in background periodically with alarmmanager

查看:124
本文介绍了无法使用Alarmmanager定期在后台工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想按小时在后台调用服务.

I want to call a service in background by the hour.

第一个问题是警报管理器无法正常工作.计时器很糟糕,有时很早,有时又很晚.

first problem is alarm manager is not working smoothly. Timer is terrible, sometimes early sometimes later.

第二个问题是,RemoteServiceException:Context.startForegroundService()然后没有调用Service.startForeground(),我不明白为什么会收到此异常

second problem is, RemoteServiceException : Context.startForegroundService() did not then call Service.startForeground() , I cant understand why I get this exception

MainActivity

MainActivity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        Intent intent1 = new Intent(MainActivity.this, AlarmReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60 * 60 * 1000L, pendingIntent);
    }
}

AlarmReceiver

AlarmReceiver

public class AlarmReceiver extends BroadcastReceiver {

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onReceive(Context context, Intent intent) {

        Intent downloadService = new Intent(context, CallService.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(downloadService);
        } else {
            context.startService(downloadService);
        }

    }

}

CallService

CallService

public class CallService extends IntentService {

    public CallService() {
        super("");
    }

    public CallService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(Intent workIntent) {
        Log.d("Now : ", Calendar.getInstance().getTime().toString());



    }
}

清单

 <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=".AlarmReceiver"/>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".CallService"
            android:exported="false"/>

对不起,我的英语不好.感谢您的帮助或建议.我不知道我该怎么做.我只是定期打电话给服务

Sorry for my terrible english. Thanks for any help or suggestion. I dont know how can I do different way. I just only call a service periodically

推荐答案

AlarmManager将在api 27(oreo 8.1)及更低版本的api上正常运行.只需设置以下内容即可:

AlarmManager will be works normally on api 27 (oreo 8.1) and less. Just setup with something like that:

public void setupAlarm(Context context, long triggerAtMillis) {
    PendingIntent pendingIntent = getPendingIntent(context);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
    } else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
    } else {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
    }
}

别忘了每次触发 AlarmReceiver 时都需要重新设置警报.但是该代码将无法在api 28及更高版本(pie 9.0)上运行.发生这种情况是因为Android Pie中引入了电源管理功能.在后台运行的应用程序中引入了严格的限制.在此处中解释了这些限制.尝试使用JobScheculer调用前台的IntentService.

Don't forget that you need to setup your alarm again every time when your AlarmReceiver triggered. But that code will not be working on api 28 and more (pie 9.0). This is happening because of Power management feature introduced in Android Pie. Strict restrictions are introduced on the apps running in background. These restrictions are explained here. Try to use JobScheculer to invoke your foreground IntentService.

关于第二个问题.您需要在您的 CallService 中发出通知.只需将此onCreate添加到您的 IntentService :

As about your second question. You need to make a notification in your CallService. Just add this onCreate to your IntentService:

@Override
public void onCreate() {
    super.onCreate();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel chan = new NotificationChannel("test", "your_channel_name", NotificationManager.IMPORTANCE_NONE);
        NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (manager != null) {
            manager.createNotificationChannel(chan);
        }

        Notification.Builder notificationBuilder = new Notification.Builder(context, "test");
        notificationBuilder.setOngoing(true);
        notificationBuilder.setContentTitle("Updatig")
                .setContentText("Wait for finish updating")
        startForeground(NOTIFICATION_ID, notificationBuilder.build());
    }
}

如果您在startForegroundService之后不调用服务中的startForeground(您有5秒钟的时间进行调用),则会引发RemoteServiceException.

RemoteServiceException will be thrown if you will not call startForeground in service (you have 5 seconds to make this call) after startForegroundService.

这篇关于无法使用Alarmmanager定期在后台工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆