[Android]Service和Activity双向通信的两种方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Gods_magic/article/details/84558169

本文源码:https://github.com/gitEkko/MyApplication.git

Service简介

Service是android 系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟 Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。service可以在很多场合的应用中使用,比如播放多媒体的 时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后台的。

这里主要总结Service和Activity进行互相通信的两种方式:

  1. 通过Binder对象,绑定服务的方式,实现ServiceConnection接口。
  2. 通过广播

一、绑定服务的方式,实现ServiceConnection接口

bindService()  - unbindService()

1.进行数据传递

  • Service中声明一个Binder类,类中声明用来传递数据的方法。比如向Activity返回Service实例/接受或返回数据。
  • Activity实现ServiceConnection接口,Activity绑定Service调用bindService()方法。此时onServiceConnected()方法就会被调用。此方法中利用获取的Binder实例,可以调用Service中各个用来传递数据的方法。 

这就实现了Activity向Service传递数据,Service接收数据进行数据操作后,再返回给Activity。

2.Activity监听Service数据变化

  • Service自定义Callback接口,声明监听数据的抽象函数onDataChange(String data),参数data用来向外部暴露data数据,并设置callback实例的setter方法。再onCreat()方法中,Service利用接收来的data数据,进行耗时操作后(例如开启线程进行data的循环递增),用callback.onDataChange(data + "")暴露data数据。
  • Activity在onServiceConnected()方法中,利用获取的Service实例调用setCallback()方法,同时实例化Callback接口,进行接口回调实现onDataChange()函数,此时就监听到了Service中data数据的状态,并利用Handler进行更新UI操作。

myService2.java

public class MyService2 extends Service {
    private static final String TAG = "xxxx";
    private boolean connecting = false;
    private Callback callback;
    public int data = 0;


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

    class MyBinder extends Binder {

        //向Activity返回MyService2实例
        MyService2 getService() {
            return MyService2.this;
        }

        //获取从Activity传来的数据
        void TransferData(int mData) {
            data = mData;
        }

        //将data数值传递给Activity
        int getData() {
            return data;
        }

    }

    @Override
    public void onCreate() {
        super.onCreate();
        connecting = true;
        //开启一个线程,对数据进行处理
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (connecting) {
                    if (callback != null) {
                        callback.onDataChange(data + "");
                    }
                    data++;
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();


    }

    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    public Callback getCallback() {
        return callback;
    }

    public interface Callback {
        void onDataChange(String data);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        connecting = false;
    }
}

ServiceActivity2.java 

public class ServiceActivity2 extends AppCompatActivity implements View.OnClickListener, ServiceConnection {

    private static final String TAG = "xxxx";
    private TextView textView;
    private boolean bind = false;
    private int TransforData;
    MyService2.MyBinder binder = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service2);

        TransforData = 0;
        textView = (TextView) findViewById(R.id.textView);
        Button bindBtn = (Button) findViewById(R.id.bind_service2);
        Button unBindBtn = (Button) findViewById(R.id.unbind_service2);
        Button clearBt = (Button) findViewById(R.id.clear);
        bindBtn.setOnClickListener(this);
        unBindBtn.setOnClickListener(this);
        clearBt.setOnClickListener(this);
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //获取binder对象
        binder = (MyService2.MyBinder) service;

