通过服务接收更新活动

时间:2013-09-08 04:51:39

标签: android broadcastreceiver android-service

我的应用程序使用IntentService来处理传入的Google Cloud Messaging消息。目前,每当我通过onHandleIntent()函数收到消息时,我都会创建通知。通知会打开特定活动,然后执行一些计算并更新UI。我正在尝试使我的实现如果我已经在Activity上打开通知,那么服务应该能够更新UI而无需发送通知。我假设我可以使用广播接收器来执行此操作,但我不确定如何实现它,以便它应该仅在活动正在运行时更新活动,否则它应该发布通知。

我不确定如何执行以下操作:

  1. 检查特定活动是否已在运行。

  2. 如果活动已在运行,则无需致电startActivity()

  3. 执行所需的计算和用户界面更新

    编辑:我对代码进行了一些更改,但是我没有看到我在onReceive()方法中添加的logcat消息。

    我已将以下代码添加到IntentService类中的onHandle()函数中:

    Intent in = new Intent("com.example.gcm.DataActivity");
    sendBroadcast(in);
    

    “com.example.gcm”是我的包名,DataActivity是活动的名称。

    我已将以下代码添加到我的活动中:

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        Log.d(TAG, "start");
          receiver = new BroadcastReceiver() {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                // TODO Auto-generated method stub
                Log.d(TAG, "notif received");
            }
    
        };
    
    }
    
    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        unregisterReceiver(receiver);
    }
    

3 个答案:

答案 0 :(得分:1)

正如所承诺的那样简单: 你基本上同步发送广播,如果有接收者,你将在你的服务类中设置一个静态标志,让服务知道它已经处理好了:

public class TestService extends IntentService {
    public volatile static boolean isHandled = false;
    public static final String INTENT_ACTION_HANDLEGCM = "com.intentexample.gcm";

    ...

    @Override
    protected void onHandleIntent(Intent intent) {
        ...
        Intent toActivityIntent = new Intent();
        toActivityIntent.setAction(INTENT_ACTION_HANDLEGCM);
        // toActivity: put other stuff into extras, which you need to update your UI
        TestService.isHandled = false;
        LocalBroadcastManager.getInstance(this).sendBroadcastSync(toActivityIntent);
        if (!TestService.isHandled) {
            // post your notification to the notification bar
        }
    }
}

并注册&在您的活动onResume和onPause中取消注册广播接收器和INTENT_ACTION_HANDLEGCM的意图过滤器(记得使用LocalBroadcastManager)

public class MyActivity extends Activity {
    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            TestService.isHandled = true;
            // update the UI
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter(TestService.INTENT_ACTION_HANDLEGCM));
    }

    @Override
    protected void onPause() {
        super.onPause();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
    }
}

注意:此代码未经测试,但应该给您一般的想法。我个人不会这样做,除了:

  • 在时间压力下
  • 该功能是次要功能,不会很快延长。

答案 1 :(得分:0)

我已在应用中通过使用SharedPreferences值来管理此活动是否可见:

    @Override
protected void onStart() {
    super.onStart();

    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    SharedPreferences.Editor editor = preferences.edit();
    editor.putBoolean("RVisibleNow",true);
    editor.commit();
}

    @Override
protected void onStop() {

    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    SharedPreferences.Editor editor = preferences.edit();
    editor.putBoolean("RVisibleNow",false);
    editor.commit();

    super.onStop();
}

然后,是的,使用BroadcastReceiver,例如:

private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String theRow = intent.getStringExtra(GCMIntentService.MESSAGE);
        String theQuery="SELECT * FROM listdata WHERE _id ='" + theRow + "'"; 
        String action = intent.getAction();
        if(action.equals("com.you.yourapp.UpdateList")){
...

哦,在您的GCM服务中:

public static final String BROADCAST = "com.you.yourapp.UpdateList";
public static final String MESSAGE = "com.you.yourapp.GCMIntentService.MESSAGE";

... 

    if(RVisibleNow){
                sendBroadcast(context, message, insertOrUpdate);
            }else{
                generateNotification(context, message, insertOrUpdate);
            }

在我的情况下,有很多省略的代码,我的sendBroadcast看起来像:

private void sendBroadcast(Context context,  String message, String whichFunction){
    String putExtraParam = "something";
    Intent in = new Intent(BROADCAST);
    in.putExtra(MESSAGE, putExtraParam);
    context.sendBroadcast(in);
}

希望这有帮助!

答案 2 :(得分:0)

我不建议将IntentService与BroadcastReceiver一起使用。 通过这种方法,您的服务可以通知您的活动,但您的服务将无法决定是否已收到广播(这是广播的想法,发送者只是广播,并且不关心是否有广播接收与否)。

更好的方法,但更复杂的是: - 使用可以启动和绑定的服务(覆盖onStartCommand和onBind) - 如果绑定,在服务和活动之间建立双向通信。 - 处理GCM消息时,检查是否建立了通信,如果是,则:您的活动存在,更新(使用通信),如果不存在:继续并发布通知。 这是我推荐的方式,但是我明白这看起来很复杂(并且是相当多的代码)因此我会给你第二个,更容易但不是很干净的代码。