首页 > 解决方案 > 复制在模拟器上工作但在安卓设备上不工作的音频文件

问题描述

我下面的代码适用于模拟器(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();
        }
    }

我把这个方法放在哪里

@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());
        }
    }

但是当我尝试使用我的手机时,它出现了问题。我该如何解决?

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)

我抓住了它,我得到了消息

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)

但我之前检查过许可

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

对不起,我的帖子是大多数代码,我必须添加一些文字...请帮助我,谢谢大家,祝你有美好的一天!

标签: javaandroidaudio

解决方案


AssertionError当程序员认为发生了他/她没想到会发生的事情时,抛出An 。所以大多数情况下这对我来说似乎是一个ScopedStorage问题,因为你明确提到了Android 11. 您可以尝试阅读 Android 中的范围存储。此外RealPathUtil,您用于 github 的内容不适用于范围存储案例

对于使用 Scoped Storage 的文件的一些常用操作,您可以参考此答案

您可能需要了解的有关 Scoped Storage 的其他几点

  • WRITE_EXTERNAL_STORAGE权限已弃用,MANAGE_EXTERNAL_STORAGE并由 Google 手动批准后在 Play 商店中允许的权限替换。您现在可以在 Q 之后访问 Android 中所有公开可用的文件,而无需WRITE_EXTERNAL_PERMISSION. MANAGE_EXTERNAL_STORAGE因此,除非您正在构建文件资源管理器或类似的东西,否则您不得请求许可
  • MediaStore如果您需要显式访问外部存储,则可以使用该类写入这些公共目录,如果不需要,则可以使用context.getFilesDir()它为您提供对目录下外部存储的应用程序私有访问权限/data/data/yourpackagename。您必须明确管理此空间
  • 如果您需要临时文件存储,您应该更喜欢使用context.getCacheDir(),这里的空间将由 Android 自己管理
  • 在任何情况下,您都无法访问应用程序的特定目录,即使您拥有MANAGE_EXTERNAL_STORAGE

推荐阅读