修订版 2:如何将数据从后台服务/线程传递到创建后台服务的 MainActivity 之外的其他活动 [英] Revision 2: How to pass data from a background Service/thread to some other activity than the MainActivity that created the background service

查看:13
本文介绍了修订版 2:如何将数据从后台服务/线程传递到创建后台服务的 MainActivity 之外的其他活动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个简单的 Android 应用程序,用于测试如何使用一个或多个处理程序将数据从后台服务/线程传递到 其他一些活动,而不是创建后台服务的 MainActivity.我在 MainActivity 中有服务、线程和处理程序.最后一步是让处理程序将数据传递给 MainActivity 以外的其他活动.我可以让服务将消息传递给 MainActivity 的处理程序,但我不知道如何让它将数据传递给其他活动.

I've created a simple Android application for testing how to use a handler or handlers to pass data from a background Service/thread to some other activity other than the MainActivity that created the background service. I've got the Service, thread, and a handler working in the MainActivity. The last step is to get a handler to pass data to some other activity other than the MainActivity. I can get the Service to pass messages to the MainActivity's handler, but I don't know how to get it to pass data to some other activity.

为什么会有人想要这样做?我认为这与一个简单的 MP3 播放器相比,但它实际上与一个不错的 FM 收音机相比.MainActivity 使用允许我选择 FM 电台的后台服务.当我启动 Play 活动时,它应该绑定到相同的后台服务,这样我就可以在它(好的部分)显示音频的图形均衡器或动画时继续收听.基本上,我不知道如何从多个活动绑定到后台服务.

Why would anyone want to do this? I thought this compared to a simple MP3 player, but what it actually compares to is a nice FM radio. The MainActivity uses a background Service that allows me to select an FM station. When I launch the Play activity it should bind to the same background Service so I can continue to listen while it (the nice part) displays a graphic equalizer or animation of the the audio. Basically, I don't know how to bind to the background Service from more than one activity.

我的代码最初基于 Pro Android 2 中的服务示例页面 304,并得到了极大的帮助CommonsWare 示例应用程序.

My code was originally based on a Service example page 304 in Pro Android 2 and was helped tremendously by a CommonsWare Sample Application.

请看一下我当前的代码.它由三个经过仔细注释的文件组成,这些文件描述了我正在尝试做的事情以及我在将数据传递给 除了 MainActivity 之外的一些其他活动 时遇到的困难:

Please have a look at my current code. It consists of three carefully commented files that describe what I am trying to do and the difficulties I am having passing data to some other activity in addition to the MainActivity:

/**************************************************************************************************
 * File: MainActivity.java
 * Application: BackgroundService
 * Description: This file contains the main activity that is run when the BackgroundService
 *     application is launched.
 **************************************************************************************************/

package com.marie.mainactivity;

import com.marie.mainactivity.BackgroundService;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

/*
 * Class: MainActivity
 * Purpose: Using a button, the MainActivity class starts the backgroundService and
 *     the RcvMessages activity. Using another button MainActivity stops the backgroundService.
 *     NOTE: RcvMessages is only a stub that does nothing but display a simple message.
 * Handler: MainActivity defines and provides a reference to "handler" for the backgroundService.
 */
public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";

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

        Log.d(TAG, "starting service");

        /*
         * The bind button: bindBtn
         * Clicking this button starts the background Service and launches the
         * RcvMessages activity. NOTE: RcvMessages is only a stub so far.
         */
        Button bindBtn = (Button)findViewById(R.id.bindBtn);
        bindBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {

                // Start the background Service for sending canned messages to the handler as a test.
                Intent backgroundService = new Intent(MainActivity.this, com.marie.mainactivity.BackgroundService.class);
                backgroundService.putExtra(BackgroundService.EXTRA_MESSENGER, new Messenger(handler));
                startService(backgroundService);

                // Start the RcvMessages activity to receive messages from the handler. But how???
                Intent messages = new Intent(MainActivity.this, com.marie.mainactivity.RcvMessages.class);
                startActivity(messages);
            }
        });

        /*
         * The unbind button: unbindBtn
         * Clicking this button stops the background Service.
         */
        Button unbindBtn = (Button)findViewById(R.id.unbindBtn);
        unbindBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {

                // Stop the background Service
                Intent backgroundService = new Intent(MainActivity.this, BackgroundService.class);
                stopService(backgroundService);
            }
        });
    }

    /*
     * This is the handler to be passed to the background Service via a Messenger.
     * NOTE: I want it to send messages to my RcvMessages activity.
     */
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // simple handler test (does not send messages to RcvMessages activity
            String obj = (String) msg.obj;
            Log.i("handleMessge", "obj: " + obj);  
        }
    };
}

/**************************************************************************************************
 * File: BackgroundService.java
 * Application: BackgroundService
 * Description: This file contains the background Service that is launched by the MainActivity's
 *     bind button.
 **************************************************************************************************/

package com.marie.mainactivity;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;

