2

I want to show whatsapp statuses in my app. Till now I have done following:

public final String getStatusPath(boolean z) {
    if (Build.VERSION.SDK_INT < 30) {
        if (z) {
            return Environment.getExternalStorageDirectory().getAbsolutePath() + "/WhatsApp Business/Media/.Statuses";
        }
        return Environment.getExternalStorageDirectory().getAbsolutePath() + "/WhatsApp/Media/.Statuses";
    } else if (z) {
        return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/media/com.whatsapp.w4b/WhatsApp Business/Media/.Statuses";
    } else {
        return Environment.getExternalStorageDirectory().getAbsolutePath()+ "/Android/media/com.whatsapp/WhatsApp/Media/.Statuses";
    }
}

private ArrayList<WhatStatusData> getStatusList() {
    ArrayList<WhatStatusData> arrayList = new ArrayList<>();

    File[] listFiles = new File(FileConstants.INSTANCE.getStatusPath(isBusiness)).listFiles();
    int i = 0;
    if (listFiles != null) {
        if (listFiles.length == 0) {
            Arrays.sort(listFiles);
        }

        int length = listFiles.length;
        while (i < length) {
            File file = listFiles[i];
            i++;
            String absolutePath = file.getAbsolutePath();
            Uri fromFile = Uri.fromFile(file);
            String name = file.getName();

            if (!name.equals(".nomedia")) {
                arrayList.add(new WhatStatusData(absolutePath, fromFile, name));
            }
        }
    }
    return arrayList;
}

In manifest

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

But I am not getting data in android 11.In other versions code is working properly.

AZyre
  • 93
  • 1
  • 8

1 Answers1

2

Got the solution There are two possibility for getting hidden files access in android 11

  1. give MANAGE_EXTERNAL_STORAGE permission as said by @Subarata Talukder
  2. give particular folder access permission using storage manager as explained below (without using MANAGE_EXTERNAL_STORAGE permission)

Here I am showing how to access whatsapp statuses programmatically

    //give permissions in manifest
    <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    //give run time permissions

    static final int REQUEST_PERMISSION_KEY = 1;

    int REQUEST_ACTION_OPEN_DOCUMENT_TREE = 101;

    SharedPreferences sharedPreferences;

