Android实现APP版本升级

最近写的项目中有用到版本升级,所以简单的写了一个例子来实现这个功能,由于时间紧迫,代码有很多需要优化的地方,请各位大神指正。

页面大概是这个样子的:


在服务中使用okgo下载APK,下载过程中在通知栏显示下载进度,下载完成后,通知栏消失,进入APK安装页面;

主要代码:

public class Update_app {
    private Context context;
    private String update_url = "http://b2b.yoyoce.com/mobile/member/down";
    private String apk_url = "";
    private int version = 0;
    private String ed_num, content, size;

    public Update_app(Context context) {
        this.context = context;
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    if (isNeedUpdate()) {
                        SharedPreferences sp = context.getSharedPreferences("update", Context.MODE_PRIVATE);
                        sp.getInt("num", 0);
                        if (sp.getInt("num", 0) != version) {
                            ShowDialog();
                        }
                    }
                    break;
            }
        }
    };

    public void update() {
        get_service();
    }

    private boolean isNeedUpdate() {
        if (getVersion() < version) {
            return true;
        } else {
            return false;
        }
    }

    //获取当前版本号
    private int getVersion() {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(
                    context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }


    void get_service() {
        OkGo.post(update_url)
                .tag(this)
                .connTimeOut(100000)
                .readTimeOut(100000)
                .writeTimeOut(100000)
                .cacheKey(update_url)
                .cacheTime(1000 * 60 * 60 * 24)
                .cacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST)
                //这里给出的泛型为 ServerModel,同时传递一个泛型的 class对象,即可自动将数据结果转成对象返回
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        try {
                            JSONObject jsonObject = new JSONObject(s);
                            if (jsonObject.getInt("status") == 1) {
                                JSONObject jsonObject1 = jsonObject.getJSONObject("result");
                                apk_url = jsonObject1.getString("apk_url");
                                String edition = jsonObject1.getString("edition");
                                //展示给用户
                                ed_num = jsonObject1.getString("ed_num");
                                content = jsonObject1.getString("content");
                                size = jsonObject1.getString("size");

                                version = Integer.parseInt(edition);
                                handler.sendEmptyMessage(1);
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }

    void ShowDialog() {
        //弹出对话框
        final LayoutInflater inflaterDl = LayoutInflater.from(context);
        LinearLayout layout = (LinearLayout) inflaterDl.inflate(R.layout.update, null);
        //初始化按钮
        TextView update_tv_yes = (TextView) layout.findViewById(R.id.update_tv_yes);
        TextView update_tv_no = (TextView) layout.findViewById(R.id.update_tv_no);
        final CheckBox cb = (CheckBox) layout.findViewById(R.id.cb);

        TextView new_banben = (TextView) layout.findViewById(R.id.new_banben);
        TextView apk_size = (TextView) layout.findViewById(R.id.apk_size);
        TextView new_context1 = (TextView) layout.findViewById(R.id.new_context1);

        new_banben.setText("最新版本: " + ed_num);
        apk_size.setText("新版本大小: " + size);
        new_context1.setText(content);


        final AlertDialog dialog = new AlertDialog.Builder(context).create();
        dialog.show();
        dialog.getWindow().setContentView(layout);

        Window dialogWindow = dialog.getWindow();
        dialogWindow.setGravity(Gravity.CENTER);
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        //屏幕宽高度
        WindowManager m = ((MainActivity) context).getWindowManager();
        Display d = m.getDefaultDisplay();
        //lp.height = (int) (d.getHeight() * 0.4);
        lp.width = (int) (d.getWidth() * 0.9);
        dialogWindow.setAttributes(lp);

        update_tv_yes.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, Update_Service.class);
                intent.putExtra("apk_url",apk_url);
                context.startService(intent);

                Toast.makeText(context, "下载中,请稍等…", Toast.LENGTH_SHORT).show();
                dialog.dismiss();
            }
        });

        update_tv_no.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (cb.isChecked()) {
                    dialog.dismiss();
                    SharedPreferences sharedPreferences = context.getSharedPreferences("update", Context.MODE_PRIVATE);
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putInt("num", version);
                    editor.commit();
                } else {
                    dialog.dismiss();
                }
            }
        });
    }
}

对话框布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="25dp"
    android:paddingTop="5dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="发现新版本"
        android:textColor="#009aff"
        android:textSize="16sp" />

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:background="#009aff" />

    <TextView
        android:id="@+id/new_banben"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="20dp"
        android:textSize="15sp" />

    <TextView
        android:id="@+id/apk_size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="10dp"
        android:textSize="15sp" />

    <TextView
        android:id="@+id/new_context"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:text="更新内容:"
        android:textSize="15sp" />

    <TextView
        android:id="@+id/new_context1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="5dp"
        android:textSize="15sp" />

    <CheckBox
        android:id="@+id/cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="15dp"
        android:checked="false"
        android:text="忽略本版"
        android:textColor="#666"
        android:textSize="16sp">
    </CheckBox>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/update_tv_no"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="5dp"
            android:layout_weight="1"
            android:background="@drawable/next_update_tv"
            android:gravity="center"
            android:paddingBottom="5dp"
            android:paddingTop="5dp"
            android:text="下次再说"
            android:textSize="15sp" />

        <TextView
            android:id="@+id/update_tv_yes"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="10dp"
            android:layout_weight="1"
            android:background="@drawable/now_update_tv"
            android:gravity="center"
            android:paddingBottom="5dp"
            android:paddingTop="5dp"
            android:text="立即更新"
            android:textColor="#fff"
            android:textSize="15sp" />

    </LinearLayout>
