Android实现APP自动更新功能

现在一般的android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新。该小程序实现的就是这个功能。

该小程序的特点是,当有更新时,会弹出一个提示框,点击确定,则在通知来创建一个进度条进行下载,点击取消,则取消更新。

以下是详细代码:

1.创建布局文件notification_item.xml,用于在通知栏生成一个进度条和下载图标。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:padding="3dp" > 

 <ImageView
  android:id="@+id/notificationImage"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@android:drawable/stat_sys_download" /> 

 <TextView
  android:id="@+id/notificationTitle"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentRight="true"
  android:layout_toRightOf="@id/notificationImage"
  android:paddingLeft="6dp"
  android:textColor="#FF000000" /> 

 <TextView
  android:id="@+id/notificationPercent"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_below="@id/notificationImage"
  android:paddingTop="2dp"
  android:textColor="#FF000000" /> 

 <ProgressBar
  android:id="@+id/notificationProgress"
  style="@style/ProgressBarHorizontal_color"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignLeft="@id/notificationTitle"
  android:layout_alignParentRight="true"
  android:layout_alignTop="@id/notificationPercent"
  android:layout_below="@id/notificationTitle"
  android:paddingLeft="6dp"
  android:paddingRight="3dp"
  android:paddingTop="2dp" /> 

</RelativeLayout>

2.创建AppContext类,该类继承自Application。

package com.test.application; 

import android.app.Application;
import android.content.Context; 

import com.test.update.config.Config; 

public class AppContext extends Application {
 private static AppContext appInstance;
 private Context context; 

 public static AppContext getInstance() {
  return appInstance;
 } 

 @Override
 public void onCreate() {
  // TODO Auto-generated method stub
  super.onCreate();
  appInstance = this;
  context = this.getBaseContext();
//  // 获取当前版本号
//  try {
//   PackageInfo packageInfo = getApplicationContext()
//     .getPackageManager().getPackageInfo(getPackageName(), 0);
//   Config.localVersion = packageInfo.versionCode;
//   Config.serverVersion = 1;// 假定服务器版本为2,本地版本默认是1
//  } catch (NameNotFoundException e) {
//   e.printStackTrace();
//  }
  initGlobal();
 } 

 public void initGlobal() {
  try {
   Config.localVersion = getPackageManager().getPackageInfo(
     getPackageName(), 0).versionCode; // 设置本地版本号
   Config.serverVersion = 2;// 假定服务器版本为2,本地版本默认是1--实际开发中是从服务器获取最新版本号,android具体与后端的交互见我另///外的博文
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }
}

3.创建配置文件类Config.java,在这个类里面定义一些与版本相关的常量

package com.test.update.config; 

public class Config {
 //版本信息
 public static int localVersion = 0;
 public static int serverVersion = 0;
 /* 下载包安装路径 */
 public static final String savePath = "/sdcard/test/"; 

 public static final String saveFileName = savePath + "test.apk";
}

4.编写更新服务类UpdateServcie.java

package com.test.update; 

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; 

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.RemoteViews; 

import com.test.update.config.Config; 

public class UpdateService extends Service {
 // 标题
 private int titleId = 0; 

 // 文件存储
 private File updateDir = null;
 private File updateFile = null;
 // 下载状态
 private final static int DOWNLOAD_COMPLETE = 0;
 private final static int DOWNLOAD_FAIL = 1;
 // 通知栏
 private NotificationManager updateNotificationManager = null;
 private Notification updateNotification = null;
 // 通知栏跳转Intent
 private Intent updateIntent = null;
 private PendingIntent updatePendingIntent = null;
 /***
  * 创建通知栏
  */
 RemoteViews contentView;
 // 这样的下载代码很多,我就不做过多的说明
 int downloadCount = 0;
 int currentSize = 0;
 long totalSize = 0;
 int updateTotalSize = 0; 