check if run time permissions are given or not on button click

    if(sharedPreferences.getString("WATREE","").equals("")){
                if(checkAndRequestPermissions()){
                    if (SDK_INT >= Build.VERSION_CODES.Q) {
                        askPermission();
                    }else {
                        callActivity();
                    }
                }
            }else{
                callActivity();
            }



    private  boolean checkAndRequestPermissions() {

      int writePerm = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
      int readPerm = ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.READ_EXTERNAL_STORAGE);

      List<String> listPermissionsNeeded = new ArrayList<>();
      if (writePerm != PackageManager.PERMISSION_GRANTED) {
          listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
      }

    if(readPerm != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
    }

      if (!listPermissionsNeeded.isEmpty()) {
        ActivityCompat.requestPermissions(GBV_StartActivity.this,
                listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),
                REQUEST_PERMISSION_KEY);
        return false;
    }
      return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
      super.onRequestPermissionsResult(requestCode, permissions, grantResults);
      if (requestCode == REQUEST_PERMISSION_KEY) {
          try {

              Map<String, Integer> permsLogin = new HashMap<>();
              // Initialize the map with both permissions
              permsLogin.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
              permsLogin.put(Manifest.permission.READ_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);

              // Fill with actual results from user
              if (grantResults.length > 0) {
                  for (int i = 0; i < permissions.length; i++)
                      permsLogin.put(permissions[i], grantResults[i]);
                  // Check for both permissions
                  if (permsLogin.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
                        && permsLogin.get(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {

                      if (SDK_INT >= Build.VERSION_CODES.Q) {
                        askPermission();
                    }else {
                        callActivity();
                    }

                    // process the normal flow
                    //else any one or both the permissions are not granted
                } else {

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                        if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                                || shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {

                            showDialogOK((dialog, which) -> {
                                switch (which) {
                                    case DialogInterface.BUTTON_POSITIVE:
                                        checkAndRequestPermissions();
                                        break;
                                    case DialogInterface.BUTTON_NEGATIVE:
                                        // proceed with logic by disabling the related features or quit the app.
                                        break;
                                }
                            });
                        }
                        //permission is denied (and never ask again is  checked)
                        //shouldShowRequestPermissionRationale will return false
                        else {
                            Toast.makeText(getApplicationContext(), "Go to settings and enable permissions.", Toast.LENGTH_LONG)
                                    .show();

                            finish();
                            //proceed with logic by disabling the related features or quit the app.
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

private void showDialogOK(DialogInterface.OnClickListener okListener) {

    android.app.AlertDialog.Builder alertDialogBuilder = new android.app.AlertDialog.Builder(GBV_StartActivity.this);

    alertDialogBuilder.setMessage("You need to allow access to the permissions.")
            .setCancelable(false)
            .setPositiveButton("OK", okListener)
            .setNegativeButton("Cancel", okListener);

    android.app.AlertDialog alertDialog = alertDialogBuilder.create();

    // show it
    alertDialog.show();

}
public void callActivity(){

    startActivity(new Intent(GBV_StartActivity.this, MainActivity.class));
}

private String getWhatsupFolder() {

    String oldPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/WhatsApp/Media/.Statuses";
    String oldBusinessPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/WhatsApp Business/Media/.Statuses";

    String newPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/media/com.whatsapp/WhatsApp/Media/.Statuses";
    String newBusinessPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/media/com.whatsapp.w4b/WhatsApp Business/Media/.Statuses";

    String finalPath;


    if(new File(newBusinessPath).exists()){
        finalPath = "Android%2Fmedia%2Fcom.whatsapp.w4b%2FWhatsApp Business%2FMedia%2F.Statuses";
    }else if(new File(newPath).exists()){
        finalPath = "Android%2Fmedia%2Fcom.whatsapp%2FWhatsApp%2FMedia%2F.Statuses";
    }else if(new File(oldBusinessPath).exists()){
        finalPath = "WhatsApp Business%2FMedia%2F.Statuses";
    }else {
        finalPath = "WhatsApp%2FMedia%2F.Statuses";
    }
    return finalPath;
}


@RequiresApi(Build.VERSION_CODES.Q)
private void askPermission() {
    StorageManager storageManager = (StorageManager) getSystemService(STORAGE_SERVICE);
    Intent intent =  storageManager.getPrimaryStorageVolume().createOpenDocumentTreeIntent();

    String targetDirectory = getWhatsupFolder(); // add your directory to be selected by the user
    Uri uri = intent.getParcelableExtra("android.provider.extra.INITIAL_URI");
    String scheme = uri.toString();
    scheme = scheme.replace("/root/", "/document/");
    scheme += "%3A"+targetDirectory;
    uri = Uri.parse(scheme);

    Log.w("TAG", "askPermission: uri::"+uri );
    intent.putExtra("android.provider.extra.INITIAL_URI", uri);
    startActivityForResult(intent, REQUEST_ACTION_OPEN_DOCUMENT_TREE);
}


@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);

    if (requestCode == this.REQUEST_ACTION_OPEN_DOCUMENT_TREE && resultCode == -1) {
        Uri data = intent.getData();
        try {
            getContentResolver().takePersistableUriPermission(data, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        } catch (Exception e) {
            e.printStackTrace();
        }
        SharedPreferences.Editor editor2 = sharedPreferences.edit();
        editor2.putString("WATREE", data.toString());
        editor2.apply();

        callActivity();
    }
}

now after giving all permissions try to get images or videos from storage like below:

    if (SDK_INT >= Build.VERSION_CODES.Q) {
        DocumentFile[] allFiles = getFromSdcard();
        if (allFiles != null) {

            for(int i = 0 ; i <allFiles.length ; i++){
                if (!allFiles[i].getUri().toString().contains(".nomedia")) {
                        Log.e("path:",allFiles[i].getUri().toString());
                        //add data in your arraylist
                }
            }
        }
    }else {
        String oldPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/WhatsApp/Media/.Statuses";
        String oldBusinessPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/WhatsApp Business/Media/.Statuses";

        String newPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/media/com.whatsapp/WhatsApp/Media/.Statuses";
        String newBusinessPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/media/com.whatsapp.w4b/WhatsApp Business/Media/.Statuses";

        String finalPath;
        if (!new File(oldPath).exists()) {
            if (!new File(oldBusinessPath).exists()) {

                if (!new File(newPath).exists()) {
                    if (!new File(newBusinessPath).exists()) {
                        finalPath = oldPath;
                    } else {
                        finalPath = newBusinessPath;
                    }
                } else {
                    finalPath = newPath;
                }
            } else {
                finalPath = oldBusinessPath;
            }
        } else {
            finalPath = oldPath;
        }
        File file2 = new File(finalPath);
        if (file2.exists()) {
            File[] listFiles = file2.listFiles();

            if (listFiles != null) {
                for (int i = 0; i < listFiles.length; i++) {
                    
                        Log.e("path:",listFiles[i].getPath()+"");
                        //add data in your arraylist
                }
            }
        }
    }



    public DocumentFile[] getFromSdcard() {
    DocumentFile fromTreeUri = DocumentFile.fromTreeUri(getContext(), Uri.parse(sharedPreferences.getString("WATREE","")));
    if (fromTreeUri == null || !fromTreeUri.exists() || !fromTreeUri.isDirectory() || !fromTreeUri.canRead() || !fromTreeUri.canWrite()) {
        return null;
    }
    return fromTreeUri.listFiles();
}
AZyre
  • 93
  • 1
  • 8