【问题标题】:Improve BroadcastReceiver + AlarmManager改进 BroadcastReceiver + AlarmManager
【发布时间】:2015-02-03 21:36:44
【问题描述】:

自从我开始使用 AlarmManager + BroadcastReceiver 后,我的应用程序出现了一些延迟/黑屏。我有 2 个 BroadcastReceiver,一个用于手机重启时,另一个用于 AlarmManager 在给定时间段内调用以向服务器发送数据。

这是BootReceiver在手机重启后启动alarmManager的代码(到目前为止它正在工作):

private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";

@Override
public void onReceive(Context context, Intent intent) {
    // when the boot is completed, restart the alarm manager
    if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
        SharedPreferences mPrefs = context.getSharedPreferences("GPS_TRACKING", Context.MODE_PRIVATE);
        if (mPrefs.getBoolean("hasGeolocation", false) && 
                !mPrefs.getBoolean("isThreadOn", false)){
            EngineerTracker tracker = new EngineerTracker(context); 
            try {
                tracker.startEngineerTrackingLocation();
            } catch (ApplicationException e) {
                e.printStackTrace();
            }
        }
    }
}

报警管理器的启动和停止方法是这样的:

    public void startEngineerTrackingLocation() throws ApplicationException{
    PendingIntent pendingIntent = null;
    AlarmManager manager = null;
    ProjectGeospatialConfig geospatialConfig;

    // check if the intent is running, if it is not, start it
    if (PendingIntent.getBroadcast(context, 0, 
            new Intent(context, EngineerGeospatialTrackingReceiver.class), 
            PendingIntent.FLAG_NO_CREATE) == null){

        // fetch the geospatial configuration, it may come null, so verify before using
        geospatialConfig = getFirstFoundGeospatialConfiguration();

        // if not null and use gps
        if (geospatialConfig != null && geospatialConfig.isUseGps()){
            // session information
            SessionInformationDTO sessionInformation = dao.getObjectForKey(SqlLiteStorageKey.USER_INFORMATION);
            Integer currentResourceId = sessionInformation.getSecurityHandler().getCurrentUser().getId();

            // Retrieve a PendingIntent that will perform a broadcast and add resource id as extra
            Intent alarmIntent = new Intent(context, EngineerGeospatialTrackingReceiver.class);
            alarmIntent.putExtra("resourceId", currentResourceId.toString());

            // set pending intent
            if (pendingIntent == null){
                pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
            }

            // set manager
            if (manager == null){
                manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            }

            // set interval between alarms
            int interval = (geospatialConfig.getGpsTrackingInterval() *1000) * 60;

            // set alarm repetition
            manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 
                        interval, pendingIntent);

            // set variables for gps tracking
            SharedPreferences mPrefs = getApplicationContext().getSharedPreferences("GPS_TRACKING", Context.MODE_PRIVATE);
            Editor editor = mPrefs.edit();

            // these variables will be measured once db is set
            editor.putBoolean("hasExecuted", false);
            editor.commit();        
        }
    }       
}

到目前为止,两者都在工作,该标志旨在知道服务何时执行一次,并且不会再次尝试基本活动(所有活动的模板)

在警报管理器中调用以在定义的时间间隔内发送信息的广播是这样的:

public class EngineerGeospatialTrackingReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    String resourceId = intent.getStringExtra("id");
    sendLocation(context, resourceId);
}

private void sendLocation(final Context context, final String resourceId){      
    new RemoteRequestTask<Void>(null, false, null) {

        @Override
        public Void executeTask() throws ApplicationException {
            // working code
        }

        @Override
        public void completed(Void refreshed) {
        }

        @Override
        public void onException(final ApplicationException ex) {
        }
    }.start();
}}

两个接收器均已添加到 AndroidManifest。除了缓慢之外,当我从一个活动过渡到另一个活动时,我也会遇到黑屏。

【问题讨论】:

    标签: android broadcastreceiver alarmmanager


    【解决方案1】:

    使用 Traceview 确定您将时间花在哪里,并考虑启用 StrictMode 以指出您在主应用程序线程上做的不幸事情。

    您希望onReceive() 非常快,最好在 1 毫秒以下。但是,看起来您可能正在那里进行数据库 I/O(例如,对 dao 的引用),这意味着工作应该在主应用程序线程之外处理,可能由您从 @987654325 开始的 IntentService @。

    【讨论】:

    • 感谢您的回答,我会在这里尝试并发布结果。一个问题,IntentService 是否总是在替代线程中运行,还是它与应用程序使用相同?
    • @AndreFróes:onHandleIntent() 始终在由IntentService 提供的后台线程中运行。生命周期方法,如 onCreate(),在主应用程序线程上运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多