AlarmManager和BroadcastReceiver的,而不是服务 - 是坏? (时间到) [英] AlarmManager and BroadcastReceiver instead of Service - is that bad ? (Timeout)

查看:164
本文介绍了AlarmManager和BroadcastReceiver的,而不是服务 - 是坏? (时间到)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景资料:

我需要从网络,大约每隔一小时左右,即使在我的应用程序被关闭更新一些数据。数据本身的更新需要约40秒至1分钟。然后将其保存为一个序列化到一个文件中。我的应用程序启动时,该文件被读取。

这是我拍的那一刻(不使用服务)

THE APPROACH

使用AlarmManager和BroadcastReceiver的是这样的:

 私人无效set_REFRESH_DATA_Alarm(){
    mContext = Main.this;
    alarmManager =(AlarmManager)getSystemService(ALARM_SERVICE);
    broadcast_intent =新的意图(mContext,
            RepeatingAlarmReceiver_REFRESH_DATA.class);
    pendingIntent = PendingIntent.getBroadcast(mContext,0,broadcast_intent,0);
    //执行刷新每隔一小时,开始首次在30分钟内从现在开始......
    日历现在= Calendar.getInstance();
    长triggerAtTime = now.getTimeInMillis()+(1 * 30 * 60 * 1000); //开始在30分钟内
    长repeat_alarm_every =(1 * 60 * 60 * 1000); //重复每60分钟
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,triggerAtTime,
            repeat_alarm_every,pendingIntent);
}
 

我的 RepeatingAlarmReceiver_REFRESH_DATA.class 需要从网络更新数据的护理:

 公共类RepeatingAlarmReceiver_REFRESH_DATA扩展的BroadcastReceiver {

    公共静态语境mContext;
    ConnectivityManager mConnectivity;

    @覆盖
    公共无效的onReceive(上下文的背景下,意图意图){
        mContext =背景;
        //如果网络连接正常(Wifi或移动),然后加载数据...
        mConnectivity =(ConnectivityManager)上下文
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        Log.i(枢纽,
                mConnectivity.getNetworkInfo(0)=
                        + mConnectivity.getNetworkInfo(0));
        Log.i(枢纽,
                mConnectivity.getNetworkInfo(1)=
                        + mConnectivity.getNetworkInfo(1));
        如果((mConnectivity.getNetworkInfo(0).getState()== NetworkInfo.State.CONNECTED)
                || (mConnectivity.getNetworkInfo(1).getState()== NetworkInfo.State.CONNECTED)){
            Log.i(中心,连接OK ......);
            Refresh_HIST_DATA();
        } 其他 {
            //否则对话框显示无网络连接...
            Log.i(枢纽,
                    目前没有网络连接...将稍后重试!);
        }
    }

    // ================================================ =========================
    私人无效Refresh_HIST_DATA(){
        Log.i(中心,Refresh_HIST_DATA()......开始......);
        // 等等...
    }
}
 

在清单中,我有:

 <接收器的Andr​​oid版本:NAME =com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA安卓程序=:远程/>
 

问题:

报警被解雇的时间和更新启动,但随后约10秒后停止(超时):

  

11月6日至25日:55:05.278:   WARN / ActivityManager(76):超时   广播BroadcastRecord {44bb4348   空值} -   receiver=android.os.BinderProxy@44bcc670

     

11月6日至25日:55:05.278:   WARN / ActivityManager(76):接收器   在超时:ResolveInfo {44bb42c0   com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA   P = 0°= 0 M =为0x0}

     

11月6日至25日:55:05.278:信息/工艺(76):   发送信号。 PID:819 SIG:9

     

11月6日至25日:55:05.298:   信息/ ActivityManager(76):过程   com.cousinHub.myapp:远程(PID 819)   已经死了。

PS:奇怪的是,这个超时在我的HTC Hero(仍然在Android 1.5 - API等级4),约10秒钟后不会发生,但也对我的Nexus One(2.1 UPDATE1)

问题:

  1. 为什么超时?任何简单的方法来避免这种情况?
  2. 难道我在清单中设置我的BroadcastReceiver是否正确?我是否需要添加一些(为了避免这种超时)?
  3. 如果我绝对去为这样的刷新来自网络功能的服务? (考虑到这篇文章:<一个href="http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/">http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) 如果是(我应该切换到服务)的code /教程任何好的片段为这个...

由于传真,感谢您的帮助。

小时。

解决方案
  

为什么超时?

您的主应用程序线程上运行。超过几秒钟的主应用程序线程上不能运行。此外,虽然这样做,你损害设备的性能(因为你的与前台优先级的运行),例如引起在游戏或视频帧速率损失。

  

任何简单的方法来避免这种情况?

不要做显著的工作(> 100毫秒)主应用程序线程上。让你的的BroadcastReceiver 委托给 IntentService ,也许是的 WakefulIntentService

  

难道我建立了我的BroadcastReceiver   正确的清单?

请请请请请摆脱安卓过程=:远程。你不需要它,它不会帮你,它进一步降低了设备的性能。

  

