天天看點

利用Bmob雲更新APP

在寫自己App的時候,APP更新是非常重要的,後續版本的釋出及時送到使用者

效果圖:

利用Bmob雲更新APP

看下Bmob的背景,建立應用,配置啥的就不說了

首先我們建立表update

利用Bmob雲更新APP

objectID是唯一标示,不能改變,我們根據這個ID擷取APK檔案的下載下傳連結更新内容text,Code是APP版本号,伺服器上的CODE号一定要比上個版本大。

流程:開啟APP——檢測CODE——CODE大于目前CODE執行更新——下載下傳APK——install

擷取APP版本号的工具類:

import android.content.Context;
import android.content.pm.PackageManager;

/*擷取版本code和name的工具類*/
public class APKVersionCodeUtils {

    /* 擷取目前本地apk的版本*/
    public static int getVersionCode(Context mContext) {
        int versionCode = 0;
        try {
            //擷取軟體版本号,對應AndroidManifest.xml下android:versionCode
            versionCode = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionCode;
    }


    /* 擷取版本号名稱*/
    public static String getVerName(Context context) {
        String verName = "";
        try {
            verName = context.getPackageManager().
                    getPackageInfo(context.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return verName;
    }

}
           

versionCode是版本号,,cersionName是版本号

調用:

      int versionCode = APKVersionCodeUtils.getVersionCode(this) ;

       String versionName = APKVersionCodeUtils.getVerName(this);

update.java

import cn.bmob.v3.BmobObject;
import cn.bmob.v3.datatype.BmobFile;

public class update extends BmobObject {


    public BmobFile getAPK() {
        return APK;
    }
    public void setAPK(BmobFile APK) {
        this.APK = APK;
    }
    BmobFile APK;



    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    String text;

    public String getCode() {
        return Code;
    }

    public void setCode(String code) {
        Code = code;
    }

    String Code;


    public String getapkUrl(){
        return APK.getFileUrl();
    }


}
           

需要注意的是getAPKurl()這個方法是擷取APK的下載下傳連結

擷取版本Code和APK連結以及text:

//查詢單條資料
    public void querySingleData() {
        BmobQuery<update> bmobQuery = new BmobQuery<update>();
        bmobQuery.getObject("MF4j000B", new QueryListener<update>() {
            @Override
            public void done(update object, BmobException e) {
                if (e == null) {
                    url = object.getapkUrl();
                    code1 = object.getCode();
                    text = object.getText();
                    System.out.println("APK更新位址:" + url);
                    System.out.println("版本号:" + code1);
                    System.out.println("更新内容" + text);
                    check(code1);
                } else {
                    Log.i("bmob圖檔", "失敗:" + e.getMessage() + "," + e.getErrorCode());
                }
            }
        });
    }
           

檢測版本CODE:

//判斷版本大小
    public void check(String code1) {
        code = APKVersionCodeUtils.getVersionCode(this) ;
        int i = Integer.valueOf(this.code1).intValue();
        if (i > code) {
            showDialog();
        }
    }
           

如果需要更新,顯示Dialog給使用者提示更新:

private void showDialog() {
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setIcon(R.drawable.ic_launcher_background)//設定标題的圖檔
                .setTitle("檢查到新版本")//設定對話框的标題
                .setMessage(text)//設定對話框的内容
                //設定對話框的按鈕
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //Toast.makeText(MainActivity.this, "點選了取消按鈕", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("更新", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //Toast.makeText(MainActivity.this, "點選了确定的按鈕", Toast.LENGTH_SHORT).show();
                        //postUrl(url);
                        mIsCancel=false;
                        //展示對話框
                        showDownloadDialog(url);
                        dialog.dismiss();
                    }
                }).create();
        dialog.show();
    }

    /*
     * 顯示正在下載下傳對話框
     */
    protected void showDownloadDialog(String url) {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setTitle("下載下傳中");
        View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_progress, null);
        mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress);
        builder.setView(view);

        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 隐藏目前對話框
                dialog.dismiss();
                // 設定下載下傳狀态為取消
                mIsCancel = true;
            }
        });

        mDownloadDialog = builder.create();
        mDownloadDialog.show();

        // 下載下傳檔案
        downloadAPK(url);
    }
           

