App实现自动更新
来源:互联网 发布:无人机遥控软件 编辑:程序博客网 时间:2024/05/29 23:47
app上线之后会经常面临版本更新,因此每当有新版本发布时,应用自动更新就显得很有必要!其实整个实现并不复杂,通过后台返回的url,利用Httpurl去下载即可,同时在通知栏显示下载进度.当下载完成时,自动跳转至安装页面.
首先仍然是我代码的目录结构
/**事件的监听回调 * Created by Administrator on 2017/8/14. */public interface UpdateDownloadListener { //下载请求开始回调 public void onStarted(); //进度更新回调 public void onProgressChanged(int progress,String downloadUrl); //下载完成回调 public void onFinished(int completeSize,String downloadUrl); //下载失败回调 public void onFailure();}/**真正的负责处理文件的下载和线程间的通信 * Created by Administrator on 2017/8/14. */public class UpdateDownloadRequest implements Runnable{ private String downloadUrl; private String localFilePath; private UpdateDownloadListener downloadListener; //下载的标记位 private boolean isDownloading=false; //文件长度 private long currentLength; private DownloadResponseHandler downloadHandler; public UpdateDownloadRequest(String downloadUrl,String localFilePath,UpdateDownloadListener downloadListener) { this.downloadUrl=downloadUrl; this.localFilePath=localFilePath; this.downloadListener=downloadListener; //构造方法完成则开始下载 this.isDownloading=true; this.downloadHandler=new DownloadResponseHandler(); } //真正的去建立连接的方法 private void makeRequest() throws IOException,InterruptedException { try { if (!Thread.currentThread().isInterrupted()) { URL url = new URL(downloadUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5000); //默认也是如此,重新设置避免关闭 connection.setRequestProperty("Connection","Keep-Alive"); connection.connect(); currentLength = connection.getContentLength(); if (!Thread.currentThread().isInterrupted()) { //真正完成文件的下载 downloadHandler.sendResponseMessage(connection.getInputStream()); } } }catch (IOException e){ throw e; } } @Override public void run() { try{ makeRequest(); } catch (IOException e){ }catch (InterruptedException e){ } } //格式化数据,保留两位小数 private String getTwoPointFloatStr(float value) { DecimalFormat format = new DecimalFormat("0.00"); return format.format(value); } //包含了下载过程中所有可能出现的异常情况 public enum FailureCode{ UnknowHost,Socket,SocketTimeout,ConnectTimeout,IO,HttpResponse,JSON,Interrupted } //用来真正的去下载文件,并发送消息和回调接口 public class DownloadResponseHandler{ protected static final int SUCCESS_MESSAGE=0; protected static final int FAILURE_MESSAGE=1; protected static final int START_MESSAGE=2; protected static final int FINISH_MESSAGE=3; protected static final int NETWORK_OFF=4; protected static final int PROGRESS_CHANGED=5; private int mCompleteSize=0; private int progress=0; private int preProgress=0; //真正的完成线程间的通信 private Handler handler; public DownloadResponseHandler() { //依附于主线程 handler=new Handler(Looper.getMainLooper()){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); handleSelfMessage(msg); } }; } //用来发送不同的消息对象 protected void sendFinishMessage() { sendMessage(obtainMessage(FINISH_MESSAGE,null)); } private void sendProgressChangedMessage(int progress) { sendMessage(obtainMessage(PROGRESS_CHANGED,new Object[]{progress})); } protected void sendFailureMessage(FailureCode failureCode) { sendMessage(obtainMessage(FAILURE_MESSAGE,new Object[]{failureCode})); } protected void sendMessage(Message msg) { if (handler!=null) { handler.sendMessage(msg); } else { handleSelfMessage(msg); } } //获取一个消息对象 protected Message obtainMessage(int responseMessage,Object response) { Message msg=null; if (handler!=null) { msg=handler.obtainMessage(responseMessage,response); } else { msg=Message.obtain(); msg.what=responseMessage; msg.obj=response; } return msg; } protected void handleSelfMessage(Message msg) { Object[] response; switch (msg.what) { case FAILURE_MESSAGE: response= (Object[]) msg.obj; handleFailureMessage((FailureCode)response[0]); break; case PROGRESS_CHANGED: response= (Object[]) msg.obj; handleProgressChangedMessage(((Integer)response[0]).intValue()); break; case FINISH_MESSAGE: onFinish(); break; default: break; } } //各种消息的处理逻辑 protected void handleProgressChangedMessage(int progress) { downloadListener.onProgressChanged(progress,""); } protected void handleFailureMessage(FailureCode failureCode) { onFailure(failureCode); } //外部接口的回调 public void onFinish() { downloadListener.onFinished(mCompleteSize,""); } public void onFailure(FailureCode failureCode) { downloadListener.onFailure(); } //文件下载方法,会发送各种类型的事件,比如下载开始,下载结束,更新进度条等 void sendResponseMessage(InputStream inputStream) { RandomAccessFile randomAccessFile=null; //记录下载进度 mCompleteSize=0; try{ byte[] buff = new byte[1024]; int length=-1; int limit=0; randomAccessFile=new RandomAccessFile(localFilePath,"rwd"); while ((length=inputStream.read(buff))!=-1) { if (isDownloading) { randomAccessFile.write(buff,0,length); mCompleteSize+=length; if (mCompleteSize<=currentLength) { progress= (int) (mCompleteSize*1.0f/currentLength*100); if (progress>=99||(limit%30==0&&progress<=100)) { Log.e("======","====progress===="+progress); /*if (preProgress!=progress) {*/ sendProgressChangedMessage(progress); /*}*/ } limit++; preProgress=progress; } } } sendFinishMessage(); }catch (IOException e){ //异常时发送消息 sendFailureMessage(FailureCode.IO); } finally { try { if (inputStream!=null) { inputStream.close(); } if (randomAccessFile!=null) { randomAccessFile.close(); } }catch (IOException e) { sendFailureMessage(FailureCode.IO); } } } }}/**下载调度管理器,调用我们的updateDownloadRequest * Created by Administrator on 2017/8/14. */public class UpdateManager { private static UpdateManager manager; private ThreadPoolExecutor threadPoolExecutor; private UpdateDownloadRequest request; public UpdateManager() { threadPoolExecutor= (ThreadPoolExecutor) Executors.newCachedThreadPool(); } public static UpdateManager getInstance() { if (manager==null) { manager=new UpdateManager(); } return manager; } public void startDownloads(String downloadUrl,String localPath,UpdateDownloadListener listener) { if (request!=null) { return; } checkLocalFilePath(localPath); request=new UpdateDownloadRequest(downloadUrl,localPath,listener); threadPoolExecutor.submit(request); } //检查本地文件路径 private void checkLocalFilePath(String localPath) { File dir = new File(localPath.substring(0, localPath.lastIndexOf("/") + 1)); if (!dir.exists()) { dir.mkdirs(); } File file = new File(localPath); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } }}/**app更新下载后台服务 * Created by Administrator on 2017/8/14. */public class UpdateService extends Service{ private String apkUrl; private String filePath; private NotificationManager notificationManager; private Notification notification; @Override public void onCreate() { super.onCreate(); notificationManager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE); filePath= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator+"autoupdate"+File.separator+"auto.apk"; } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent==null) { notifyUser("下载失败","下载地址错误",0); stopSelf(); } else { apkUrl=intent.getStringExtra("apkUrl"); notifyUser("开始下载","开始下载",0); startDownload(); } return super.onStartCommand(intent, flags, startId); } private void startDownload() { UpdateManager.getInstance().startDownloads(apkUrl, filePath, new UpdateDownloadListener() { @Override public void onStarted() { } @Override public void onProgressChanged(int progress, String downloadUrl) { notifyUser("正在下载","正在下载",progress); } @Override public void onFinished(int completeSize, String downloadUrl) { notifyUser("下载完成","下载完成",100); stopSelf(); } @Override public void onFailure() { notifyUser("下载失败","下载失败",0); stopSelf(); } }); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } //更新我们的notification来告知用户当前下载的进度 private void notifyUser(String result, String reason,int progress) { NotificationCompat.Builder builder=new NotificationCompat.Builder(this); builder.setSmallIcon(R.mipmap.logol) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.logol)) .setContentTitle("autoupdate"); //Log.e("===progress===","======"+progress); if (progress>0&&progress<100) { builder.setProgress(100,progress,false); } else { builder.setProgress(0,0,false); } builder.setAutoCancel(true); builder.setWhen(System.currentTimeMillis()); builder.setTicker(result); if (progress>=100) { getContentIntent(); } else { /*builder.setContentIntent(progress>=100?getContentIntent(): PendingIntent.getActivity(this,0,new Intent(),PendingIntent.FLAG_UPDATE_CURRENT));*/ builder.setContentIntent(PendingIntent.getActivity(this,0,new Intent(),PendingIntent.FLAG_UPDATE_CURRENT)); notification=builder.build(); notificationManager.notify(0,notification); } } private PendingIntent getContentIntent() { //创建一个开启安装App界面的意图 File apkFile = new File(filePath); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //判断版本是否在7.0以上 if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N) { Uri apkUri = FileProvider.getUriForFile(this, "com.example.administrator.myautoupdate" + ".fileprovider", apkFile); //添加这一句表示对目标应用临时授权该uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(apkUri,"application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.parse("file://"+apkFile.getAbsolutePath()),"application/vnd.android.package-archive"); //intent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive"); } startActivity(intent); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return pendingIntent; }}public class MainActivity extends AppCompatActivity { Button button_bt; String url="http://wap.sogou.com/app/redir.jsp?appdown=1&u=0Gd8piB6093-W-QPHXpNcQJvLH6U5CYd9F0_TSI0vGQYAGh2YbdCmC1hNfN-kHhp&docid=2355133373028692437&sourceid=-5321678202930570851&w=1906&stamp=20170814"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button_bt= (Button) findViewById(R.id.button_bt); button_bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { checkVersion(); } }); checkVersion(); } private void checkVersion() { CommonDialog dialog = new CommonDialog(this); dialog.setListener(new CommonDialog.CommonDialogListener() { @Override public void confirm() { Intent intent = new Intent(MainActivity.this, UpdateService.class); intent.putExtra("apkUrl",url); startService(intent); } }); dialog.show(); }}虽然代码不复杂,但还是得敲过才知道!
程序运行时,界面效果如下
阅读全文
0 0
- Retrofit2实现App自动更新
- Retrofit2实现App自动更新
- Android实现APP自动更新
- App实现自动更新
- App实现自动更新
- Android实现APP自动更新功能
- Android实现App版本自动更新
- Android实现App版本自动更新
- Android实现App版本自动更新
- Android App应用程序实现自动更新
- App自动更新基础实现方式
- Android实现App版本自动更新
- Android如何实现APP自动更新
- 通过RSS实现app的自动更新
- 简单实现安卓app自动更新功能
- Android实现APP版本自动更新功能
- 关于ionic 开发自动更新app的实现
- 实现App自动更新,一个方法搞定
- SVN迁移IP变更地址修改relocate
- 【HDU
- Android5.0
- USB协议解析
- springmvc配置详细讲解
- App实现自动更新
- 对Ajax的理解
- iscc2017 pwn
- KNN算法实现问题记录
- tomcat的配置流程
- 处理SIGCHLD信号(CS模型改进4)
- JavaScript轮播图(三)
- C语言 数组行列数获取
- 读取Ini