我应该绝对去服务   对于这种从网页刷新   功能? (考虑到这   文章 :   <一href="http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/">http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/)   如果是(我应该切换到服务):   code /教程任何好的片段   这...

恕我直言,是的。再说,我写的博客文章。举一个例子,请参见 WakefulIntentService 项目。

BACKGROUND INFO:

I need to update some data from the web, about every hour or so, even when my app is closed. The update of the data itself takes about 40 seconds to 1 minute. It is then saved as a Serializable to a file. This file is read when my app starts.

THIS IS THE APPROACH I TOOK FOR THE MOMENT (not using a Service)

use the AlarmManager and BroadcastReceiver like this :

private void set_REFRESH_DATA_Alarm(){
    mContext = Main.this;
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    broadcast_intent = new Intent(mContext, 
            RepeatingAlarmReceiver_REFRESH_DATA.class);
    pendingIntent = PendingIntent.getBroadcast(mContext, 0,  broadcast_intent, 0);
    // do a REFRESH every hour, starting for the first time in 30 minutes from now ...
    Calendar now = Calendar.getInstance();
    long triggerAtTime = now.getTimeInMillis()+ (1 * 30 * 60 * 1000); // starts in 30 minutes
    long repeat_alarm_every = (1 * 60 * 60 * 1000); // repeat every 60 minutes
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 
            repeat_alarm_every, pendingIntent);
}

My RepeatingAlarmReceiver_REFRESH_DATA.class takes care of updating the Data from the Web:

public class RepeatingAlarmReceiver_REFRESH_DATA extends BroadcastReceiver {

    public static Context mContext;
    ConnectivityManager mConnectivity;

    @Override
    public void onReceive(Context context, Intent intent) {
        mContext = context;
        // if Network connection is OK (Wifi or Mobile) then Load data ...
        mConnectivity = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        Log.i("Hub",
                "mConnectivity.getNetworkInfo(0)="
                        + mConnectivity.getNetworkInfo(0));
        Log.i("Hub",
                "mConnectivity.getNetworkInfo(1)="
                        + mConnectivity.getNetworkInfo(1));
        if ((mConnectivity.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED)
                || (mConnectivity.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTED)) {
            Log.i("Hub", "Connectivity OK ...");
            Refresh_HIST_DATA();
        } else {
            // else Show Dialog "No network connection" ...
            Log.i("Hub",
                    "No network connection for the moment... will try again later!");
        }
    }

    // =========================================================================
    private void Refresh_HIST_DATA() {
        Log.i("Hub", "Refresh_HIST_DATA()... Starting ...");
        // etc...
    }
}

In the Manifest I have :

<receiver android:name="com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA" android:process=":remote" />

PROBLEM :

The alarm gets fired on time and the update starts but then after about 10 seconds it stops (Timeout):

06-25 11:55:05.278: WARN/ActivityManager(76): Timeout of broadcast BroadcastRecord{44bb4348 null} - receiver=android.os.BinderProxy@44bcc670

06-25 11:55:05.278: WARN/ActivityManager(76): Receiver during timeout: ResolveInfo{44bb42c0 com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA p=0 o=0 m=0x0}

06-25 11:55:05.278: INFO/Process(76): Sending signal. PID: 819 SIG: 9

06-25 11:55:05.298: INFO/ActivityManager(76): Process com.cousinHub.myapp:remote (pid 819) has died.

ps: strangely enough, this "Timeout" does not happen after about 10 seconds on my HTC Hero (still on Android 1.5 - API Level 4) but well on my Nexus One (2.1-update1)

Questions :

  1. Why this timeout ? Any easy way to avoid this ?
  2. Did I set up my BroadcastReceiver correctly in the manifest ? Do I need to add something (to avoid this timeout) ?
  3. Should I absolutely go for a Service for this kind of "Refresh from Web" functionality ? (considering this article : http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) If YES (I should switch to a service): Any good snippets of code/tutorial for this ...

As allways, thanks for your help.

H.

解决方案

Why this timeout ?

You are running on the main application thread. You cannot run on the main application thread for more than a few seconds. Also, while doing this, you are harming the performance of the device (because you are running with foreground priority), such as causing frame-rate loss in games or videos.

Any easy way to avoid this ?

Don't do significant work (>100ms) on the main application thread. Have your BroadcastReceiver delegate to an IntentService, perhaps a WakefulIntentService.

Did I set up my BroadcastReceiver correctly in the manifest ?

Please please please please please get rid of the android:process=:remote. You do not need it, it is not helping you, and it is degrading performance of the device even further.

Should I absolutely go for a Service for this kind of "Refresh from Web" functionality ? (considering this article : http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) If YES (I should switch to a service): Any good snippets of code/tutorial for this ...

IMHO, yes. Then again, I wrote that blog post. For an example, see the WakefulIntentService project.

这篇关于AlarmManager和BroadcastReceiver的,而不是服务 - 是坏? (时间到)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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