向所有同事们致以问候和新年快乐。
我的代码从远程服务器下载apk文件。我需要通过代码启动安装过程,而无需用户明确安装它。问题是,我无法使用SD卡下载apk文件。
我可以导航到data / data / files文件夹,可以看到我的文件已下载。唯一的问题是我无法安装它。这就是我得到的
'/data/data/org.obs.testinstall.main/files/app.apk': Permission denied
据我所知,Android不授予访问数据目录的权限。 我的问题是如何在不使用SD卡的情况下下载和安装应用程序(apk)。此应用程序不打算在市场上发布。我尝试过使用内部存储
FileOutputStream fos = openFileOutput("app.apk", Context.MODE_PRIVATE);
和缓存目录
File file = getCacheDir();
File outputFile = new File(file, "app.apk");
两者都给出相同的结果..“权限被拒绝”
当我更改代码以合并SD卡时,应用程序运行正常,但使用SD卡不是一种选择。
当然必须有办法做到这一点。很难相信Android O / S存在这样的障碍。
有人这样做过吗?任何解决方法?任何指针都会有所帮助。
答案 0 :(得分:12)
你可以这样做:
String fileName = "tmp.apk";
FileOutputStream fos = openFileOutput(fileName,
MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE);
// write the .apk content here ... flush() and close()
// Now start the standard instalation window
File fileLocation = new File(context.getFilesDir(), fileName);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(fileLocation),
"application/vnd.android.package-archive");
context.startActivity(intent);
但要小心,因为该文件现在是世界可见的, 并且可以在同一设备中的任何应用程序中看到, 如果他们知道文件位置。
答案 1 :(得分:2)
无需root。 你可以使用linux命令chmod来完成它。
public static String exec(String[] args) {
String result = "";
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
InputStream errIs = null;
InputStream inIs = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read = -1;
process = processBuilder.start();
errIs = process.getErrorStream();
while ((read = errIs.read()) != -1) {
baos.write(read);
}
baos.write('\n');
inIs = process.getInputStream();
while ((read = inIs.read()) != -1) {
baos.write(read);
}
byte[] data = baos.toByteArray();
result = new String(data);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (errIs != null) {
errIs.close();
}
if (inIs != null) {
inIs.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
return result;
}
在您的程序中,可以像这样调用:
String[] args1 = { "chmod", "705", "/data/data/org.obs.testinstall.main/files/" };
exec(args1);
String[] args2 = { "chmod", "604", "/data/data/org.obs.testinstall.main/files/app.apk" };
exec(args2);
然后您可以根据需要安装app.apk。
答案 2 :(得分:1)
还可以使用
downloadedFile.setReadable(true, false);
与
fileOutputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
有两个setReadable方法。第一个具有一个参数,第二个具有两个参数。
setReadable(boolean readable)
setReadable(boolean readable, boolean ownerOnly)
答案 3 :(得分:0)
尝试生根设备,然后从设备运行程序,而不是使用模拟器。
答案 4 :(得分:0)
对我来说,我在startActivity
之后删除了apk文件,这是异步的。
太糟糕了,没有更好的解析错误描述(文件未找到,访问被拒绝,包中的文件损坏,......)
答案 5 :(得分:0)
当您发送安装apk的意图时,您可以使用此功能更改apk目录的模式。
private static boolean changeMode(String filePath, String prefixPath) {
if (TextUtils.isEmpty(prefixPath) || !filePath.startsWith(prefixPath)) {
return true;
}
try {
String[] args1 = { "chmod", "705", prefixPath};
Runtime.getRuntime().exec(args1);
} catch (IOException e) {
e.printStackTrace();
return false;
}
String subPath = filePath.split(prefixPath)[1];
String[] subArr = subPath.split(File.separator);
for (String path : subArr) {
if (!TextUtils.isEmpty(path)) {
prefixPath = prefixPath + File.separator + path;
try {
if (!prefixPath.endsWith(".apk")) {
String[] progArray1 = {"chmod", "705", prefixPath};
Runtime.getRuntime().exec(progArray1);
} else {
String[] progArray2 = {"chmod", "604", prefixPath};
Runtime.getRuntime().exec(progArray2);
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
return true;
}
在发送意图之前,请检查chmod是否成功。
boolean chmodRes = changeMode(filePath, context.getCacheDir().getAbsolutePath())
&& changeMode(filePath, context.getFilesDir().getAbsolutePath());
if (!chmodRes) {
return false;
}