安信科技官網-觸屏版
  • <menu id="smwsk"><strong id="smwsk"></strong></menu>
    <menu id="smwsk"><strong id="smwsk"></strong></menu>
  • <menu id="smwsk"><tt id="smwsk"></tt></menu>
  • 當前位置:首頁 > 安信自媒體 > 移動微信

    Android開發中使用FileProvider解決apk升級包無法安裝的問題

    時間:2023年11月29日 瀏覽:

    Android使用FileProvider解決apk無法安裝的問題

    安卓開發APP,需要提供APP升級包安裝時,提示出現下面的問題:

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

    上面的錯誤代碼中:updata.apk為升級包。
    通用使用下面的方法解決處理:

    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 這里使用的是包名。這個其實可以隨便寫,換成自己的包名就都可以。
    android:resource 這里配置一個 xml文件。命名為:filepaths.

    2.在xml下創建filepaths.xml文件如下:
    <paths>
        <external-path name="." path="."/>
    </paths>


    以下代碼說明:
    external-path 是放到sd卡的目錄下 Environment.getExternalStorageDirectory()
    path="." 代表共享 sd卡下的所有目錄。會遍歷sd卡下的所有目錄,來匹配你要安裝 的apk 的目錄。。
    name="." 代表apk存放目錄下所有apk的名字都會遍歷一遍,然后跟你要安裝的apk進行匹配

    3.以下是判斷遠程升級包版本號,并下載、安裝升級包APP的代碼:

    public class Updateapk extends BaseData {
    Context context;
    private RadioGroup mRg;
    ImageView iv_back;
    String url="http://遠程服務器/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("新版本待升級,新版本號:"+serviceversionName);
    tv_versioninfo=findViewById(R.id.tv_versioninfo);
    tv_versioninfo.setText(serviceversionInfo);
    if (getVersionCode() < serviceVersionCode) {
    showDialogUpdate();

    }else{
    Toast.makeText(this,"當前已經是最新的版本", Toast.LENGTH_SHORT).show();
    }
    }
    private void showDialogUpdate() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("版本升級").
    setIcon(R.mipmap.ic_launcher).
    setMessage("發現新版本!請及時更新").
    setPositiveButton("確定", new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {
    loadNewVersionProgress();//下載最新的版本程序
    }
    }).
    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();
    }
    /**
    * 下載新版本程序,需要子線程
    */
    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("正在下載更新");
    pd.show();
    //啟動子線程下載任務
    new Thread(){
    @Override
    public void run() {
    try {
    File file = getFileFromServer(uri, pd);
    sleep(3000);
    installApk(file);
    pd.dismiss();
    } catch (Exception e) {
    Toast.makeText(getApplicationContext(), "下載新版本失敗", Toast.LENGTH_LONG).show();
    e.printStackTrace();
    }
    }}.start();
    }
    /**
    * 從服務器獲取apk文件的代碼
    * 傳入網址uri,進度條對象即可獲得一個File文件(要在子線程中執行哦)
    */
    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"即是在清單文件中配置的authorities
    // 通過FileProvider創建一個content類型的Uri
    data = FileProvider.getUriForFile(this, "com.anxin.loveenglish.fileprovider", file);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 給目標應用一個臨時授權
    } 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, "當前為最新版本,不需要升級!", 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://遠程服務器/getjson/getnewversion

    這里獲取的是遠程服務器中設置的APP新版本信息,以tp6.0為例:

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

    上面的代碼:serviceversionCode使用自然數,不要使用帶小數點。


    當前頁面電腦端訪問網址:


    發送給朋友 分享到朋友圈

    手機版電腦版

    欧美黑白配性xxxxx