從APP升級更新淺談安卓Service知識

博主原創轉載請註明作者MskyAndroid
出處http://blog.csdn.net/AndroidMsky/article/details/53407925

GITHUB鏈接:
https://github.com/AndroidMsky/UpdateApp

本文將簡述一個APP升級功能,通過前臺service實時下載一個APK然後跳入安裝界面.

這裏寫圖片描述

這裏寫圖片描述

首先回顧一下Service的知識點,service可翻譯爲服務,你可以暫時把它理解爲一個沒有界面的Activity,但是他的生命週期又和activity有所不同。但又大致相同,我認爲唯一需要特別注意的就是onbind方法,是綁定的意思。也就是說一個service自己在黑暗中運行,要如何給他指指路呢,那麼就通過onbind方法,綁定這個service。說起綁定這個詞肯定很多人又開始暈了,其實可以這樣理解,一個Activity去通過ServiceConnection綁定一個service,就是從Activity中拿取一個service中的對象,這個對象往往有一些可以控制service做什麼的方法(這並不是一定的,你可以寫一些沒什麼用的方法因爲這個類的方法都是自己定義的)。

好下面舉個栗子:
本文通過更新按鈕啓動一個service去通過HttpURLConnection去下載一個網絡的apk,並且可以通過獲取進度按鈕獲取實時進度。實時獲取進度,我們就用activity去綁定一個service來實現。
首先也就是我們剛纔說的,activity拿取service的一個對象,這個對象的類型必須是Binder的子類:

class MyBinder extends Binder {

        public int getDownload() {
            Log.d("TAG", "getDownload ");
            return updateCount;

        }

    }

在service中聲明該對象

private MyBinder mBinder = new MyBinder();

在service這個唯一的抽象方法中返回這個mBinder對象

@Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

service的工作就做完了,接下來就是activity中寫一個實現serviceConnection接口的類:

class MyServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName arg0, IBinder service) {
            Log.d("info", "Service Connection Success");

            myBinder = (UpdateService.MyBinder) service;

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
            Log.d("info", "Service Connection Filed");
//連接失敗執行
        }

    }

可見兩個方法,一個連接成功一個連接失敗,連接成功方法中的IBinder service也就是傳遞給我們的那個連接二者的對象,操作這個對象的方法,去指揮service中的動作就可以了。
最後啓動service並且綁定:

UpdateService.into(this, getString(R.string.app_name), url);
Intent intent = new Intent(this, UpdateService.class);
        bindService(intent,myServiceConnection , Context.BIND_AUTO_CREATE);

相信綁定這塊大家都已經清楚了,接下來就看一下service的生命週期,我們在幾個關鍵的生命週期打一下log。當我們點擊更新按鈕,創造並綁定service:

這裏寫圖片描述

當我們每次點擊獲取進度按鈕,也就是通過綁定得到那個對象中的方法,都會調用service中的方法執行。

特別需要注意的是即使調用

stopSelf();

service並沒有完全結束,因爲它還被綁定,必須解綁stop兩者同時滿足service纔會停下來,我們就設定如果獲取進度打到100的時候就進行解綁。

public void getprogress(View v){

        textView.setText("進度:"+myBinder.getDownload());
        if (myBinder.getDownload()==100)
            unbindService(myServiceConnection);


    }

這裏寫圖片描述

接下來說一下前臺service一個service如何穿上前臺service的外衣就是在通知欄去創造一個通知它就升級爲前臺service,這樣就有了更高的優先級不容易被系統殺死了,當然這個通知不是通過NotificationManager來顯示出來的,是通過startForeground(1, notification);方法來顯示出來,這樣service就編程前臺service了。


    public void createNotification() {
        builder = new Notification.Builder(this);
        builder.setSmallIcon(R.mipmap.ic_launcher).setOngoing(false)
                .setContentText("正在下載")
                .setContentTitle("XXXX下載");
        builder.setAutoCancel(false);
        builder.setOngoing(true);
        builder.setTicker("XXXX正在下載");
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
        builder.setProgress(100, 0, false);

        Notification notification = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            builder.setPriority(Notification.PRIORITY_MAX);
            notification = builder.build();
        } else {
            notification = builder.getNotification();
        }
        notification.icon = R.mipmap.ic_launcher;
        startForeground(1, notification);

    }

另外不要以爲service在後臺沒有界面它就有自己的線程了,錯錯錯,普通的service的代碼默認還是跑在主線程中的,所以我們開啓下載任務也是要重新開啓線程來下載的。

private class DownLoadThread extends Thread {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            Message message = new Message();
            try {
                long downloadSize = downloadUpdateFile(down_url,
                        FileUtil.updateFile.toString());
                if (downloadSize > 0) {
                    message.what = DOWN_OK;
                    handler.sendMessage(message);
                }
            } catch (Exception e) {
                message.what = DOWN_ERROR;
                handler.sendMessage(message);
            }
        }
    }

相信通過本文的淺談,大家都可以靈活的去使用service了。

歡迎關注作者。歡迎評論討論。歡迎拍磚。 如果覺得這篇文章對你有幫助,歡迎打賞, 歡迎star,Fork我的github。 喜歡作者的也可以Follow。也算對作者的一種支持。
本文Github代碼鏈接
https://github.com/AndroidMsky/UpdateApp
歡迎加作者自營安卓開發交流羣:308372687
這裏寫圖片描述

—————————————————————————————
作者推薦:
安卓自定義view滾動數據顯示
http://blog.csdn.net/androidmsky/article/details/53009886 RecyclerView
下拉刷新分頁加載性能優化和Gilde配合加載三部曲
http://blog.csdn.net/androidmsky/article/details/53115818
打造企業級網絡請求框架集合retrofit+gson+mvp
http://blog.csdn.net/androidmsky/article/details/52882722
安卓手機自動接起QQ視頻秒變攝像頭
http://blog.csdn.net/androidmsky/article/details/53066441 —————————————————————————————

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章