1. 程式人生 > >Android Service與Activity的互動

Android Service與Activity的互動

Android中有時候需要在Service中改變Activity的UI,或者在Activity中修改Service中的數值。首先必須使用與Activity繫結的Service,有三種方式可以實現。第一,是使用介面回撥的方式在Activty中實現Service中的介面;第二,使用廣播的方式傳遞;第三,則是用觀察者模式,在Activity中實現update方法。

使用介面回撥的方式在Activty中實現Service中的介面

package com.kkrs.serivce;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * Created by zd on 2018/12/20.
 */

//繫結的service
public class LocalService extends Service {

    private final static String TAG = "LocalService";
    private int count;
    private boolean quit;
    private Thread thread;
    private LocalBinder binder = new LocalBinder();


    /**
     * 回撥
     */
    private Callback callback;

    /**
     * 提供介面回撥方法
     * @param callback
     */
    public void setCallback(Callback callback) {
        this.callback = callback;
    }


    /**
     * 回撥介面
     *
     * @author lenovo
     *
     */
    public static interface Callback {
        /**
         * 得到實時更新的資料
         *
         * @return
         */
        void getNum(int num);
    }


    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "Service is invoke Created");
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 每間隔一秒count加1 ,直到quit為true。
                while (!quit) {
                    try {
                        Thread.sleep(1000);

                        if(callback!=null){
                /*
                 * 得到最新資料
                 */
                            callback.getNum(count);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                }
            }
        });
        thread.start();
    }

    public class LocalBinder extends Binder {
        // 宣告一個方法,getService。(提供給客戶端呼叫)
        LocalService getService() {
            // 返回當前物件LocalService,這樣我們就可在客戶端端呼叫Service的公共方法了
            return LocalService.this;
        }
    }

    /**
     * 公共方法
     * @return
     */
    public int getCount(){
        return count;
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "Service is onDestroy");

        this.quit = true;
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "Service is onUnbind");
        return super.onUnbind(intent);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "Service is onBind");

        return binder;
    }
}

  

   private ServiceConnection conn;
    private LocalService mService;
  @Override
    protected void onCreate(Bundle savedInstanceState) {
    
 conn = new ServiceConnection() {
            /**
             * 與伺服器端互動的介面方法 繫結服務的時候被回撥,在這個方法獲取繫結Service傳遞過來的IBinder物件,
             * 通過這個IBinder物件,實現宿主和Service的互動。
             */
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.e("MainActivity", "繫結成功呼叫:onServiceConnected");
                // 獲取Binder
                LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
                mService = binder.getService();
                mService.setCallback(new LocalService.Callback(){

                    @Override
                    public void getNum(int num) {
                        // TODO Auto-generated method stub
                        Log.e("num","====num===="+num);
                    }
                });
            }
            /**
             * 當取消繫結的時候被回撥。但正常情況下是不被呼叫的,它的呼叫時機是當Service服務被意外銷燬時,
             * 例如記憶體的資源不足時這個方法才被自動呼叫。
             */
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mService=null;
            }
        };

        final Intent intent = new Intent(this, LocalService.class);

        btnBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.e("MainActivity", "繫結呼叫:bindService");

                bindService(intent, conn, Service.BIND_AUTO_CREATE);

            }
        });

        btnUnBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 解除繫結
                Log.e("MainActivity", "解除繫結:bindService");

                if(mService!=null) {
                    Log.e("MainActivity", "mService!=null");
                    mService = null;
                    unbindService(conn);
                }
            }
        });


        btnGetDatas.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mService != null) {
                    // 通過繫結服務傳遞的Binder物件,獲取Service暴露出來的資料
                    Log.e("MainActivity", "從服務端獲取資料:" + mService.getCount());
                } else {

                    Log.e("MainActivity", "還沒繫結呢,先繫結,無法從服務端獲取資料");
                }
            }
        });

}

  使用廣播的方式傳遞

package com.kkrs.serivce;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import static android.content.ContentValues.TAG;

/**
 * Created by zd on 2018/12/25.
 */

public class ContentService extends Service {

