清单中需要有的权限
文件的上传 下载
private String apkUrl = "http://cdn.banmi.com/banmiapp/apk/banmi_330.apk";
/**
* http下载安装-单线程
*/
private Button mBtn1;
private File savaFile;
private ProgressBar mPb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
EventBus.getDefault().register(this);
checkPremisstion();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void changemPb(MsgE msgE){
long allPro = mPb.getProgress() + msgE.getProgress();//把新的进度追加到旧的进度上,算出当前最新的进度
mPb.setMax((int)msgE.getMax());
mPb.setProgress((int)allPro);
//如果进度和最大进度一致,表示下载完成,安装apk
if(allPro == msgE.getMax()){
ApkInstallUtil.installApk(MainActivity.this,savaFile.getPath());
}
}
private void checkPremisstion() {
//检查 sdcard读权限
int i = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (i != PackageManager.PERMISSION_GRANTED) {//没有权限,申请权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
}
int j = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
if (j != PackageManager.PERMISSION_GRANTED) {//没有权限,申请权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
}
}
private void initView() {
mBtn1 = (Button) findViewById(R.id.btn1);
mBtn1.setOnClickListener(this);
mPb = (ProgressBar) findViewById(R.id.pb);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.btn1:
// new Thread() {
// @Override
// public void run() {
// super.run();
// httpDownload();
// }
// }.start();
//调用多线程下载
try {
savaFile = new File("/storage/emulated/0/c.apk");
savaFile.createNewFile();
DownLoadMoreThread.httpDownLoadByMoreThreads(apkUrl,"/storage/emulated/0/c.apk",this);
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
private void httpDownload() {
savaFile = new File("/storage/emulated/0/c.apk");
try {
savaFile.createNewFile();
URL url = new URL(apkUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() == 200) {
InputStream inputStream = conn.getInputStream();
int max = conn.getContentLength();
savaFile(savaFile, inputStream, max);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//保存文件
private void savaFile(final File savaFile, InputStream is, long max) {
int len = 0;
byte[] buff = new byte[4096];//每次读取1k
int count = 0;//记录当前读取的进度
FileOutputStream fos = null;
try {
fos = new FileOutputStream(savaFile);
while ((len = is.read(buff)) != -1) {
fos.write(buff, 0, len);//把读取的数据,写入本地文件中,作为保存
count = count + len;//累加读取的数据
//发送进度给主线程,接收改变进度条 eventbus
EventBus.getDefault().post(new MsgE(count, max));
Log.i("111", "savaFile: max->" + max + ",count->" + count);
}
// mBtn1.setText("下载完成");
runOnUiThread(new Runnable() { //当前是次线程,次方法能切换到主线程中,执行吐司
@Override
public void run() {
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
//调用安装的代码
ApkInstallUtil.installApk(MainActivity.this,savaFile.getPath());
}
});
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//读取写入完数据后,关闭流
if (is != null)
is.close();
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//对于未知来源的apk进行安装时,需要对私有文件进行授权,授权后的回调,进行安装未知的apk
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ApkInstallUtil.UNKNOWN_CODE) {
ApkInstallUtil.installApk(this,"/storage/emulated/0/c.apk");//再次执行安装流程,包含权限判等
}
}
ApkInstallUtil (调用安装代码)
public class ApkInstallUtil {
public static final int UNKNOWN_CODE = 2019;
//调用安装的方法,进行判断是哪种sdk的版本,进行对应的安装
public static void installApk(Context context, String path) {
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){ //8.0 26以上
startInstallO(context,path);
}else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){//7.0 24到26之间
startInstallN(context,path);
}else { //7.0之下 6.x 5.x。。。
startInstall(context,path);
}
}
/**
*android1.x-6.x
*@param path 文件的路径
*/
public static void startInstall(Context context, String path) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.parse("file://" + path), "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
/**
* android7.x
* @param path 文件路径
*/
@RequiresApi(api = Build.VERSION_CODES.N)
public static void startInstallN(Context context, String path) {
//参数1 上下文, 参数2 在AndroidManifest中的android:authorities值, 参数3 共享的文件
Uri apkUri = FileProvider.getUriForFile(context, "aaaaaa", new File(path));
Intent install = new Intent(Intent.ACTION_VIEW);
//由于没有在Activity环境下启动Activity,设置下面的标签
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
context.startActivity(install);
}
/**
* android8.x
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private static void startInstallO(final Context context, String path) {
//获取是否允许私有的文件夹可以访问
boolean isGranted = context.getPackageManager().canRequestPackageInstalls();
if (isGranted) //允许过了,直接装
startInstallN(context,path);//安装应用的逻辑(写自己的就可以)
else new AlertDialog.Builder(context) //没有允许过,请求允许,授权
.setCancelable(false)
.setTitle("安装应用需要打开未知来源权限,请去设置中开启权限")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d, int w) {
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
Activity act = (Activity) context;
act.startActivityForResult(intent, UNKNOWN_CODE);
}
})
.show();
}
}