 // 在onStartCommand()方法中准备相关的下载工作:
 @SuppressWarnings("deprecation")
 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
  // 获取传值
  titleId = intent.getIntExtra("titleId", 0);
  // 创建文件
  if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment
    .getExternalStorageState())) {
   updateDir = new File(Environment.getExternalStorageDirectory(),
     Config.saveFileName);
   updateFile = new File(updateDir.getPath(), getResources()
     .getString(titleId) + ".apk");
  } 

  this.updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  this.updateNotification = new Notification(); 

  // 设置下载过程中,点击通知栏,回到主界面
  updateIntent = new Intent(this, UpdateActivity.class);
  updatePendingIntent = PendingIntent.getActivity(this, 0, updateIntent,
    0);
  // 设置通知栏显示内容
  updateNotification.icon = R.drawable.ic_launcher;
  updateNotification.tickerText = "开始下载";
  updateNotification.setLatestEventInfo(this, "QQ", "0%",
    updatePendingIntent);
  // 发出通知
  updateNotificationManager.notify(0, updateNotification); 

  // 开启一个新的线程下载,如果使用Service同步下载,会导致ANR问题,Service本身也会阻塞
  new Thread(new updateRunnable()).start();// 这个是下载的重点,是下载的过程 

  return super.onStartCommand(intent, flags, startId);
 } 

 @Override
 public IBinder onBind(Intent arg0) {
  // TODO Auto-generated method stub
  return null;
 } 

 @SuppressLint("HandlerLeak")
 private Handler updateHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
   switch (msg.what) { 

   case DOWNLOAD_COMPLETE:
    // 点击安装PendingIntent
    Uri uri = Uri.fromFile(updateFile);
    Intent installIntent = new Intent(Intent.ACTION_VIEW);
    installIntent.setDataAndType(uri,
      "application/vnd.android.package-archive"); 

    updatePendingIntent = PendingIntent.getActivity(
      UpdateService.this, 0, installIntent, 0); 

    updateNotification.defaults = Notification.DEFAULT_SOUND;// 铃声提醒
    updateNotification.setLatestEventInfo(UpdateService.this,
      "QQ", "下载完成,点击安装。", updatePendingIntent);
    updateNotificationManager.notify(0, updateNotification); 

    // 停止服务
    stopService(updateIntent);
   case DOWNLOAD_FAIL:
    // 下载失败
    updateNotification.setLatestEventInfo(UpdateService.this,
      "QQ", "下载完成,点击安装。", updatePendingIntent);
    updateNotificationManager.notify(0, updateNotification);
   default:
    stopService(updateIntent);
   }
  }
 }; 

 public long downloadUpdateFile(String downloadUrl, File saveFile)
   throws Exception { 

  HttpURLConnection httpConnection = null;
  InputStream is = null;
  FileOutputStream fos = null; 

  try {
   URL url = new URL(downloadUrl);
   httpConnection = (HttpURLConnection) url.openConnection();
   httpConnection
     .setRequestProperty("User-Agent", "PacificHttpClient");
   if (currentSize > 0) {
    httpConnection.setRequestProperty("RANGE", "bytes="
      + currentSize + "-");
   }
   httpConnection.setConnectTimeout(10000);
   httpConnection.setReadTimeout(20000);
   updateTotalSize = httpConnection.getContentLength();
   if (httpConnection.getResponseCode() == 404) {
    throw new Exception("fail!");
   }
   is = httpConnection.getInputStream();
   fos = new FileOutputStream(saveFile, false);
   byte buffer[] = new byte[4096];
   int readsize = 0;
   while ((readsize = is.read(buffer)) > 0) {
    fos.write(buffer, 0, readsize);
    totalSize += readsize;
    // 为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次
    if ((downloadCount == 0)
      || (int) (totalSize * 100 / updateTotalSize) - 10 > downloadCount) {
     downloadCount += 10; 

     updateNotification.setLatestEventInfo(UpdateService.this,
       "正在下载", (int) totalSize * 100 / updateTotalSize
         + "%", updatePendingIntent); 

     /***
      * 在这里我们用自定的view来显示Notification
      */
     updateNotification.contentView = new RemoteViews(
       getPackageName(), R.layout.notification_item);
     updateNotification.contentView.setTextViewText(
       R.id.notificationTitle, "正在下载");
     updateNotification.contentView.setProgressBar(
       R.id.notificationProgress, 100, downloadCount, false); 

     updateNotificationManager.notify(0, updateNotification);
    }
   }
  } finally {
   if (httpConnection != null) {
    httpConnection.disconnect();
   }
   if (is != null) {
    is.close();
   }
   if (fos != null) {
    fos.close();
   }
  }
  return totalSize;
 } 

 class updateRunnable implements Runnable {
  Message message = updateHandler.obtainMessage(); 

  public void run() {
   message.what = DOWNLOAD_COMPLETE; 

   try {
    // 增加权限<USES-PERMISSION
    // android:name="android.permission.WRITE_EXTERNAL_STORAGE">;
    if (!updateDir.exists()) {
     updateDir.mkdirs();
    }
    if (!updateFile.exists()) {
     updateFile.createNewFile();
    }
    // 下载函数,以QQ为例子
    // 增加权限<USES-PERMISSION
    // android:name="android.permission.INTERNET">;
    long downloadSize = downloadUpdateFile(
      "http://softfile.3g.qq.com:8080/msoft/179/1105/10753/MobileQQ1.0(Android)_Build0198.apk",
      updateFile);
    if (downloadSize > 0) {
     // 下载成功
     updateHandler.sendMessage(message);
    }
   } catch (Exception ex) {
    ex.printStackTrace();
    message.what = DOWNLOAD_FAIL;
    // 下载失败
    updateHandler.sendMessage(message);
   }
  }
 }
}

5.编写活动类UpdateActivity

package com.test.update; 

import com.test.update.config.Config; 

import android.support.v4.app.Fragment;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater; 

public class UpdateActivity extends Activity { 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  checkVersion();
 } 

 /**
  * 检查更新版本
  */
 public void checkVersion() { 

  if (Config.localVersion < Config.serverVersion) {
   Log.i("hgncxzy", "==============================");
   // 发现新版本,提示用户更新
   AlertDialog.Builder alert = new AlertDialog.Builder(this);
   alert.setTitle("软件升级")
     .setMessage("发现新版本,建议立即更新使用.")
     .setPositiveButton("更新",
       new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,
          int which) {
         // 开启更新服务UpdateService
         // 这里为了把update更好模块化,可以传一些updateService依赖的值
         // 如布局ID,资源ID,动态获取的标题,这里以app_name为例
         Intent updateIntent = new Intent(
           UpdateActivity.this,
           UpdateService.class);
         updateIntent.putExtra("titleId",
           R.string.app_name);
         startService(updateIntent);
        }
       })
     .setNegativeButton("取消",
       new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,
          int which) {
         dialog.dismiss();
        }
       });
   alert.create().show();
  } else {
   // 清理工作,略去
   // cheanUpdateFile()
  }
 }
} 

6.添加权限以及将服务静态加载(在配置文件中加载)。

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

注册服务

<service android:name="com.test.update.UpdateService" >
  </service>

完整的AndroidManifest.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.test.update"
 android:versionCode="1"
 android:versionName="1.0" > 

 <uses-sdk
  android:minSdkVersion="8"
  android:targetSdkVersion="8" /> 

 <application
  android:name="com.test.application.AppContext"
  android:icon="@drawable/ic_launcher"
  android:label="@string/app_name" >
  <activity
   android:name="com.test.update.UpdateActivity"
   android:label="@string/app_name" >
   <intent-filter>
    <action android:name="android.intent.action.MAIN" /> 

    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
  </activity>
  <service android:name="com.test.update.UpdateService" >
  </service>
 </application> 

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

</manifest> 

到此编码结束。

源码下载:Android实现APP自动更新功能

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • 基于Retrofit2+RxJava2实现Android App自动更新
  • Android应用APP自动更新功能的代码实现
  • Android如何实现APP自动更新
  • Android程序自动更新功能模块的实现方法【附完整demo源码下载】
  • Android应用自动更新功能实现的方法
  • Android App实现应用内部自动更新的最基本方法示例
  • Android编程实现应用自动更新、下载、安装的方法
  • Android 软件自动更新功能实现的方法
  • android实现通知栏下载更新app示例
  • android实现软件自动更新的步骤
(0)

相关推荐

  • Android如何实现APP自动更新

    先来看看要实现的效果图: 对于安卓用户来说,手机应用市场说满天飞可是一点都不夸张,比如小米,魅族,百度,360,机锋,应用宝等等,当我们想上线一款新版本APP时,先不说渠道打包的麻烦,单纯指上传APP到各大应用市场的工作量就已经很大了,好不容易我们把APP都上传完了,突然发现一个会导致应用闪退的小Bug,这时那个崩溃啊,明明不是很大的改动,难道我们还要再去重新去把各大应用市场的版本再上传更新一次?相信我,运营人员肯定会弄死你的!! 有问题,自然就会有解决问题的方案,因此我们就会想到如果在APP里

  • Android编程实现应用自动更新、下载、安装的方法

    本文实例讲述了Android编程实现应用自动更新.下载.安装的方法.分享给大家供大家参考,具体如下: 我们看到很多Android应用都具有自动更新功能,用户一键就可以完成软件的升级更新.得益于Android系统的软件包管理和安装机制,这一功能实现起来相当简单,下面我们就来实践一下. 1. 准备知识 在AndroidManifest.xml里定义了每个Android apk的版本标识: <manifest xmlns:android="http://schemas.android.com/a

  • Android应用自动更新功能实现的方法

    本文给大家分享Android里应用版本更新功能这一块的实现. 一个好的应用软件都是需要好的维护,从初出版本到最后精品,这个过程需要版本不停的更新,那么如何让用户第一时间获取最新的应用安装包呢?那么就要求我们从第一个版本就要实现升级模块这一功能. 自动更新功能的实现原理,就是我们事先和后台协商好一个接口,我们在应用的主Activity里,去访问这个接口,如果需要更新,后台会返回一些数据(比如,提示语:最新版本的url等).然后我们给出提示框,用户点击开始下载,下载完成开始覆盖安装程序,这样用户的应

  • Android 软件自动更新功能实现的方法

    相信所有的用户都遇到过软件提醒更新的情况,下面就将实现此功能 首先看一下程序目录结构    步骤: 1.新建一个类UpdateManger,用于显示提示更新 复制代码 代码如下: public class UpdateManger { // 应用程序Context private Context mContext; // 提示消息 private String updateMsg = "有最新的软件包,请下载!"; // 下载安装包的网络路径 private String apkUrl

  • 基于Retrofit2+RxJava2实现Android App自动更新

    本文实例为大家分享了Retrofit2 RxJava2实现Android App自动更新,具体内容如下 功能解析 自动更新可以说已经是App的标配了,很多第三方平台也都支持这个功能,最近手头上的项目需要加入这个App自动更新,考虑到项目里有用到Retrofit2和RxJava2,于是打算使用它俩自己实现这个功能. 分析App自动更新,可以分为以下三个功能点: 1.APK文件的下载 2.下载进度的实时更新显示 3.下载完成后的自动安装 其中比较难的一点是下载进度的实时更新显示,更难的是如何优雅的进

  • Android程序自动更新功能模块的实现方法【附完整demo源码下载】

    本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更新模块检测服务器上存放的版本号跟当前程序的版本号如果大于当前版本号,弹出更新对话框,如果用户选择更新,则显示当前更新状态,然后替换当前程序. 程序调用版本更新检测: private UpdateManager updateMan; private ProgressDialog updateProgr

  • Android App实现应用内部自动更新的最基本方法示例

    这只是初步的实现,并没有加入自动编译等功能.需要手动更改更新的xml文件和最新的apk.    共涉及到四个文件! 一.客户端 AndroidUpdateTestActivity:程序首页 main.xml:首页布局 Update:更新类 softupdate_progress:更新等待界面 Updage package majier.test; import java.io.File; import java.io.FileOutputStream; import java.io.IOExce

  • Android应用APP自动更新功能的代码实现

    由于Android项目开源所致,市面上出现了N多安卓软件市场.为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量.因此我们有必要给我们的Android应用增加自动更新的功能. 既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息: <update> <version>2</version> <name>baidu

  • android实现软件自动更新的步骤

    本篇文章是直接下载最新的APK安装的方法,并不是增量下载该APk. 想要实现一个android应用,自动更新下载APK软件的方法,我采取的是以下几步方法: 1.每次进入主界面时,获取服务器的数据,看是否是最新版本,是,则无操作,否,则进行以下步骤: 2.弹出是否更新软件的对话框,点击下载后 3.弹出下载的进度条的对话框,开始下载,可以上随时点击按钮,停止下载 4.下载完成后,调用系统安装软件的服务,安装软件 效果图:     实现过程:   新建一个UpdateManager方法,具体内容我已经

  • android实现通知栏下载更新app示例

    1.设计思路,使用VersionCode定义为版本升级参数.android为我们定义版本提供了2个属性: 复制代码 代码如下: <manifest package="com.cnblogs.tianxia.subway"android:versionCode="1" <!--Integer类型,系统不显示给用户-->android:versionName="1.0"<!--String类型,系统显示用户-->>

随机推荐