美文网首页Android开发武科大领航工作室
Android-第一行代码下载示例&下载后跳转安装

Android-第一行代码下载示例&下载后跳转安装

作者: 棒棒小糖 | 来源:发表于2018-12-06 22:24 被阅读3次

    最近项目要做软件内更新(在app中下载安装包),因为之前从来没做过下载,所以就照着《第一行代码》上的下载示例敲了一遍。

    先看看项目中的文件目录,主要有一个下载监听接口,下载服务,下载
    的AsyncTask以及一个测试界面。

    DownloadListener文件代码:

    public interface DownloadListener {
    
        void onProgress(int progress);
    
        void onSuccess();
    
        void onFailed();
    
        void onPaused();
    
        void onCancel();
    }
    

    DownloadService文件代码:(在第一行代码的基础上加了个openFile的方法,用来在下载完成时自动安装)

    public class DownloadService extends Service {
        private String downloadUrl;
        private DownloadTask mDownloadTask;
        private final int notifyId = 1;
    
        private DownloadListener mListener = new DownloadListener( ) {
            @Override
            public void onProgress(int progress) {
                getNotificationManager().notify(notifyId, getNotification("下载中...", progress));
            }
    
            @Override
            public void onSuccess() {
                mDownloadTask = null;
                // 下载成功后将前台服务关闭,创建一个下载完成的通知
                stopForeground(true);
                getNotificationManager().notify(notifyId, getNotification("下载成功!", -1));
                ToastUtil.showToast("下载成功!");
                String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
                String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
                File file = new File(directory + fileName);
                openFile(file);
            }
    
            @Override
            public void onFailed() {
                mDownloadTask = null;
                // 下载失败时将前台服务关闭,创建一个下载失败的通知
                stopForeground(true);
                getNotificationManager().notify(notifyId, getNotification("下载失败!", -1));
                ToastUtil.showToast("下载失败!");
            }
    
            @Override
            public void onPaused() {
                downloadUrl = null;
                ToastUtil.showToast("已暂停");
            }
    
            @Override
            public void onCancel() {
                mDownloadTask =null;
                stopForeground(true);
                ToastUtil.showToast("已取消");
            }
        };
    
        private DownloadBinder mBinder = new DownloadBinder();
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        class DownloadBinder extends Binder {
    
            public void startDownload(String url) {
                if (mDownloadTask == null) {
                    downloadUrl = url;
                    mDownloadTask = new DownloadTask(mListener);
                    mDownloadTask.execute(downloadUrl);
                    startForeground(notifyId, getNotification("下载中...", 0));
                    ToastUtil.showToast("开始下载");
                }
            }
    
            public void pauseDownload() {
                if (mDownloadTask != null) {
                    mDownloadTask.pauseDownload();
                }
            }
    
            public void cancelDownload() {
                if (mDownloadTask != null) {
                    mDownloadTask.cancelDownload();
                } else {
                    if (downloadUrl != null) {
                        // 取消下载,将文件删除并关闭通知
                        String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
                        String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
                        File file = new File(directory + fileName);
                        if (file.exists()) {
                            file.delete();
                        }
                        getNotificationManager().cancel(notifyId);
                        stopForeground(true);
                        ToastUtil.showToast("已取消");
                    }
                }
            }
        }
    
        private NotificationManager getNotificationManager() {
            return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        }
    
        private Notification getNotification(String title, int progress) {
            //Intent intent = new Intent(this, MainActivity.class);
            //PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "1000");
            builder.setSmallIcon(R.mipmap.logo)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.logo))
                    .setContentTitle(title)
                    .setAutoCancel(true);
            if (progress >= 0) {
                // progress大于等于0时才显示下载进度
                builder.setContentText(progress + "%");
                builder.setProgress(100, progress, false);
            }
            //builder.setContentIntent(pi);
            return builder.build();
        }
    
        private void openFile(File f) {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setAction(android.content.Intent.ACTION_VIEW);
            String type = "application/vnd.android.package-archive";
            intent.setDataAndType(Uri.fromFile(f), type);
            startActivity(intent);
        }
    }
    

    DownloadTask文件:

    public class DownloadTask extends AsyncTask<String, Integer, Integer> {
    
        public static final int TYPE_SUCCESS = 0;
        public static final int TYPE_FAILED = 1;
        public static final int TYPE_PAUSE = 2;
        public static final int TYPE_CANCELED = 3;
    
        private DownloadListener mListener;
    
        private boolean isCanceled = false;
        private boolean isPaused = false;
        private int lastProgress = 0;
    
        public DownloadTask(DownloadListener listener) {
            mListener = listener;
        }
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute( );
        }
    
        @Override
        protected Integer doInBackground(String... strings) {
            InputStream is = null;
            RandomAccessFile savedFile = null;
            File file = null;
            try{
                // 记录已下载的文件长度
                long downloadLength = 0;
                // 传入第一个参数为下载地址
                String downloadUrl = strings[0];
    
                String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
                // 保存到sd卡,这里是获取的是内部sd卡路径
                String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
                file = new File(directory + fileName);
                // 说明已经下载了,文件存在
                if (file.exists()) {
                    downloadLength = file.length();
                }
                // 获取网络上的文件长度
                long contentLength = getContentLength(downloadUrl);
                if (contentLength == 0) {
                    // 获得文件字节出错
                    return TYPE_FAILED;
                } else if (contentLength == downloadLength) {
                    // 网络文件与本地文件长度相同,说明文件已下载好
                    return TYPE_SUCCESS;
                }
    
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder()
                        // 断点下载,指定从哪个字节下载
                        .addHeader("RANGE", "bytes=" + downloadLength + "-")
                        .url(downloadUrl)
                        .build();
                Response response = client.newCall(request).execute();
                if (response != null) {
                    is = response.body().byteStream();
                    savedFile = new RandomAccessFile(file, "rw");
                    // 跳过已下载的字节
                    savedFile.seek(downloadLength);
                    byte[] b = new byte[1024];
                    int total = 0;
                    int len;
                    while ((len = is.read(b)) != -1) {
                        if (isCanceled) {
                            return TYPE_CANCELED;
                        } else if (isPaused) {
                            return TYPE_PAUSE;
                        } else {
                            total += len;
                            savedFile.write(b, 0, len);
                            // 计算已下载的百分比
                            int progress = (int) ((total + downloadLength) * 100 / contentLength);
                            publishProgress(progress);
                        }
                    }
                    response.body().close();
                    return TYPE_SUCCESS;
                }
            }catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (is != null) {
                        is.close();
                    }
                    if (savedFile != null) {
                        savedFile.close();
                    }
                    if (isCanceled && file != null) {
                        file.delete();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return TYPE_FAILED;
        }
    
        @Override
        protected void onProgressUpdate(Integer... values) {
            int progress = values[0];
            // 进度比最新进度还要大,就更新最新进度
            if (progress > lastProgress) {
                mListener.onProgress(progress);
                lastProgress = progress;
            }
        }
    
        @Override
        protected void onPostExecute(Integer status) {
            switch (status) {
                case TYPE_SUCCESS:
                    mListener.onSuccess();
                    break;
                case TYPE_CANCELED:
                    mListener.onCancel();
                    break;
                case TYPE_PAUSE:
                    mListener.onPaused();
                    break;
                case TYPE_FAILED:
                    mListener.onFailed();
                    default:
                        break;
            }
        }
    
        private long getContentLength(String downloadUrl) throws IOException {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(downloadUrl)
                    .build();
            Response response = client.newCall(request).execute();
            if (response != null && response.isSuccessful()) {
                long contentLength = response.body().contentLength();
                response.body().close();
                return contentLength;
            }
            return 0;
        }
    
        public void pauseDownload() {
            isPaused = true;
        }
    
        public void cancelDownload() {
            isCanceled = true;
        }
    }
    

    UpdateTestActivity界面:(这里我用了EasyPermission开源库,要用库的同学可自行导库,很简单,这里不多说)

    public class UpdateTestActivity extends AppCompatActivity implements View.OnClickListener, EasyPermissions.PermissionCallbacks {
    
        private DownloadService.DownloadBinder mDownloadBinder;
    
        private ServiceConnection mConnection = new ServiceConnection( ) {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                mDownloadBinder = (DownloadService.DownloadBinder) iBinder;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {}
        };
    
        public static Intent newInstance(Context context) {
            return new Intent(context, UpdateTestActivity.class);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate( savedInstanceState );
            setContentView( R.layout.activity_update_test );
            Button start = findViewById(R.id.btn_start_download);
            Button pause = findViewById(R.id.btn_pause_download);
            Button cancel = findViewById(R.id.btn_cancel_download);
            start.setOnClickListener(this);
            pause.setOnClickListener(this);
            cancel.setOnClickListener(this);
    
            Intent intent = new Intent(this, DownloadService.class);
            startService(intent);
            bindService(intent, mConnection, BIND_AUTO_CREATE);
    
            if (ContextCompat.checkSelfPermission(UpdateTestActivity.this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                EasyPermissions.requestPermissions(this, "请求向存储卡写入文件", 1, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy( );
            unbindService(mConnection);
        }
    
        @Override
        public void onClick(View view) {
            if (mDownloadBinder == null) {
                return;
            }
            switch (view.getId()) {
                case R.id.btn_start_download:
                    String url = "放你的测试下载地址,最好不要用书上的地址,会有超时错误";
                    mDownloadBinder.startDownload(url);
                    break;
                case R.id.btn_pause_download:
                    mDownloadBinder.pauseDownload();
                    break;
                case R.id.btn_cancel_download:
                    mDownloadBinder.cancelDownload();
                    break;
                    default:
                        break;
            }
        }
    
        @Override
        public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
            if (requestCode == 1) {
    
            }
        }
    
        @Override
        public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
            if (requestCode == 1) {
                ToastUtil.showToast("拒绝权限无法运行");
                finish();
            }
        }
    }
    

    最后在manifast中加上权限:

        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    

    运行的下载的图片就不放了,因为我直接放到项目中了,放应用图标好像不太好,等项目上线了我再来更新简书,把图放上。

    (ps:找了一晚上升级的火箭图片,还P了一下图,才勉强做完了项目的更新界面,没有美工是真的烦。搞得写简书都没时间,只能简单的贴一贴代码了。哦,还有,天气越来越冷了,大家注意保暖哦!)

    相关文章

      网友评论

        本文标题:Android-第一行代码下载示例&下载后跳转安装

        本文链接:https://www.haomeiwen.com/subject/fsuwcqtx.html