Android 開啟Service兩種方式及Activity與Service間進行消息傳遞

Service

Android開發(fā)者文檔里這樣定義:
A service is a component that runs in the background to perform long-running operations or to perform work for remote processes. A service does not provide a user interface. For example, a service might play music in the background while the user is in a different app, or it might fetch data over the network without blocking user interaction with an activity.Another component, such as an activity, can start the service and let it run or bind to it in order to interact with it.

Service是Android提供的四大組件之一流济,我們可以認為它是一個沒有用戶界面、開發(fā)者創(chuàng)建的組件腌闯,它可以用來執(zhí)行長久的操作绳瘟,可以超出單個Activity的范圍。Service可以作為客戶端/服務(wù)器開發(fā)模式的服務(wù)器姿骏,通過進程間通信(IPC)提供遠程調(diào)用服務(wù)糖声。
如果一個任務(wù)需要使用worker線程,可能會影響應(yīng)用的響應(yīng)速度和性能分瘦,而這個任務(wù)對處理時間并不敏感蘸泻,那就考慮使用Service,在主要應(yīng)用程序和任何單獨的Activity生命周期外處理任務(wù)嘲玫。

常見應(yīng)用

  • 天氣悦施、電子郵件或者社交網(wǎng)絡(luò)的App,可以定期檢查網(wǎng)絡(luò)上更新的服務(wù)去团。
  • 一個游戲歼争,可以在用戶需要的時候創(chuàng)建一個Service下載并處理相關(guān)內(nèi)容。
  • 一個照片或者多媒體應(yīng)用保持數(shù)據(jù)的在線同步渗勘。
  • 一個視頻編輯軟件沐绒,可以將繁重的處理工作放置在服務(wù)隊列,降低系統(tǒng)能耗旺坠。
  • 一個新聞應(yīng)用乔遮,可以實現(xiàn)預(yù)加載內(nèi)容的服務(wù),當用戶啟動時取刃,提前下載相應(yīng)新聞蹋肮,提高性能和相應(yīng)能力出刷。

開啟Service的兩種方式:

  1. startService(Intent serviceIntent) 一個組件可以通過startService的方式來開啟Service服務(wù)。這種方式開啟的Service可以調(diào)用stopSelf()來停止服務(wù)坯辩,也可以通過在其他組件中調(diào)用stopService()方法來停止馁龟。
Intent serviceIntent = new Intent(this, FirstStartedService.class);
  startService(serviceIntent);

FirstStartedService就是開啟的繼承自Service的服務(wù)。

public class FirstStartedService extends Service {
    private CustomHanlder ch;
    public FirstStartedService() {

    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.w("service created:","flag");
        HandlerThread ht=new HandlerThread("handler.thread.name");
        ht.start();
        ch=new CustomHanlder(ht.getLooper());
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
       return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.w("service started:","flag");
        Log.w("main thread id:",""+Thread.currentThread().getName()+Thread.currentThread().getId());
        //do service task;
        //stopSelf();
        ch.sendEmptyMessage(0);
        return Service.START_STICKY;
    }

    private class CustomHanlder extends Handler{
        public CustomHanlder(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            Log.w("handler thread id:",""+Thread.currentThread().getName()+Thread.currentThread().getId());
        }
    }
}

2.bindService(Intent service ,ServiceConnection conn ,Int flags) 參數(shù)service是指要綁定的Service漆魔,conn是ServiceConnection對象坷檩,這個對象不能為null,flags為binding的類型改抡,可以為0矢炼。 這種方式開啟的Service會一直運行,直到?jīng)]有組件綁定這個Service的時候系統(tǒng)才會停止Service阿纤。一般情況下句灌,一個組件在不需要Service服務(wù)后要調(diào)用unBindService(ServiceConnection conn)來解綁Service。
一個簡單示例:Activity作為客戶端使用bindService的方式開啟一個Service服務(wù)欠拾,并向服務(wù)端發(fā)送一個字符串胰锌,服務(wù)端接收字符串后向客戶端返回一個字符串。這也是一個簡單的進程間通信(IPC)的例子