</LinearLayout>
服务中开始下载, okgo用到的依赖:

compile 'com.lzy.net:okgo:2.0.0'
compile 'com.lzy.net:okrx:0.1.0'
compile 'com.lzy.net:okserver:1.1.0'

public class Update_Service extends Service {
    private NotificationManager notifyManager;
    private NotificationCompat.Builder builder;
    private RemoteViews mRemoteViews;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mRemoteViews = new RemoteViews(getPackageName(), R.layout.update_progress);
        mRemoteViews.setImageViewResource(R.id.icon_pg, R.mipmap.icon);
        mRemoteViews.setTextViewText(R.id.pg_tv, "0%");
        builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.icon)
                .setContentTitle("正在下载安装包")
                .setContentText("请稍等…")
                .setTicker("开始更新")
                .setContent(mRemoteViews);

        notifyManager.notify(1, builder.build());

        down(intent.getStringExtra("apk_url"));
        return Service.START_STICKY;

    }

    void down(String url2) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            String sdpath = Environment.getExternalStorageDirectory().getAbsolutePath();
            OkGo.get(url2)
                    .tag(this)
                    .execute(new FileCallback(sdpath, "fenglaike.apk") {
                        @Override
                        public void onBefore(BaseRequest request) {

                        }

                        @Override
                        public void onSuccess(File file, Call call, Response response) {
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            getApplicationContext().startActivity(intent);
                            stopSelf();
                            notifyManager.cancelAll();
                        }

                        @Override
                        public void downloadProgress(long currentSize, long totalSize, float progress, long networkSpeed) {

                            mRemoteViews.setProgressBar(R.id.pg, 100, (int) (Math.round(progress * 10000) * 1.0f / 100), false);
                            mRemoteViews.setTextViewText(R.id.pg_tv, (Math.round(progress * 10000) * 1.0f / 100) + "%");
                            notifyManager.notify(1, builder.build());

                        }

                        @Override
                        public void onError(Call call, @Nullable Response response, @Nullable Exception e) {
                            super.onError(call, response, e);
                            Toast.makeText(getApplicationContext(), "下载出错,请重新下载", Toast.LENGTH_SHORT).show();
                        }
                    });

        } else {
            Toast.makeText(getApplicationContext(), "存储卡装载错误", Toast.LENGTH_SHORT).show();
        }
    }
}

通知栏布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="65dp"
    android:gravity="center_vertical"
    android:orientation="horizontal">


    <ImageView
        android:id="@+id/icon_pg"
        android:layout_width="45dp"
        android:layout_height="45dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="15dp"
            android:layout_marginLeft="10dp"
            android:text="更新下载中"
            android:textSize="10sp" />

        <ProgressBar
            android:id="@+id/pg"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="3.5dp"
            android:progressDrawable="@drawable/pg_style"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="5dp"
            android:background="#debd2c"
            android:max="100"
            android:progress="0" />

        <TextView
            android:id="@+id/pg_tv"
            android:layout_width="wrap_content"
            android:layout_height="15dp"
            android:layout_marginLeft="10dp"
            android:text="25%"
            android:textSize="10sp" />
    </LinearLayout>


</LinearLayout>

进度条背景:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 这个是背景颜色 -->
    <item android:id="@android:id/background">
        <shape>

            <!-- 这个是设置圆角还会直角,如果设置成0dip就是直角 -->
            <corners android:radius="5dip" />
            <!-- 设置背景的颜色,将startColor、centerColor、endColor都设置成同一个颜色值 -->
            <!--
                 如果你不用颜色值也可以,可以直接用图片来代替,在item中添加这个属性就可以了,其他的不需要
                 android:drawable="@drawable/progressbar_bg"
            -->
            <gradient
                android:endColor="#DDE3E4"
                android:startColor="#DDE3E4" />
        </shape>
    </item>
    <!-- 这个是第二进度条的颜色,没用到,大同小异 -->
    <!--<item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="5dip" />

                <gradient
                    android:angle="270"
                    android:centerColor="#80C07AB8"
                    android:centerY="0.75"
                    android:endColor="#a0C07AB8"
                    android:startColor="#80C07AB8" />
            </shape>
        </clip>
    </item>-->
    <!-- 这个是设置你进度的颜色 -->
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <!-- 这个也是设置时圆角还是直角,左边的 -->
                <corners android:radius="5dip" />
                <!-- 设置进度的颜色,将startColor、centerColor、endColor都设置成同一个颜色值 -->
                <gradient
                    android:endColor="#009aff"
                    android:startColor="#009aff" />
            </shape>
        </clip>
    </item>
</layer-list>
为了在关闭应用后还可以继续下载,可以再开启一个进程:

<service
            android:name=".update.Update_Service"
            android:process=":download" />









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值