Android 6.0 - 无需请求许可即可将文件下载到外部存储

Android 6.0 - Download file to external storage without asking for permission

我在我的设备上拥有超级用户访问权限。我非常成功地使用此功能以编程方式下载和更新我的应用程序,但自 android 6.0 起此功能停止工作(由于新类型的权限请求)。

我的问题是:因为我在我的 root 设备上有超级用户访问权限,如何编辑我的函数以便我可以在不征求用户许可的情况下下载 sdcard 上的外部文件?

这是我用来更新应用程序的函数:

public class UpdateAppZ extends AsyncTask<String,Void,Void>{
    private Context context;
    public void setContext(Context contextf){
        context = contextf;
    }

    @Override
    protected Void doInBackground(String... arg0) {
        try {
            URL url = new URL(arg0[0]);
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();

            String PATH = "/mnt/sdcard/Download/";
            File file = new File(PATH);
            file.mkdirs();
            File outputFile = new File(file, "update.apk");
            if(outputFile.exists()){
                outputFile.delete();
            }
            FileOutputStream fos = new FileOutputStream(outputFile);

            InputStream is = c.getInputStream();

            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len1);
            }
            fos.close();
            is.close();

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(new File("/mnt/sdcard/Download/update.apk")), "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
            context.startActivity(intent);


        } catch (Exception e) {
            Log.e("UpdateAPP", "Update error! " + e.getMessage());
        }
        return null;
    }
}

并致电:

UpdateAppZ atualizaApp = new UpdateAppZ();    
                             atualizaApp.setContext(getApplicationContext()); 
                              atualizaApp.execute("http://85.118.98.251/misho/app-debug.apk");

不,你不能这样做,因为从 Android 6.0 开始你需要在运行时请求危险权限。

Because If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the OS will enforce the app to request permissions from the user at run-time.

无论您是否拥有 root 访问权限。

来源:
https://developer.android.com/guide/topics/security/permissions.html https://developer.android.com/training/permissions/index.html

下载到 getExternalFilesDir()。其他应用可以访问时无需许可。


如果你想在没有任何权限的情况下保存文件,你可以使用getExternalFilesDir。 如文档中所述:

getExternalFilesDir

Added in API level 8

File getExternalFilesDir (String type)

Returns the absolute path to the directory on the primary shared/external storage device where the application can place persistent files it owns. These files are internal to the applications, and not typically visible to the user as media.

This is like getFilesDir() in that these files will be deleted when the application is uninstalled, however there are some important differences: Shared storage may not always be available, since removable media can be ejected by the user. Media state can be checked using getExternalStorageState(File). There is no security enforced with these files. For example, any application holding WRITE_EXTERNAL_STORAGE can write to these files.

If a shared storage device is emulated (as determined by isExternalStorageEmulated(File)), it's contents are backed by a private user data partition, which means there is little benefit to storing data here instead of the private directories returned by getFilesDir(), etc.

Starting in KITKAT, no permissions are required to read or write to the returned path; it's always accessible to the calling app. This only applies to paths generated for package name of the calling application.

To access paths belonging to other packages, WRITE_EXTERNAL_STORAGE and/or READ_EXTERNAL_STORAGE are required. On devices with multiple users (as described by UserManager), each user has their own isolated shared storage. Applications only have access to the shared storage for the user they're running as.

The returned path may change over time if different shared storage media is inserted, so only relative paths should be persisted.

https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)


这个link可能有用:

Save files on device storage