簡體   English   中英

如何在我的應用程序中共享 apk 文件(發送應用程序本身)

[英]How can i share apk file in my app (send app itself)

我正在嘗試使用此代碼將我的應用程序 apk 文件發送到另一台設備:

public static void sendAppItself(Activity paramActivity) throws IOException {
    PackageManager pm = paramActivity.getPackageManager();
    ApplicationInfo appInfo;
    try {
        appInfo = pm.getApplicationInfo(paramActivity.getPackageName(),
                PackageManager.GET_META_DATA);
        Intent sendBt = new Intent(Intent.ACTION_SEND);
        sendBt.setType("*/*");
        sendBt.putExtra(Intent.EXTRA_STREAM,
                Uri.parse("file://" + appInfo.publicSourceDir));

        paramActivity.startActivity(Intent.createChooser(sendBt,
                "Share it using"));
    } catch (PackageManager.NameNotFoundException e1) {
        e1.printStackTrace();
    }
}

這段代碼工作得很好。

但是與此代碼共享的apk文件的名稱是base.apk

我怎樣才能改變它?

將文件從源目錄復制到新目錄。 復制和共享復制的文件時重命名文件。 共享完成后刪除臨時文件。

 private void shareApplication() {
    ApplicationInfo app = getApplicationContext().getApplicationInfo();
    String filePath = app.sourceDir;

    Intent intent = new Intent(Intent.ACTION_SEND);

    // MIME of .apk is "application/vnd.android.package-archive".
    // but Bluetooth does not accept this. Let's use "*/*" instead.
    intent.setType("*/*");

    // Append file and send Intent
    File originalApk = new File(filePath);

    try {
        //Make new directory in new location
        File tempFile = new File(getExternalCacheDir() + "/ExtractedApk");
        //If directory doesn't exists create new
        if (!tempFile.isDirectory())
            if (!tempFile.mkdirs())
                return;
        //Get application's name and convert to lowercase
        tempFile = new File(tempFile.getPath() + "/" + getString(app.labelRes).replace(" ","").toLowerCase() + ".apk");
        //If file doesn't exists create new
        if (!tempFile.exists()) {
            if (!tempFile.createNewFile()) {
                return;
            }
        }
        //Copy file to new location
        InputStream in = new FileInputStream(originalApk);
        OutputStream out = new FileOutputStream(tempFile);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
        System.out.println("File copied.");
        //Open share dialog
        intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
        startActivity(Intent.createChooser(intent, "Share app via"));

    } catch (IOException e) {
        e.printStackTrace();
    }
}

更新:此方法不再起作用,並且如果您實現它會拋出異常。 從 android N 開始,如果我們想訪問內存中的文件(如 apk 文件),我們應該使用內容提供程序。 如需更多信息,請訪問本指南 盡管復制、重命名和共享復制版本的整個想法仍然有效。

您可以使用此功能,在 api 22 和 27 上進行測試

    private void shareApplication() {
        ApplicationInfo app = getApplicationContext().getApplicationInfo();
        String filePath = app.sourceDir;

        Intent intent = new Intent(Intent.ACTION_SEND);

        // MIME of .apk is "application/vnd.android.package-archive".
        // but Bluetooth does not accept this. Let's use "*/*" instead.
        intent.setType("*/*");

        // Append file and send Intent
        File originalApk = new File(filePath);

        try {
            //Make new directory in new location=
            File tempFile = new File(getExternalCacheDir() + "/ExtractedApk");
            //If directory doesn't exists create new
            if (!tempFile.isDirectory())
                if (!tempFile.mkdirs())
                    return;
            //Get application's name and convert to lowercase
            tempFile = new File(tempFile.getPath() + "/" + getString(app.labelRes).replace(" ","").toLowerCase() + ".apk");
            //If file doesn't exists create new
            if (!tempFile.exists()) {
                if (!tempFile.createNewFile()) {
                    return;
                }
            }
            //Copy file to new location
            InputStream in = new FileInputStream(originalApk);
            OutputStream out = new FileOutputStream(tempFile);

            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            in.close();
            out.close();
            System.out.println("File copied.");
            //Open share dialog
//          intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
            Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", tempFile);
//          intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
            intent.putExtra(Intent.EXTRA_STREAM, photoURI);
            startActivity(Intent.createChooser(intent, "Share app via"));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

這只會發生,因為它是由 base.apk 名稱保存的。 要根據您的需要共享它,您只需將此文件復制到另一個目錄路徑並在那里重命名即可。 然后使用新文件進行共享。

數據文件夾中的此文件路徑 [file:///data/app/com.yourapppackagename/base.apk] 僅具有讀取權限,因此您無法在那里重命名 .apk 文件。

2021 Kotlin 方式

首先我們需要設置一個文件提供者在AndroidManifest.xml中創建一個文件提供者

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true"
            >
        <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"
                />
    </provider>

如果您沒有 file_path.xml,則在 res/xml 中創建一個(如果不存在則創建 xml 文件夾)並在 file_path.xml 添加

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path
            name="apk"
            path="cache/ExtractedApk/" />
</paths>

現在添加共享apk的代碼

private fun shareAppAsAPK(context: Context) {
    val app: ApplicationInfo = context.applicationInfo
    val originalApk = app.publicSourceDir
    try {
        //Make new directory in new location
        var tempFile: File = File(App.instance.getExternalCacheDir().toString() + "/ExtractedApk")
        //If directory doesn't exists create new
        if (!tempFile.isDirectory) if (!tempFile.mkdirs()) return
        //rename apk file to app name
        tempFile = File(tempFile.path + "/" + getString(app.labelRes).replace(" ", "") + ".apk")
        //If file doesn't exists create new
        if (!tempFile.exists()) {
            if (!tempFile.createNewFile()) {
                return
            }
        }
        //Copy file to new location
        val inp: InputStream = FileInputStream(originalApk)
        val out: OutputStream = FileOutputStream(tempFile)
        val buf = ByteArray(1024)
        var len: Int
        while (inp.read(buf).also { len = it } > 0) {
            out.write(buf, 0, len)
        }
        inp.close()
        out.close()
        //Open share dialog
        val intent = Intent(Intent.ACTION_SEND)
//MIME type for apk, might not work in bluetooth sahre as it doesn't support apk MIME type

        intent.type = "application/vnd.android.package-archive"
        intent.putExtra(
            Intent.EXTRA_STREAM, FileProvider.getUriForFile(
                context, BuildConfig.APPLICATION_ID + ".fileprovider", File(tempFile.path)
            )
        )
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
        startActivity(intent)
    } catch (e: IOException) {
        e.printStackTrace()
    }
}

如果有人試圖從片段生成 apk,他們可能需要更改@sajad 的回答中的幾行,如下所示

  1. 代替

    文件 tempFile = new File(getExternalCacheDir() + "/ExtractedApk");

File tempFile = new File(getActivity().getExternalCacheDir() + "/ExtractedApk");

2.同時為以下行導入 BuildConfig

import androidx.multidex.BuildConfig // 不import androidx.multidex.BuildConfig !!! ,使用您的應用程序 BuildConfig。

如果你低於 EXCEPTION

無法找到具有權限的提供者的元數據

  1. 在清單文件中查找提供者信息

顯現

然后在您的清單文件中查找“ provider ”的名稱和權限,如果它是androidx.core.content.FileProvider然后替換

Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", tempFile);

Uri photoURI = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".fileprovider", tempFile);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM