/**
* http://blog.csdn.net/rodulf/article/details/51706788
*
* 修改后兼容7.0
*/
public class UpdateService extends Service {
// 文件保存路径(如果有SD卡就保存SD卡,如果没有SD卡就保存到手机包名下的路径)
private String APK_dir = "";
private String apkName;
// 文件下载路径
private String APK_url = "";
public UpdateService() {
}
/** 安卓系统下载类 **/
DownloadManager manager;
/** 接收下载完的广播 **/
DownloadCompleteReceiver receiver;
/** 初始化下载器 **/
private void initDownManager() {
manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
receiver = new DownloadCompleteReceiver();
//设置下载地址
// String urlPath = "http://47.93.61.22/wordpress/app-release.apk";
Uri parse = Uri.parse(APK_url);
DownloadManager.Request down = new DownloadManager.Request(parse);
// 百度音乐 Uri.parse("http://gdown.baidu.com/data/wisegame/fd84b7f6746f0b18/baiduyinyue_4802.apk"));
// 乐视体育
//Uri.parse("http://122.228.237.132/apk.r1.market.hiapk.com/data/upload/apkres/2016/6_12/16/com.lesports.glivesports_040405.apk"));
// 设置允许使用的网络类型,这里是移动网络和wifi都可以
down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
// 下载时,通知栏显示途中
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
}
// 显示下载界面
down.setVisibleInDownloadsUi(true);
apkName = parse.getLastPathSegment();
// 设置下载后文件存放的位置
initAPKDir();
down.setDestinationInExternalFilesDir(this, APK_dir, apkName);
// 将下载请求放入队列
manager.enqueue(down);
//注册下载广播
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent!=null){
APK_url = intent.getStringExtra("apk_url");
// 调用下载
initDownManager();
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
// 注销下载广播
if (receiver != null)
unregisterReceiver(receiver);
super.onDestroy();
}
// 接受下载完成后的intent
class DownloadCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//判断是否下载完成的广播
if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
//获取下载的文件id
long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
Log.d("kodulf","id="+downId);
//自动安装apk
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
Uri uriForDownloadedFile = manager.getUriForDownloadedFile(downId);
Log.d("kodulf","uri="+uriForDownloadedFile);
installApkNew(uriForDownloadedFile);
}
//停止服务并关闭广播
UpdateService.this.stopSelf();
}
}
//安装apk
protected void installApkNew(Uri uri) {
Intent intent = new Intent();
//执行动作
intent.setAction(Intent.ACTION_VIEW);
//执行的数据类型
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// intent.setDataAndType(uri, "application/vnd.android.package-archive");
//不加下面这句话是可以的,查考的里面说如果不加上这句的话在apk安装完成之后点击单开会崩溃
// android.os.Process.killProcess(android.os.Process.myPid());
String path = getRealFilePath(getApplication(),uri);
File apkFile = new File(path);
//Android 7.0 系统共享文件需要通过 FileProvider 添加临时权限,否则系统会抛出 FileUriExposedException .
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(getApplication(),"com.vipcarehealthservice.e_lap.provider",apkFile);
intent.setDataAndType(contentUri,"application/vnd.android.package-archive");
}else {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType( Uri.fromFile(apkFile),"application/vnd.android.package-archive");
}
try {
startActivity(intent);
}catch (Exception e){
e.printStackTrace();
}
}
}
private void initAPKDir() {
/**
* 创建路径的时候一定要用[/],不能使用[],但是创建文件夹加文件的时候可以使用[].
* [/]符号是Linux系统路径分隔符,而[]是windows系统路径分隔符 Android内核是Linux.
*/
String APK_dir_old = "";
if (isHasSdcard())// 判断是否插入SD卡
APK_dir_old = getApplicationContext().getFilesDir().getAbsolutePath() + "/apk/download/";// 保存到app的包名路径下
else
APK_dir_old = Environment.getExternalStorageDirectory().getAbsolutePath() + ClapConstant.DOWNLOAD_APK ;//"/apk/download/";// 保存到SD卡路径下
File outputfile = new File(APK_dir_old);
Uri apkuri ;
if (Build.VERSION.SDK_INT >= 24){
apkuri = FileProvider.getUriForFile(this, "com.vipcarehealthservice.e_lap.provider", //可以是任意字符串
outputfile);
}else{
apkuri = Uri.fromFile(outputfile);
}
APK_dir = getRealFilePath(this,apkuri);
File destDir = new File(APK_dir,apkName);
if (!destDir.exists()) {// 判断文件夹是否存在
destDir.mkdirs();
}
}
/**
*
* @Description:判断是否插入SD卡
*/
private boolean isHasSdcard() {
String status = Environment.getExternalStorageDirectory().getAbsolutePath();
if (status.equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
/**
* Try to return the absolute file path from the given Uri
*
* @param context
* @param uri
* @return the file path or null
*/
public static String getRealFilePath( final Context context, final Uri uri ) {
if ( null == uri ) return null;
final String scheme = uri.getScheme();
String data = null;
if ( scheme == null )
data = uri.getPath();
else if ( ContentResolver.SCHEME_FILE.equals( scheme ) ) {
data = uri.getPath();
} else if ( ContentResolver.SCHEME_CONTENT.equals( scheme ) ) {
Cursor cursor = context.getContentResolver().query( uri, new String[] { MediaStore.Images.ImageColumns.DATA }, null, null, null );
if ( null != cursor ) {
if ( cursor.moveToFirst() ) {
int index = cursor.getColumnIndex( MediaStore.Images.ImageColumns.DATA );
if ( index > -1 ) {
data = cursor.getString( index );
}
}
cursor.close();
}
}
return data;
}
}
mxl创建文件 file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path path="" name="camera_photos" />
<external-cache-path path="app/" name="apk"/>
</paths>
</resources>
AndroidManifest.xml 里面配置
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<!--提供共享路径-->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
关于7.0路劲问题参考
https://blog.csdn.net/c__chao/article/details/65437099