Android API26+应用中APK文件选择与网络传输问题求助
Android应用APK选择与上传解决方案
问题背景
开发基于Android API 26+的文件上传应用,支持文档、视频、图片及应用(APK)上传至服务器。服务端已就绪,但客户端使用Intent.ACTION_GET_CONTENT无法选择APK文件,计划自行实现已安装应用列表展示,通过publicSourceDir获取APK路径后复制到应用目录再上传,担忧APK无法正常网络传输。
现有代码
文件选择实现(无法选择APK)
Intent intent = new Intent(); intent.setAction(Intent.ACTION_GET_CONTENT); intent.setType("*/*");
获取已安装应用列表
final PackageManager pm = getPackageManager(); // 获取已安装应用列表 @SuppressLint("QueryPermissionsNeeded") List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA); for (ApplicationInfo packageInfo: packages) { String publicSourceDir = packageInfo.publicSourceDir; System.out.println(packageInfo.packageName); }
解决方案
1. 解决APK读取权限问题
直接访问publicSourceDir会因API 26+的权限限制抛出异常,应通过PackageManager提供的openArchive方法获取APK输入流,无需直接访问文件路径:
// 针对用户选中的ApplicationInfo实例 ApplicationInfo selectedApp = ...; PackageManager pm = getPackageManager(); try { // 打开APK文件的输入流 InputStream apkInputStream = pm.openArchive(selectedApp.sourceDir, null); // 后续可直接用该流上传,无需复制文件 } catch (IOException e) { e.printStackTrace(); }
2. 直接上传APK流(无需复制到应用目录)
跳过文件复制步骤,直接读取APK输入流并上传,节省存储与时间成本。以下是基于OkHttp的上传示例:
// 获取选中应用的APK输入流 InputStream apkInputStream = pm.openArchive(selectedApp.sourceDir, null); // 构建OkHttp上传请求 OkHttpClient client = new OkHttpClient(); RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("upload_file", selectedApp.packageName + ".apk", new InputStreamRequestBody(apkInputStream)) .build(); Request request = new Request.Builder() .url("你的服务器上传接口地址") .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 处理上传失败逻辑 try { apkInputStream.close(); } catch (IOException ex) { ex.printStackTrace(); } } @Override public void onResponse(Call call, Response response) throws IOException { // 处理上传成功逻辑 apkInputStream.close(); } }); // 自定义RequestBody,支持直接上传输入流 static class InputStreamRequestBody extends RequestBody { private final InputStream inputStream; public InputStreamRequestBody(InputStream inputStream) { this.inputStream = inputStream; } @Override public MediaType contentType() { return MediaType.parse("application/vnd.android.package-archive"); } @Override public void writeTo(BufferedSink sink) throws IOException { Source source = Okio.source(inputStream); sink.writeAll(source); } }
3. 必要权限配置
- 应用列表查询权限:若需获取所有已安装应用(含系统应用),在
AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
仅需第三方应用时,可通过过滤ApplicationInfo.FLAG_SYSTEM避免申请该权限。
- 网络权限:添加网络访问权限以实现上传:
<uses-permission android:name="android.permission.INTERNET" />
4. APK传输说明
APK属于二进制压缩文件,与普通文件的网络传输逻辑完全一致。只要能正确获取文件输入流,通过HTTP的multipart/form-data或二进制流方式上传即可,服务端按常规文件接收逻辑处理即可,不存在传输障碍。
内容的提问来源于stack exchange,提问作者Uber_soldaten228
相关产品推荐
相关产品推荐