客戶端代碼:

public class ServiceTestScreen extends AppCompatActivity {

    private TextView tv;

    public ServiceTestScreen() {
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service_test_screen);
        tv = (TextView) findViewById(R.id.reply_text);
    }

    public void onClickButton(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.start_service: {
                Intent serviceIntent = new Intent(this, FirstStartedService.class);
                startService(serviceIntent);
                break;
            }
            case R.id.bind_service: {
                Intent serviceIntent = new Intent(this, FirstBinderService.class);
                bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
                break;
            }
            case R.id.start_intent_service: {
                Intent serviceIntent = new Intent(this, FirstIntentService.class);
                startService(serviceIntent);
                break;
            }
            case R.id.send_msg: {
                if (serviceBound) {
                    if (serverMsger != null) {
                        Message msg = new Message();
                        Bundle data = new Bundle();
                        data.putString("send", "client msg");
                        msg.setData(data);
                        msg.replyTo = clientMsger;
                        try {
                            serverMsger.send(msg);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }
                break;
            }
        }
    }

    private boolean serviceBound = false;
    private Messenger serverMsger;
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            Log.w("component name:", name.getClassName());
            serverMsger = new Messenger(binder);
            serviceBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            serverMsger = null;
            serviceBound = false;
        }
    };
    private Handler h = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            tv.setText(msg.getData().getString("reply"));
        }
    };

    private Messenger clientMsger = new Messenger(h);

    @Override
    protected void onStop() {
        super.onStop();
        if (serviceBound) {
            unbindService(serviceConnection);
            serviceBound = false;
            serverMsger = null;
        }
    }
}

服務(wù)端代碼:

public class FirstBinderService extends Service {

    private final Messenger serverMsger = new Messenger(new MessageHandler());

    public FirstBinderService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return serverMsger.getBinder();
    }

    private class MessageHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Message replyMsg = new Message();
            Bundle data = new Bundle();
            data.putString("reply", msg.getData().getString("send") + "--server msg");
            replyMsg.setData(data);
            try {
                msg.replyTo.send(replyMsg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

}

示例效果圖:


Activity獲取Service的返回字符串
Activity獲取Service的返回字符串

總結(jié)

本文主要總結(jié)了Android中啟動Service的兩種方式藐窄,并用了具體示例來進行演示资昧,完成了使用bindService的方式進行進程間通信。如果總結(jié)的有錯誤或不足的地方枷邪,歡迎大家批評指正榛搔。
示例代碼
個人主頁
GitHub

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市东揣,隨后出現(xiàn)的幾起案子践惑,更是在濱河造成了極大的恐慌,老刑警劉巖嘶卧,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尔觉,死亡現(xiàn)場離奇詭異,居然都是意外死亡芥吟,警方通過查閱死者的電腦和手機侦铜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钟鸵,“玉大人钉稍,你說我怎么就攤上這事」姿#” “怎么了贡未?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我俊卤,道長嫩挤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任消恍,我火速辦了婚禮岂昭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狠怨。我一直安慰自己约啊,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布取董。 她就那樣靜靜地躺著棍苹,像睡著了一般无宿。 火紅的嫁衣襯著肌膚如雪茵汰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天孽鸡,我揣著相機與錄音蹂午,去河邊找鬼。 笑死彬碱,一個胖子當著我的面吹牛豆胸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巷疼,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼晚胡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嚼沿?” 一聲冷哼從身側(cè)響起估盘,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骡尽,沒想到半個月后遣妥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡攀细,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年箫踩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谭贪。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡境钟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出俭识,到底是詐尸還是另有隱情慨削,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站理盆,受9級特大地震影響痘煤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜猿规,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一衷快、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姨俩,春花似錦蘸拔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至张遭,卻和暖如春邓萨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背菊卷。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工缔恳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洁闰。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓歉甚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扑眉。 傳聞我的和親對象是個殘疾皇子纸泄,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容