java - 将图像从 Android 上传到我的服务器(权限被拒绝)

标签 java android android-permissions resttemplate

我正在尝试将从图库中选择的图像上传到我的 Springboot 服务器,但是当我的服务尝试发布图像时,我的文件路径权限被拒绝。我已将这些权限添加到我的 AndroidManifest 中:

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- permission below just in case, should not be needed I believe -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

然后,我实时请求许可以选择图像,然后我想将其放置在膨胀 View 中,用户可以在其中提供有关图像的更多详细信息,然后将其添加到我稍后发布的报告中。

由于我遇到了这个权限问题,当我尝试提交包含图像(Uri)的报告对象时,我也再次请求权限。

但我仍然收到此错误:

Caused by: java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/IMG_20200206_120434.jpg (Permission denied)

我在谷歌上发现的这个错误的每一次点击都会指向那些不要求这种实时许可的人,但我相信我什至做了一次。

这是我的代码的一些相关 fragment :

else if (view.getId() == R.id.stubNewBreedingReportSelectImageButt) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
                } else {
                    getPhotoFromPhone(); // this starts the intent to pick an image
                }
            } 
        }

else if (view.getId() == R.id.stubNewBreedingReportSubmitButt) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
                } else {
                    submitNewBreedingReport();
                }
            } 
        }

这是来 self 的 onClick(View view) 方法。第一个有效,因为我可以从图库中选择图像。根据我发现的从 Android 上传图像的项目的每个示例,第二个可能不需要检查权限。

在我的 onActivityResult(int requestCode, int resultCode, Intent data) 方法中,我膨胀了这个“添加图像详细信息 View ”。我还将选定的 Uri 作为私有(private) Uri selectedImg 存储在 Activity 中以供将来使用。这一切似乎工作得很好。

然后,当我提交图像(在submitNewReport() 方法中)时,我使用ExecutorService(java 类)启动一个新的异步线程进行上传。在此 Callable<> 中,我获取 Springs RestTemplate 的实例并尝试发布图像,但是当我的 RestTemplate 尝试调用并从我的 Uri 获取文件时,我的权限被拒绝。

这是我的应用程序ImageService中的上传方法:

public Gallery uploadPictureWithInfo(Uri uri, Map<String,Object> imgParams, Context context) {
        if (uri.getPath() != null) {
            File resourceFile = new File(getPathFromUri(uri,context));
            //if (resourceFile.exists()) {
                Gallery saved = null;
                Map<String,Object> params = new HashMap<>();
                params.put(PARAM_FILE, new FileSystemResource(resourceFile));
                if (imgParams.get(PARAM_GALLERY_ID) != null || (long) imgParams.get(PARAM_GALLERY_ID) > (long) 0)  {
                    params.put(PARAM_GALLERY_ID, imgParams.get(PARAM_GALLERY_ID));
                    if (imgParams.get(PARAM_DESCRIPTION) != null) {
                        params.put(PARAM_DESCRIPTION, imgParams.get(PARAM_DESCRIPTION));
                    }
                    if (imgParams.get(PARAM_PHOTOGRAPH) != null) {
                        params.put(PARAM_PHOTOGRAPH, imgParams.get(PARAM_PHOTOGRAPH));
                    }
                    if (imgParams.get(PARAM_USER_ID) != null && (long) imgParams.get(PARAM_USER_ID) > 0) {
                        params.put(PARAM_USER_ID, imgParams.get(PARAM_USER_ID));
                    }
                    HttpEntity requestEntity = new HttpEntity<>(params, AquaDbConfig.getImageHeaders());
                    ResponseEntity<Gallery> responseEntity =
                            restTemplate.exchange(AquaDbConfig.getApiUrl() + "/images/uploadImgWithInfo", HttpMethod.POST, requestEntity, Gallery.class);
                    if (responseEntity.hasBody()) {
                        saved = responseEntity.getBody();
                    }
                    return saved;
                }
            //}
        }
        return null;
    }


public static String getPathFromUri(Uri uri, Context context) {
        String[] filePath = { MediaStore.Images.Media.DATA };
        Cursor c = context.getContentResolver().query(uri,filePath, null, null, null);
        c.moveToFirst();
        int columnIndex = c.getColumnIndex(filePath[0]);
        String picturePath = c.getString(columnIndex);
        c.close();
        return picturePath;
    }

我注释掉了对 file.isExist() 的检查以通过该测试,因为否则它不会生成堆栈跟踪。

所以我的问题是当我将图像文件发布到服务器时如何读取图像文件?我读了一些有关 FileProvider 类的内容,但在我看来,它用于通过 Intents 将文件发送到新的 Activites 或其他应用程序。在我看来,它并不是专门用于此目的的,因为除了在图库中选择图像之外,我从未离开过我的 Activity 。创建此 ReportedBreeding 对象的不同步骤是由膨胀的 ViewStub 处理的,而不是新的 Activity 。此外,我使用的 Uri 并不引用我为应用程序创建的任何目录,而是引用用户图像库(外部存储)。

我还尝试在 android list 中将我的 ImageService 声明为服务,尽管我不确定我们谈论的是同一种服务。然后我添加了这个权限,但没有什么区别:

        <service
            android:name=".service.MyImageFactory"
            android:permission="android.permission.READ_EXTERNAL_STORAGE">
        </service>

如果您知道如何获得此 RestTemplate POST 方法的权限(在我审查的示例中似乎没有其他人需要)或者我如何解决此问题,请分享!我开始感到有点沮丧和困惑。对我来说问题是为什么 android 需要另一个权限检查以及如何提供它或在我的 uploadPictureWithInfo(..) 方法中解决它?

最佳答案

尝试在 getPhotoFromPhone() 之前请求 WRITE_EXTERNAL_STORAGE 的权限

关于java - 将图像从 Android 上传到我的服务器(权限被拒绝),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60129392/

相关文章:

java - android - 在包含特殊字符的特定字符串上使用 replaceAll 时出现 java.lang.ArrayIndexOutOfBoundsException

android - 如何以编程方式更改 android 中的 ProgressDialog 消息字体大小?

java - 由于缺少位置权限,应用程序在启动时崩溃

android - API 23中的Android权限正常权限和危险权限列表?

java - Dropbox api 获取以前的文件版本预览 url

java - 我的 java spring boot 代码有什么问题

在 Linux 上使用 chromedriver 和 chrome 时出现 java.lang.ExceptionInInitializerError

java - 如何通过其他变量访问java类中的常量?

java - 当调用 Activity 被销毁时,新 Activity 的 Android getIntent 为 NULL

google-play - 向亚马逊和谷歌提交应用程序后的Android权限