欢迎来到安信科(kē)技官方网站!【www.anxin66.com】
18112005550
工作时间: 8:30-21:30
新(xīn)闻中心
News Center

Android开发中使用(yòng)FileProvider解决apk升级包无法安装的问题

资讯分(fēn)类: 移动微信  浏览: 2023年11月29日

Android使用(yòng)FileProvider解决apk无法安装的问题

安卓开发APP,需要提供APP升级包安装时,提示出现下面的问题:

W/System.err: android.os.FileUriExposedException: file:///xxxx/xxxx/xxxx/updata.apk exposed beyond app through Intent.getData()

上面的错误代码中:updata.apk為(wèi)升级包。
通用(yòng)使用(yòng)下面的方法解决处理(lǐ):

1.配置mainfest信息,在mainfest的application结点内添加如下代码:
<>
android:name="androidx.core.content.FileProvider"
android:authorities="com.anxin.myapp.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
tools:ignore="WrongManifestParent">
<>
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />


上面的代码中:
android:authorities 这里使用(yòng)的是包名。这个其实可(kě)以随便写,换成自己的包名就都可(kě)以。
android:resource 这里配置一个 xml文(wén)件。命名為(wèi):filepaths.

2.在xml下创建filepaths.xml文(wén)件如下:
<paths>
    <external-path name="." path="."/>
</paths>


以下代码说明:
external-path 是放到sd卡的目录下 Environment.getExternalStorageDirectory()
path="." 代表共享 sd卡下的所有(yǒu)目录。会遍历sd卡下的所有(yǒu)目录,来匹配你要安装 的apk 的目录。。
name="." 代表apk存放目录下所有(yǒu)apk的名字都会遍历一遍,然后跟你要安装的apk进行匹配

3.以下是判断遠(yuǎn)程升级包版本号,并下载、安装升级包APP的代码:

public class Updateapk extends BaseData {
Context context;
private RadioGroup mRg;
ImageView iv_back;
String url="http://遠(yuǎn)程服務(wù)器/getjson/getnewversion";
TextView tv_versionName,tv_versioninfo;
Button btn_backusercenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.updateapk);
initRadioGroup();
findViewById();
loadData(url);
}
private void findViewById() {
iv_back=findViewById(R.id.iv_back);
iv_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
btn_backusercenter=findViewById(R.id.btn_backusercenter);
btn_backusercenter.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
public void onSuccess(String result) {
try {
parseShowData(result);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}

private void parseShowData(String result) throws PackageManager.NameNotFoundException {
BeanUpdate bean=new Gson().fromJson(result,BeanUpdate.class);
Integer serviceVersionCode= bean.getServiceversionCode();
String serviceversionName=bean.getServiceversionName();
String serviceversionInfo=bean.getServiceversionInfo();
tv_versionName=findViewById(R.id.tv_versionName);
tv_versionName.setText("新(xīn)版本待升级,新(xīn)版本号:"+serviceversionName);
tv_versioninfo=findViewById(R.id.tv_versioninfo);
tv_versioninfo.setText(serviceversionInfo);
if (getVersionCode() < serviceVersionCode) {
showDialogUpdate();

}else{
Toast.makeText(this,"当前已经是最新(xīn)的版本", Toast.LENGTH_SHORT).show();
}
}
private void showDialogUpdate() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("版本升级").
setIcon(R.mipmap.ic_launcher).
setMessage("发现新(xīn)版本!请及时更新(xīn)").
setPositiveButton("确定", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
loadNewVersionProgress();//下载最新(xīn)的版本程序
}
}).
setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent=new Intent();
intent.setClass(Updateapk.this, UserCenter.class);
startActivity(intent);
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
/**
* 下载新(xīn)版本程序,需要子線(xiàn)程
*/
private void loadNewVersionProgress() {
final String uri="http://xxxx.xxxx.com/updata.apk";
final ProgressDialog pd;//进度条对话框
pd = new  ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("正在下载更新(xīn)");
pd.show();
//启动子線(xiàn)程下载任務(wù)
new Thread(){
@Override
public void run() {
try {
File file = getFileFromServer(uri, pd);
sleep(3000);
installApk(file);
pd.dismiss();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "下载新(xīn)版本失败", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}}.start();
}
/**
* 从服務(wù)器获取apk文(wén)件的代码
* 传入网址uri,进度条对象即可(kě)获得一个File文(wén)件(要在子線(xiàn)程中执行哦)
*/
public static File getFileFromServer(String uri, ProgressDialog pd) throws Exception{
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
URL url = new URL(uri);
HttpURLConnection conn =  (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
pd.setMax(conn.getContentLength());
InputStream is = conn.getInputStream();
long time= System.currentTimeMillis();
File file = new File(Environment.getExternalStorageDirectory()+"/Download/", time+"updata.apk");
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len ;
int total=0;
while((len =bis.read(buffer))!=-1){
fos.write(buffer, 0, len);
total+= len;
pd.setProgress(total);
}
fos.close();
bis.close();
is.close();
return file;
}
else{
return null;
}
}

/**
* 安装apk
*
* @param file
*/
private void installApk(File file) {
//File file = new File(fileSavePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri data;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//判断版本大于等于7.0
// "com.anxin.loveenglish.fileprovider"即是在清单文(wén)件中配置的authorities
// 通过FileProvider创建一个content类型的Uri
data = FileProvider.getUriForFile(this, "com.anxin.loveenglish.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 给目标应用(yòng)一个临时授权
} else {
data = Uri.fromFile(file);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
startActivity(intent);
}

@Override
public void onError(Throwable ex, boolean isOnCallback) {
Toast toast =Toast.makeText(this, "当前為(wèi)最新(xīn)版本,不需要升级!", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
Intent intent=new Intent();
intent.setClass(Updateapk.this, UserCenter.class);
startActivity(intent);
}

/*获取当前程序的版本号*/

private int getVersionCode() throws PackageManager.NameNotFoundException {
//获取packagemanager的实例
PackageManager packageManager = getPackageManager();
//getPackageName()是你当前类的包名,0代表是获取版本信息
PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0);
return packInfo.versionCode;
}
}


最后说明下,http://遠(yuǎn)程服務(wù)器/getjson/getnewversion

这里获取的是遠(yuǎn)程服務(wù)器中设置的APP新(xīn)版本信息,以tp6.0為(wèi)例:

class Getjson extends Base{
public function getnewversion(){
$data['serviceversionName']='1.2.0';
$data['serviceversionCode']=2;
$data['serviceversionInfo']='最新(xīn)版本说明文(wén)字';
return json($data);
}

上面的代码:serviceversionCode使用(yòng)自然数,不要使用(yòng)带小(xiǎo)数点。

Copyright © 2007-2022 安信科(kē)技(十五周年纪念版) All Rights Reserved  备案号: 
网站首页 |  新(xīn)闻资讯 |  服務(wù)项目 |  软件产品 |  试用(yòng)下载 |  需求提交 |  模版建站 |  关于安信 |  产品授权 |  联系我们 |  定制开发 | 
服務(wù)热線(xiàn):181-1200-5550  客服QQ: 120094883  | 邮箱:120094883#qq.com(#改@)