1

my code below worked with emulator (android 11 & api 30).

private void copy(File in, File out) throws IOException {
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            is = new FileInputStream(in);
            os = new FileOutputStream(out);

            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
                Log.d("AAA", String.valueOf(out.length()));
            }
        } finally {
            assert is != null;
            is.close();
            assert os != null;
            os.close();
        }
    }

where i put this method

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0 && resultCode == RESULT_OK) {
            String path = RealPathUtil.getRealPath(SetVoiceIntroActivity.this, data.getData());
            File in = new File(path);
            File out = new File(getFilesDir(), "record.mp3");

            try {
                copy(in, out);
                Log.d(TAG, out.getAbsolutePath());
            } catch (IOException e) {
                e.printStackTrace();
            }
            binding.voicePlayerView.setVisibility(View.VISIBLE);
            binding.buttonDeleteVoice.setVisibility(View.VISIBLE);
            binding.voicePlayerView.setAudio(out.getAbsolutePath());
        }
    }

but when i try with my phone it have a problem. how can i fix it?

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.yolo.hopel, PID: 19152
    java.lang.AssertionError
        at com.yolo.hopel.Activities.SetProfile.SetVoiceIntroActivity.copy(SetVoiceIntroActivity.java:251)
        at com.yolo.hopel.Activities.SetProfile.SetVoiceIntroActivity.onActivityResult(SetVoiceIntroActivity.java:64)
        at android.app.Activity.dispatchActivityResult(Activity.java:8292)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:5136)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:5184)
        at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2175)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7860)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)

i catch it and i get the message

2021-08-03 19:29:10.310 25013-25013/com.yolo.hopel D/error: /storage/emulated/0/NCT/NgayKhacLa-DenDJGiangPhamTripleD-5393909.mp3: open failed: EACCES (Permission denied)

but i checked permission before

binding.buttonSetVoiceGallery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                checkPermission();
            }
        });
private void checkPermission() {
        PermissionListener permissionlistener = new PermissionListener() {
            @Override
            public void onPermissionGranted() {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_GET_CONTENT);
                intent.setType("audio/*");
                startActivityForResult(intent, 0);
            }
            @Override
            public void onPermissionDenied(List<String> deniedPermissions) {
                Toast.makeText(SetVoiceIntroActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
            }
        };
        TedPermission.with(this)
                .setPermissionListener(permissionlistener)
                .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
                .setPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .check();
    }

i'm sorry but my post is mostle code, i must add some text... please help me, thanks everyone and have a nice day!

2 Answers2

2

An AssertionError is thrown when the programmer thinks that something has happened which he/she didn't expect it to happen. So mostly this seems like a ScopedStorage issue to me since you explicitly mentioned the case with Android 11. You can try reading about the scoped storage in Android . Also the RealPathUtil that you used for github doesn't work for the scoped storage case

You can refer to this answer for some commonly needed operations for Files using Scoped Storage

Some other points you may need to know about Scoped Storage

  • The WRITE_EXTERNAL_STORAGE permission is deprecated and it is replaced by the MANAGE_EXTERNAL_STORAGE which is allowed on Play Store after manual approval by Google. You can now access all the publically available files in Android after Q without need the WRITE_EXTERNAL_PERMISSION. So you must not request the MANAGE_EXTERNAL_STORAGE permission unless you're building a File Explorer or anything like that
  • You can write to these public directories using the MediaStore class if you need explicit access to external storage, if not then you can use context.getFilesDir() which gives you app private access to the external storage under the /data/data/yourpackagename directory. You must manage this space explicitly
  • If you need temporary file storage, you should prefer using context.getCacheDir() and the space here will be managed by Android itself
  • Under no circumstances, you can get access to the app specific directory, even after you have MANAGE_EXTERNAL_STORAGE
gtxtreme
  • 1,830
  • 1
  • 13
  • 25
1

You got a nice uri and then you mess around with all kind of untrusty code to obtain a file path to use FileInputStream for it.

Completely unnecessary.

Open an inputstream for the obtained uri and use it as it was your fileinputstream.

InputStream is = getContentResolver.openInputStream(data.getData());
blackapps
  • 8,011
  • 2
  • 11
  • 25