繁体   English   中英

如何从android中的另一个应用程序以编程方式安装apk

[英]how to install apk programmatically from another app in android

我想以编程方式安装我的应用程序的新版本。 使用 targetSdkVersion=23 应用程序工作正常,这是我的代码:

public class MainActivity extends AppCompatActivity {
    private int PERMISSION_REQUEST_STORAGE = 0;
    private DownloadController downloadController;

    Button btn_download;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_download = findViewById(R.id.buttonDownload);

        btn_download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                checkStoragePermission();
            }
        });
    }

    public void checkStoragePermission() {
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {

            String url= getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/example.apk";
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(Uri.parse("file://" + url), "application/vnd.android.package-archive");
            String selfPackageName = getApplicationContext().getPackageName();
            ComponentName componentName = intent.resolveActivity(getApplicationContext().getPackageManager());
            String otherPackageName = (componentName != null ? componentName.getPackageName() : "");

            if (MainActivity.this == null || !selfPackageName.equals(otherPackageName)) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
           startActivity(intent);

        } else {
            requestStoragePermission();
        }
    }

    public void requestStoragePermission() {
        ActivityCompat.requestPermissions(
                MainActivity.this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                PERMISSION_REQUEST_STORAGE);
    }
}

但是 targetSdkVersion=29 我听说我必须使用 FileProvider。 我使用了这个结构,但不幸的是它没有打开我的 apk 进行安装。 这是我的 res=>xml=>file_provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external"
        path="." />
    <external-files-path
        name="external_files"
        path="." />
    <files-path
        name="files"
        path="." />
</paths>

我的清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mysms">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".service.OnComplete" >
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.example.myapp"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_provider_paths" />
        </provider>
    </application>

</manifest>

我的主要活动

public class MainActivity extends AppCompatActivity {
    private int PERMISSION_REQUEST_STORAGE = 0;
    private DownloadController downloadController;

    Button btn_download;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_download = findViewById(R.id.buttonDownload);

        btn_download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                checkStoragePermission();
            }
        });
    }

    public void checkStoragePermission() {
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            File file = new File(getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/example.apk");
            Uri uri = FileProvider.getUriForFile(getApplicationContext(), "com.example.myapp", file);
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setData(Uri.fromFile(file));
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            install.setClassName("com.example.myapp", "com.example.myapp.MainActivity");
            install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            ClipData clipData = new ClipData(new ClipDescription("Meshes", new String[]{ClipDescription.MIMETYPE_TEXT_URILIST}), new ClipData.Item(uri));
            install.setClipData(clipData);
            startActivity(install);
        } else {
            requestStoragePermission();
        }
    }

    public void requestStoragePermission() {
        ActivityCompat.requestPermissions(
                MainActivity.this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                PERMISSION_REQUEST_STORAGE);
    }
}

我收到这个错误

2019-12-17 00:46:38.035 32020-32020/com.example.myapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.mysms, PID: 32020
    android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.example.myapp/files/Download/example.apk exposed beyond app through Intent.getData()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
        at android.net.Uri.checkFileUriExposed(Uri.java:2346)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:8933)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:8894)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517)
        at android.app.Activity.startActivityForResult(Activity.java:4224)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:767)
        at android.app.Activity.startActivityForResult(Activity.java:4183)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:754)
        at android.app.Activity.startActivity(Activity.java:4507)
        at android.app.Activity.startActivity(Activity.java:4475)
        at com.example.mysms.MainActivity.checkStoragePermission(MainActivity.java:107)
        at com.example.mysms.MainActivity$3.onClick(MainActivity.java:76)
        at android.view.View.performClick(View.java:5610)
        at android.view.View$PerformClick.run(View.java:22265)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

似乎问题在于您为意图数据设置了错误的 uri:

install.setData(Uri.fromFile(file));

您需要设置使用 FileProvider 创建的 uri:

Uri uri = FileProvider.getUriForFile(getApplicationContext(), "com.example.myapp", file);
install.setData(uri);

在您找到的指令中也是如此:

val contentUri = FileProvider.getUriForFile(
    context,
    BuildConfig.APPLICATION_ID + PROVIDER_PATH,
    File(destination)
)
val install = Intent(Intent.ACTION_VIEW)
install.data = contentUri

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM