前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android应用安装、卸载、状态、打开及Android7以上文件权限设置

Android应用安装、卸载、状态、打开及Android7以上文件权限设置

作者头像
码客说
发布2024-04-03 08:50:30
900
发布2024-04-03 08:50:30
举报
文章被收录于专栏:码客码客

应用安装

代码语言:javascript
复制
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;

import androidx.annotation.RequiresApi;
import androidx.core.content.FileProvider;

import java.io.File;

public class AppInstallUtils {
    private Activity mAct;
    private String mPath;//下载下来后文件的路径
    public static int UNKNOWN_CODE = 2018;

    public AppInstallUtils(Activity mAct, String mPath) {
        this.mAct = mAct;
        this.mPath = mPath;
    }

    public void install() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) startInstallO();
        else startInstallN();
    }

    /**
     * android1.x-6.x
     */
    private void startInstall() {
        Intent install = new Intent(Intent.ACTION_VIEW);
        install.setDataAndType(Uri.parse("file://" + mPath), "application/vnd.android.package-archive");
        install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mAct.startActivity(install);
    }

    /**
     * android7.x
     */
    private void startInstallN() {
        //参数1 上下文, 参数2 在AndroidManifest中的android:authorities值, 参数3  共享的文件
        Uri apkUri = FileProvider.getUriForFile(mAct, mAct.getApplicationContext().getPackageName() + ".fileprovider", new File(mPath));
        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");
        mAct.startActivity(install);
    }

    /**
     * android8.x
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startInstallO() {
        boolean isGranted = mAct.getPackageManager().canRequestPackageInstalls();
        if (isGranted) startInstallN();//安装应用的逻辑(写自己的就可以)
        else new AlertDialog.Builder(mAct)
                .setCancelable(false)
                .setTitle("安装应用需要打开未知来源权限,请去设置中开启权限")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface d, int w) {
                        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                        mAct.startActivityForResult(intent, UNKNOWN_CODE);
                    }
                })
                .show();
    }
}

打开APP

代码语言:javascript
复制
public static void openApp(Activity activity,String packageName){
    Intent launchIntent = activity.getPackageManager().getLaunchIntentForPackage(packageName);
    if (launchIntent != null) {
        activity.startActivity(launchIntent);
    } else {
        // 应用未安装或包名无效
        Toast.makeText(activity, "应用未安装或包名无效", Toast.LENGTH_SHORT).show();
    }
}

FileProvider

Android7及以上对文件权限的管控抓的很严格。

需要在AndroidManifest.xml里面对它进行声明一个ContentProvider

定义FileProvider

由于FileProvider提供了ContentURI的生成方法,所以我们无需在代码中定义写一个它的子类

name属性是固定的。

authorities可以自己定义,一般是包名字加上.fileprovider

exported设置为false,因为通常是拒绝外部直接访问的。

grantUriPermissions需要为true,需要授予临时的Uri权限。

代码语言:javascript
复制
<manifest>
    <application>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="cn.psvmc.myapp.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
             <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_path" />
        </provider>
    </application>
</manifest>

假如我们APP的包名是cn.psvmc.myapp,其中的android:authorities就在包名的基础上添加.fileprovider

代码语言:javascript
复制
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="cn.psvmc.myapp.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_path" />
</provider>

file_path.xml需要建立在res目录下名为xml的目录下,xml目录需要自己建立。

paths下可以包含一个或者多个子节点。

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path
        name="files"
        path="images/" />
    <cache-path
        name="cache"
        path="." />
    <external-path
        name="external"
        path="." />
    <external-files-path
        name="external-files"
        path="." />
    <external-cache-path
        name="external-cache"
        path="." />
    <external-media-path
        name="external-media"
        path="." />
</paths>

这个xml的作用在于为文件生成URI,

其中root-pathfiles-pathcache-path这些标签代表父路径:

  • root-path : File("/")
  • files-path : Context.getFilesDir()
  • cache-path : context.getCacheDir()
  • external-path : Environment.getExternalStorageDirectory()
  • external-files-path : ContextCompat.getExternalFilesDirs(context, null)[0]
  • external-cache-path : ContextCompat.getExternalCacheDirs(context)[0]
  • external-media-path : context.getExternalMediaDirs()[0]

path属性代表子路径,name代表为”父路径/子路径”起的名字,

代码语言:javascript
复制
<files-path name="files" path="images/" />

路径对应关系

创建file_paths.xml文件

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--定义APP的存放目录-->
    <external-path
        name="AppInstaller"
        path="/Download"></external-path>
</paths>

我们还可以在path中用.代替所有目录。

代码语言:javascript
复制
//文件路径
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getCanonicalPath() + "/apps/MyApp.apk");
//获取文件对应的content类型Uri
Uri uri = FileProvider.getUriForFile(this, "cn.psvmc.myapp.fileprovider", file);

观察我们生成的Uri示例,上边是我们普通的fileUri下边是我们生成的ContentUri,区别就在于ContentUri没有暴露具体的文件路径。

fileUri地址构成

file://+文件的全路径

ContentUri地址构成

content://+android:authorities的值/paths中匹配的名称/应用名称

例如:

代码语言:javascript
复制
//普通的fileUri(通过Uri.fromFile(file)获取)
file:///storage/emulated/0/Download/apps/MyApp.apk
//contentUri
content://cn.psvmc.myapp.fileprovider/AppInstaller/apps/MyApp.apk

APP的安装

代码语言:javascript
复制
//文件路径
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getCanonicalPath() + "/MyApp.apk");
Intent intent = new Intent(Intent.ACTION_VIEW);
//获取文件对应的content类型Uri
Uri uri = FileProvider.getUriForFile(this, "cn.psvmc.myapp.fileprovider", file);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//可以不加
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 应用安装
  • 打开APP
  • FileProvider
    • 定义FileProvider
      • 路径对应关系
        • APP的安装
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档