4

I have a superuser access on my device. I used this function very successfully to download and update my application programattically, but since android 6.0 this function stopped working (because of new type of permission requests).

My question is: since I have superuser access on my rooted device, how can edit my function so I can download the external file on the sdcard without asking for permission from user?

here is the function I use to update the app:

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;
    }
}

and call:

UpdateAppZ atualizaApp = new UpdateAppZ();    
                             atualizaApp.setContext(getApplicationContext()); 
                              atualizaApp.execute("http://85.118.98.251/misho/app-debug.apk");
Mister M
  • 1,539
  • 3
  • 17
  • 37
  • what is your build tool ,target and compiled sdk version? – Radhey Oct 18 '16 at 09:13
  • buildToolsVersion '23.0.3' minSdkVersion 19 targetSdkVersion 23 this function works well up to 6.0, but I need to edit it so it can work on 6.0 also – Mister M Oct 18 '16 at 09:15
  • Why not dowload it to File's app dir ? you dont need to make the apk public. – crgarridos Oct 18 '16 at 09:18
  • @cgarrido can you provide code snippet please? I need to run the downloaded file from the device after download has been completed – Mister M Oct 18 '16 at 09:20
  • Just as recommandation : don't use "/mnt/sdcard/Download/", all devices don't have the same mounting point path. Prefer [Environment.getExternalStorageDirectory()](https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()) – crgarridos Oct 18 '16 at 09:22
  • you need to set permission model for runtime permission ,as your compiled sdk might be 23 ,but if your compiled version was 22 or less then it would be directly allow you to download files etc. no need to set runtime permission.just follow this http://stackoverflow.com/questions/33139754/android-6-0-marshmallow-cannot-write-to-sd-card and let me know if not getting. – Radhey Oct 18 '16 at 09:23
  • @MisterM just replace "/mnt/sdcard/Download/ with Context#getFilesDir() – crgarridos Oct 18 '16 at 09:25
  • `I need to run the downloaded file from the device after download has been complete`. You did not tell if your app should 'run' it or a different app choosed by intent. – greenapps Oct 18 '16 at 09:32
  • `download the external file on the sdcard`. You very probably are not downloading to a micro SD card at all but to external memory. – greenapps Oct 18 '16 at 09:34

3 Answers3

2

Download to getExternalFilesDir(). No permission needed while other apps have access.

greenapps
  • 11,154
  • 2
  • 16
  • 19
  • 1
    As per the docs : 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. – Radhey Oct 18 '16 at 09:25
1

No you can not do that as from Android 6.0 You need to ask for dangerous permissions at runtime.

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.

Weather you have root access or not.

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

Shridutt Kothari
  • 7,326
  • 3
  • 41
  • 61
1

https://stackoverflow.com/a/51112708/4650581


You can use getExternalFilesDir if you want to save file without any permission. As stated in the documentation:

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)


This link may be useful:

Save files on device storage

Misagh
  • 3,403
  • 1
  • 20
  • 17