        //向Service传递数据 TransforData
        binder.TransferData(TransforData);
        //获取从Service传递的MyService对象
        MyService2 myService2 = binder.getService();
        //接口回调 监控Service中的数据变化 并在handler中更新UI
        myService2.setCallback(new MyService2.Callback() {
            @Override
            public void onDataChange(String data) {
                Message msg = new Message();
                msg.obj = data;
                handler.sendMessage(msg);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bind_service2:
                if (!bind) {
                    bind = true;
                    //服务绑定后,会调用 onServiceConnected
                    Intent bindIntent = new Intent(this, MyService2.class);
                    bindService(bindIntent, this, BIND_AUTO_CREATE);
                    Toast.makeText(this, "Bind Service Success!", Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.unbind_service2:
                if (bind) {
                    //从Service中获取data数值
                    TransforData = binder.getData();
                    unbindService(this);
                    bind = false;
                    Toast.makeText(this, "unBind Service Success!", Toast.LENGTH_SHORT).show();
                }
                break;

            case R.id.clear:
                if (!bind) {
                    TransforData = 0;
                    textView.setText("0");
                }
                break;
            default:
                break;
        }
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //在此处更新UI
            textView.setText(msg.obj.toString());
        }
    };
}

二、利用广播方式

startService() - stopService()

  • Activity:动态注册广播 。将data存储到intent中,调用startService(intent)开启服务。
  • Service:重写onStartCommand()方法,利用intent.getXXExtra()获取Activity传来的数据。对数据进行操作后,将data存到intent中并发送广播。
  • Activity:接收广播,重写onReceive()函数,开启主线程并从intent中取出data数据,进行更新UI操作。

利用广播和intent实现了数据通信和监听服务数据状态。

扫描二维码关注公众号,回复: 4633969 查看本文章

MyService3.java

public class MyService3 extends Service {

    private boolean connecting = false;
    public static final String COUNTER = "data";
    public static final String ACTION_NAME = "com.example.myinterview.service3.COUNTER_ACTION";

    private int data;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //从Activity获取data
        data = intent.getIntExtra(COUNTER, 0);

        final Intent mIntent = new Intent();
        mIntent.setAction(ACTION_NAME);
        connecting = true;
        //开启一个线程,对数据进行处理
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (connecting) {
                        //耗时操作:数据处理并保存,向Activity发送广播
                        mIntent.putExtra(COUNTER, data);
                        sendBroadcast(mIntent);
                        data++;
                        Thread.sleep(300);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        connecting = false;
    }
}

ServiceActivity3.java


public class ServiceActivity3 extends AppCompatActivity implements View.OnClickListener {

    private int TransforData;
    private TextView textView;
    private Intent mIntent;
    private MyReceiver myReceiver;
    private boolean bind = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service3);

        TransforData = 0;
        textView = (TextView) findViewById(R.id.textView);
        Button startBtn = (Button) findViewById(R.id.mstart);
        Button pauseBtn = (Button) findViewById(R.id.pause);
        Button clearBt = (Button) findViewById(R.id.clear);
        startBtn.setOnClickListener(this);
        pauseBtn.setOnClickListener(this);
        clearBt.setOnClickListener(this);

        mIntent = new Intent(this, MyService3.class);
        myReceiver = new MyReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(MyService3.ACTION_NAME);
        //注册广播
        registerReceiver(myReceiver, intentFilter);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.mstart:
                if (!bind) {
                    bind = true;
                    //向Service传递data
                    mIntent.putExtra(MyService3.COUNTER, TransforData);
                    startService(mIntent);
                    Toast.makeText(this, "Start!", Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.pause:
                //停止服务
                stopService(mIntent);
                bind = false;
                break;
            case R.id.clear:
                if (!bind) {
                    TransforData = 0;
                    textView.setText("0");
                    Toast.makeText(this, "Pause!", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }

    class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, final Intent intent) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //获取从Service中传来的data
                    TransforData = intent.getIntExtra(MyService3.COUNTER, 0);
                    //更新UI
                    textView.setText(String.valueOf(TransforData));
                }
            });
        }
    }

    @Override
    protected void onDestroy() {
        stopService(mIntent);
        unregisterReceiver(myReceiver);
        super.onDestroy();
    }
}

两种方式共同实现了秒表的开始、暂停、清零。

  • Service和Activity互相传递data数据
  • Activity监控Service中的数据变化状态

猜你喜欢

转载自blog.csdn.net/Gods_magic/article/details/84558169
今日推荐