/*
 * Class: BackgroundService
 * Purpose: Using the onStart() method the BackgroundService gets the reference to the
 *     Messenger instance that was passed to BackgroundService. The messenger is then
 *     used by the ServiceWorker() thread to send messages to the handler that is defined
 *     in the MainActivity class.
 */
public class BackgroundService extends Service {
    private NotificationManager notificationMgr;

    public static final String EXTRA_MESSENGER = "com.marie.mainactivity.EXTRA_MESSENGER";
    private Messenger messenger;

    @Override
    public void onCreate() {
        super.onCreate();

        notificationMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

        displayNotificationMessage("starting Background Service");

        Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService");
        thr.start();
    }   

    /*
     * This is the ServiceWorker thread that passes messages to the handler defined in
     * the MainActivity class.
     * NOTE: Instead of passing messages to a handler in MainActivity I would like
     * it to pass messages to a handler defined in the RcvMessages activity.
     */
    class ServiceWorker implements Runnable
    {
        public void run() {
            // do background processing here... something simple

            // send a message to the handler defined in the MainActivity class
            try {
                Message msg1 = Message.obtain();
                msg1.obj = "Hello 1";
                messenger.send(msg1);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

            // stop the service when done...
            // BackgroundService.this.stopSelf();
            // Or use the unbindBtn in the MainActivity class.
        }
    }

    @Override
    public void onDestroy()
    {
        displayNotificationMessage("stopping Background Service");
        super.onDestroy();
    }

    /*
     * onStart is where we get our reference the Messenger that allows
     * us to send messages to the handler defined in the MainActivity class.
     */
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);

        Bundle extras = intent.getExtras();
        messenger = (Messenger)extras.get(EXTRA_MESSENGER);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void displayNotificationMessage(String message)
    {
        Notification notification = new Notification(R.drawable.note, message, System.currentTimeMillis());

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);

        notification.setLatestEventInfo(this, "Background Service", message, contentIntent);

        notificationMgr.notify(R.id.app_notification_id, notification);
    }
}

/**************************************************************************************************
 * File: RcvMessages.java
 * Application: BackgroundService
 * Description: This file contains stub code that displays a test message in an EditText.
 **************************************************************************************************/

package com.marie.mainactivity;

import android.app.Activity;
import android.os.Bundle;
import android.text.InputType;
import android.widget.EditText;

/*
 * Class: RcvMessages
 * Purpose: RcvMessages is stub code that I want to extend in some way to receive messages from
 *     the background Service.
 *     NOTE: I don't know who to do this.
 */
public class RcvMessages extends Activity {

    EditText myText;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.messages);

        myText = (EditText)findViewById(R.id.my_text);

        myText.setSingleLine();
        myText.setInputType(InputType.TYPE_NULL);

        // Display a simple test message for now.
        myText.setText("RcvMessages here");
    }
}

任何使用后台服务、线程和处理程序将数据传递给其他活动的帮助,除了创建后台服务的 MainActivity,我们将不胜感激.

Any help using a background Service, thread, and handler(s) to pass data to some other activity in addition to the MainActivity that created the backgraound Service would be greatly appreciated.

推荐答案

Handler是与特定线程相关联的,所以只要你在UI线程中创建它,你需要做的就是共享处理程序.我会将您的处理程序放在我的 Application 类中.如果需要,您可以将整个 Messenger 放在那里.然后,您可以通过 ((MyApplication)getApplication()).getHandler() 访问任何活动中的处理程序.当活动开始或暂停时,您可以将其注册为回调.

The Handler is associated with specific thread, so for as long as you create it in UI thread all you need to do is to share the handler. I would put your handler in my Application class. And you can put the whole Messenger there, if you want. Then you can access handler in any activity via ((MyApplication)getApplication()).getHandler(). When activity starts or pauses, you can register it as a callback.

像这样的

public class MyApplication extends Application {
   Handler h = new Handler() {
      public void handleMessage(Message m) {
        if (realCallback!=null) {
           realCallback.handleMessage(m);
        }
      }
   };
   Handler.Callback realCallback=null;
   ......
   public Handler getHandler() {
      return h;
   }

   public void setCallback(Handler.Callback c) {
      realCallback = c;
   }
}

在任何需要通过信使接收请求的活动中

In any activity that needs to do receive requests via messenger

public class MyActivity extends Activity implements Handler.Callback

......

public void onStart() {
   ((MyApplication)getApplication()).setCallback(this);
}

public void onPause() {
   ((MyApplication)getApplication()).setCallback(null);
}

public void handleMessage(Message msg) {
  //.... Do stuff ....
}

}

这只是一个想法.您可能需要根据自己的需要对其进行调整.

This is just an idea. You may need to tune it to your needs.

别忘了在 AndroidManifest.xml 中设置 MyApplication 名称

And don't forget to set MyApplication name in AndroidManifest.xml

这篇关于修订版 2:如何将数据从后台服务/线程传递到创建后台服务的 MainActivity 之外的其他活动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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