我如何在我的应用程序中共享 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
如何更改?
这只是因为它是由 base.apk 名称保存的。
要根据您的需要共享它,您只需将此文件复制到另一个目录路径并在那里重命名。然后使用新文件进行共享。
数据文件夹中的这个文件路径[file:///data/app/com.yourapppackagename/base.apk]只有读取权限,所以你不能重命名那里的.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();
}
}
Update:此方法不再有效,如果您实施它会抛出异常。由于 android N,如果我们想访问内存中的文件(如 apk 文件),我们应该使用内容提供程序。如需更多信息,请访问此 Guide。尽管复制、重命名和共享复制版本的整个想法仍然有效。
可以使用这个功能,测试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();
}
}
如果有人试图从片段生成 apk,他们可能需要更改@sajad 的回答中的几行,如下所示
替换
File tempFile = new File(getExternalCacheDir() + "/ExtractedApk");
与
File tempFile = new File(getActivity().getExternalCacheDir() + "/ExtractedApk");
2.while 正在为以下行导入 BuildConfig
import androidx.multidex.BuildConfig
// 不要这样做!!! ,使用您的应用程序 BuildConfig。
并且如果您低于异常
Couldn't find meta-data for provider with authority
- 在清单文件中查找提供商信息
然后在清单文件中查找“提供者”的名称和权限,如果是 androidx.core.content.FileProvider
,则
替换
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", tempFile);
有
Uri photoURI = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".fileprovider", tempFile);
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 文件发送到另一台设备:
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
如何更改?
这只是因为它是由 base.apk 名称保存的。 要根据您的需要共享它,您只需将此文件复制到另一个目录路径并在那里重命名。然后使用新文件进行共享。
数据文件夹中的这个文件路径[file:///data/app/com.yourapppackagename/base.apk]只有读取权限,所以你不能重命名那里的.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();
}
}
Update:此方法不再有效,如果您实施它会抛出异常。由于 android N,如果我们想访问内存中的文件(如 apk 文件),我们应该使用内容提供程序。如需更多信息,请访问此 Guide。尽管复制、重命名和共享复制版本的整个想法仍然有效。
可以使用这个功能,测试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();
}
}
如果有人试图从片段生成 apk,他们可能需要更改@sajad 的回答中的几行,如下所示
替换
File tempFile = new File(getExternalCacheDir() + "/ExtractedApk");
与
File tempFile = new File(getActivity().getExternalCacheDir() + "/ExtractedApk");
2.while 正在为以下行导入 BuildConfig
import androidx.multidex.BuildConfig
// 不要这样做!!! ,使用您的应用程序 BuildConfig。
并且如果您低于异常
Couldn't find meta-data for provider with authority
- 在清单文件中查找提供商信息
然后在清单文件中查找“提供者”的名称和权限,如果是 androidx.core.content.FileProvider
,则
替换
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", tempFile);
有
Uri photoURI = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".fileprovider", tempFile);
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()
}
}