转自:Android apk更新,下载,安装
更新的思想一般都是从服务器获取到版本号,再和当前使用的app的版本号进行比较,如果不同,就进行提示更新;
activity中:
public class UpdateAppActivity extends BaseActivity {
private String url="http://192.168.56.1:8080/apk/AppName.apk";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_update_app);
alertUpdate();
}
public void alertUpdate() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("软件升级").setMessage("发现新版本,建议立即更新使用.")
.setPositiveButton("更新", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
File file = new File(UpdateAppService.save_url + "/AppName.apk");
if (file.exists()) {
Uri uri = Uri.fromFile(file);
Intent intent2 = new Intent(Intent.ACTION_VIEW);
intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent2.setDataAndType(uri, "application/vnd.android.package-archive");
UpdateAppActivity.this.startActivity(intent2);
} else {
Intent intent = new Intent(UpdateAppActivity.this,
UpdateAppService.class);
intent.putExtra("Key_App_Name", "AppName");
intent.putExtra("Key_Down_Url", url);
startService(intent);
}
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.create().show();
}
}
在这里我们是用的是底层服务来进行下载,
service:
public class UpdateAppService extends Service{
private String app_name;// 文件名
private String down_url;// 下载文件地址
public static String save_url = Environment.getExternalStorageDirectory() + "/Louyx";
private static final int TIMEOUT = 10 * 1000;// 超时
private static final int DOWN_OK = 1;
private static final int DOWN_ERROR = 0;
// 通知
private NotificationManager notificationManager;
private Notification notification;
private RemoteViews contentView;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
app_name = intent.getStringExtra("Key_App_Name");
down_url = intent.getStringExtra("Key_Down_Url");
if (FileUtils.createFile(save_url, app_name)) {
createNotification();
// 线程开启
new DownLoadThread().start();
}
else {
stopSelf();
}
return super.onStartCommand(intent, flags, startId);
}
public void createNotification() {
notification = new Notification(R.mipmap.ic_launcher, app_name + "正在下载",
System.currentTimeMillis());
notification.flags = Notification.FLAG_ONGOING_EVENT;
// 自定义 Notification 的显示
contentView = new RemoteViews(getPackageName(),R.layout.test_notification_item);
contentView.setTextViewText(R.id.notificationTitle, app_name + "正在下载");
contentView.setTextViewText(R.id.notificationPercent, "0%");
contentView.setProgressBar(R.id.notificationProgress, 100, 0, false);
notification.contentView = contentView;
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(R.layout.test_notification_item, notification);
}
private class DownLoadThread extends Thread
{
@Override
public void run() {
Message message = new Message();
try {
long downloadSize = downloadUpdateFile(down_url, FileUtils.updateFile.toString());
if (downloadSize > 0) {
message.what = DOWN_OK;
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
message.what = DOWN_ERROR;
handler.sendMessage(message);
}
}
}
public long downloadUpdateFile(String down_url, String file) throws Exception {
int totalSize; // 文件总大小
int downloadCount = 0; // 已经下载好的大小
int updateCount = 0; // 已经上传的文件大小
int downCount = 1;// 已下载好的百分比
InputStream inputStream=null;
OutputStream outputStream=null;
URL url = new URL(down_url);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
url.openConnection();
httpURLConnection.setConnectTimeout(TIMEOUT);
httpURLConnection.setReadTimeout(TIMEOUT);
// 获取下载文件的总管大小size
totalSize = httpURLConnection.getContentLength();
if (httpURLConnection.getResponseCode() == 404) {
// 这个地方应该加一个下载失败的处理,但是,因为我们在外面加了一个try---catch,已经处理了Exception,所以不用处理
throw new Exception("fail!");
}
if(httpURLConnection.getResponseCode()==200){
inputStream = httpURLConnection.getInputStream();
outputStream = new FileOutputStream(file, false);// 文件存在则覆盖掉
byte buffer[] = new byte[1024];
int readsize = 0;
while ((readsize = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, readsize);
downloadCount += readsize;
int num = downloadCount * 100 / totalSize;
if (num > downCount || totalSize == downloadCount) {
downCount = downloadCount * 100 / totalSize;
// 改变通知栏
contentView.setTextViewText(R.id.notificationPercent, downCount + "%");
contentView.setProgressBar(R.id.notificationProgress, 100, downCount, false);
notification.contentView = contentView;
notificationManager.notify(R.layout.test_notification_item, notification);
}
}
}
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
inputStream.close();
outputStream.close();
return downloadCount;
}
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWN_OK:
// 改变通知栏
contentView.setTextViewText(R.id.notificationTitle, app_name + "下载完成");
notification.contentView = contentView;
notificationManager.notify(R.layout.test_notification_item, notification);
//安装
Uri uri = Uri.fromFile(FileUtils.updateFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
UpdateAppService.this.startActivity(intent);
stopSelf();
break;
case DOWN_ERROR:
// 改变通知栏
FileUtils.delFile(save_url + "/" + app_name + ".apk");
contentView.setTextViewText(R.id.notificationTitle, app_name + "下载失败");
notification.contentView = contentView;
notificationManager.notify(R.layout.test_notification_item, notification);
stopSelf();
break;
default:
break;
}
}
};
}
一个简单地文件操作类:
FileUtils:
public class FileUtils {
public static File updateDir;
public static File updateFile;
public static boolean createFile(String url, String name) {
// 判断SD卡可读可写
if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment
.getExternalStorageState())) {
updateDir = new File(url + "/");
updateFile = new File(url + "/" + name + ".apk");
if (!updateDir.exists()) {
updateDir.mkdirs();
}
if (!updateFile.exists()) {
try {
updateFile.createNewFile();
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
return true;
}
return false;
}
public static void delFile(String path) {
File file = new File(path);
if (file.exists()) {
file.delete();
}
}
}
下载过程中的自定义通知栏布局文件:
test_notification_item
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/notificationImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/stat_sys_download"
android:paddingLeft="16dp"/>
<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="26dp"
android:textColor="#FFFFFFFF" />
<!-- 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="#FFFFFFFF"
android:paddingLeft="16dp"/>
<ProgressBar
android:id="@+id/notificationProgress"
style="?android:attr/progressBarStyleHorizontal"
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="26dp"
android:paddingRight="3dp"
android:paddingTop="2dp" />
</RelativeLayout>