downloadAPK()及install()

/*
     * 開啟新線程下載下傳apk檔案
     */
    private void downloadAPK() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
                        String sdPath = Environment.getExternalStorageDirectory() + "/";
//                      檔案儲存路徑
                        mSavePath = sdPath + "SITdownload";

                        File dir = new File(mSavePath);
                        if (!dir.exists()){
                            dir.mkdir();
                        }
                        // 下載下傳檔案
                        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
                        conn.connect();
                        InputStream is = conn.getInputStream();
                        int length = conn.getContentLength();

                        File apkFile = new File(mSavePath, mVersion_name);
                        FileOutputStream fos = new FileOutputStream(apkFile);

                        int count = 0;
                        byte[] buffer = new byte[1024];
                        while (!mIsCancel){
                            int numread = is.read(buffer);
                            count += numread;
                            // 計算進度條的目前位置
                            mProgress = (int) (((float)count/length) * 100);
                            // 更新進度條
                            mUpdateProgressHandler.sendEmptyMessage(1);

                            // 下載下傳完成
                            if (numread < 0){
                                mUpdateProgressHandler.sendEmptyMessage(2);
                                break;
                            }
                            fos.write(buffer, 0, numread);
                        }
                        fos.close();
                        is.close();
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * 接收消息
     */
    private Handler mUpdateProgressHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 1:
                    // 設定進度條
                    mProgressBar.setProgress(mProgress);
                    break;
                case 2:
                    // 隐藏目前下載下傳對話框
                    mDownloadDialog.dismiss();
                    // 安裝 APK 檔案
                    installAPK();
            }
        };
    };

    /*
     * 下載下傳到本地後執行安裝
     */
    protected void installAPK() {
        File apkFile = new File(mSavePath, mVersion_name);
        if (!apkFile.exists()){
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);
//	    安裝完成後,啟動app(源碼中少了這句話)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Uri uri = Uri.parse("file://" + apkFile.toString());
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        mContext.startActivity(intent);
    }
           

最後是mainfest權限:

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!--往sdcard中寫入資料的權限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--在sdcard中建立/删除檔案的權限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
           

API版本不能設定太高:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.example.alex233.update"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 11
        versionName "2.9"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.+'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    //以下SDK開發者請根據需要自行選擇
    //bmob-sdk:Bmob的android sdk包,包含了Bmob的資料存儲、檔案等服務,以下是最新的bmob-sdk:
    //3.5.5:請務必檢視下面注釋[1]
    compile 'cn.bmob.android:bmob-sdk:3.6.3'
    //bmob-push:Bmob的推送包
    compile 'cn.bmob.android:bmob-push:0.8'
    //bmob-im:Bmob的即時通訊包,注意每個版本的im依賴特定版本的bmob-sdk,具體的依賴關系可檢視下面注釋[2]
    compile 'cn.bmob.android:bmob-im:[email protected]'
    //如果你想應用能夠相容Android6.0,請添加此依賴(org.apache.http.legacy.jar)
    compile 'cn.bmob.android:http-legacy:1.0'

}
           

以上就是版本更新的内容了;

其實可以用android自帶的download下載下傳器

在dialog點選确認的點選事件中:

Intent intent = new Intent();
                intent.setData(Uri.parse(url));//Url 就是你要打開的網址
                intent.setAction(Intent.ACTION_VIEW);
                startActivity(intent); //啟動浏覽器
           

就很簡單,不需要下面的一大堆了

完整代碼:

https://github.com/IMAlex233/update.git

繼續閱讀