    private Thread thread;

    private boolean flag = true;

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        flag = true;
        return new LocalBinder();
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Log.e(TAG, "Service is invoke Created");
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 每間隔一秒count加1 ,直到quit為true。
                while (flag) {
                    try {
                        Thread.sleep(1000);
                        asyncSendPerson("ContentService");

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread.start();

    }

    public final class LocalBinder extends Binder {
        public ContentService getService() {
            return ContentService.this;
        }
    }

    public void asyncSendPerson(final String name) {
        // 休息5秒,模擬非同步任務
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //可以在子執行緒中直接傳送廣播
                sendContentBroadcast(name);
            }
        }).start();
    }

    /**
     * 傳送廣播
     * @param name
     */
    protected void sendContentBroadcast(String name) {
        // TODO Auto-generated method stub
        Intent intent=new Intent();
        intent.setAction("com.example.servicecallback.content");
        intent.putExtra("name", name);
        sendBroadcast(intent);
    }

}

  

 //廣播

    private ServiceReConn connRe;
    private ContentReceiver mReceiver;

    public class ServiceReConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            // service = ((LocalBinder) binder).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            // service = null;
        }
    }

    public class ContentReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String name = intent.getStringExtra("name");
            Person person = new Person();
            person.setName(name);
            Log.e("ContentReceiver",person.toString());
        }
    }

    /**
     * 註冊廣播接收者
     */
    private void doRegisterReceiver() {
        mReceiver=new ContentReceiver();
        IntentFilter filter = new IntentFilter(
                "com.example.servicecallback.content");
        registerReceiver(mReceiver, filter);
    }

  觀察者模式

public class ObserviceService extends Service {
    //被觀察者
    private MyObservable mObservable;
    private Thread thread;
    private boolean flag = true;

    @Override
    public IBinder onBind(Intent arg0) {
        flag = true;
        return new LocalBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mObservable = new MyObservable();
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 每間隔一秒count加1 ,直到quit為true。
                while (true) {
                    try {
                        Thread.sleep(1000);
                        asyncSendPerson("ObserviceService");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        });
        thread.start();
    }

    public final class LocalBinder extends Binder {
        public ObserviceService getService() {
            return ObserviceService.this;
        }
    }

    public void asyncSendPerson(final String name) {
        // 休息5秒,模擬非同步任務
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.sendMessage(handler.obtainMessage(0, name));
            }
        }).start();
    }

    /**
     * 新增觀察者
     * @param observer
     */
    public void addObserver(Observer observer) {
        mObservable.addObserver(observer);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            String name = (String) msg.obj;
            Person person = new Person();
            person.setName(name);
            //通知更新
            mObservable.notifyChanged(person);
        }
    };

    public class MyObservable extends Observable {

        public void notifyChanged(Object object) {
            this.setChanged();
            this.notifyObservers(object);
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        flag = false;
        return super.onUnbind(intent);
    }

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

 實現Observer

private ServiceConnection conn;
    private LocalService mService;


    //觀察這模式
    private MyServiceConn connOb;
    private ObserviceService observiceService;
    public class MyServiceConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            observiceService = ((ObserviceService.LocalBinder) binder).getService();
            //將當前activity新增為觀察者
            observiceService.addObserver(MainActivity.this);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            observiceService = null;
        }
    }

    @Override
    public void update(Observable observable, Object o) {
        Log.e("update","觀察這模式在這裡修改UI");
        Person person = (Person) o;
        Log.e("update",person.toString());
    }


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
setContentView(R.layout.activity_main);
btnBindOb = (Button)findViewById(R.id.btnBindOb);
btnUnBindOb = (Button)findViewById(R.id.btnUnBindOb);


final Intent obIntent = new Intent(context, ObserviceService.class);
connOb = new MyServiceConn();
btnBindOb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bindService(obIntent, connOb, Service.BIND_AUTO_CREATE);

}
});

btnUnBindOb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(observiceService!=null) {
Log.e("MainActivity", "observiceService!=null");
observiceService = null;
unbindService(connOb);
}
}
});

}