Загрузка файла веб-просмотра Android Studio Из галереи работает, но не при съемке

#android #file-upload #webview #android-webview #android-camera

Вопрос:

Как конвертировать

 file:/data/user/0/com...../cache/JPEG_980041_6389888734396042298.jpg
 

к этому

 [content://com.android.providers.media.documents/document/image:16781]
 

Я следил за многими учебниками о том, как делать фотографии и загружать их в веб-представление с помощью камеры и фотогалереи.

Эта работа из галереи, как говорится в журнале, [content://com.android.providers.media.documents/document/image:16781] и файл передается в html <input type="file" , но когда я нажимаю «ок» после съемки в журнале камеры, говорится file:/data/user/0/com...../cache/JPEG_980041_6389888734396042298.jpg , что файл НЕ передается на вход файла 🙁

есть ли способ изменить код для «преобразования» из file:/data/.... в [content://....

Здесь AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.apptheway.wexview">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_GPS" />
    <uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" android:maxSdkVersion="28" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.CAMERA2" />
    <uses-permission android:name="android.webkit.PermissionRequest" />
    <uses-permission android:name="com.android.vending.BILLING" />
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.VIDEO_CAPTURE" />
    <uses-permission android:name="android.permission.AUDIO_CAPTURE" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />

    <uses-feature android:name="android.hardware.camera"  />
    <uses-feature android:name="android.hardware.camera2" />
    <uses-feature android:name="android.hardware.location.gps" />
    <uses-feature android:name="android.hardware.location.network" />
    <uses-feature android:name="android.hardware.audio.low_latency" />
    <uses-feature android:name="android.hardware.audio.pro" />
    <uses-feature android:name="android.hardware.microphone" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:name="android.hardware.camera.front" />

    <application
        android:allowBackup="true"
        android:fullBackupContent="true"
        android:hardwareAccelerated="true"
        android:requestLegacyExternalStorage="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:usesCleartextTraffic="true"
        android:grantUriPermissions="true"
        android:theme="@style/SplashTheme">
        <!-- [START fcm_disable_auto_init] -->
        <meta-data
            android:name="firebase_messaging_auto_init_enabled"
            android:value="false" />
        <meta-data
            android:name="firebase_analytics_collection_enabled"
            android:value="false" />
        <!-- [END fcm_disable_auto_init] -->
       <activity android:name=".MainActivity" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:authorities="${applicationId}.provider"
            android:name=".GenericFileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
        </provider>
        <service
            android:name=".MyFirebaseMessagingService"
            android:exported="false"
            android:stopWithTask="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
    </application>

    <queries>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="image/*,video/*" />
        </intent>
    </queries>

</manifest>
 

Здесь xml/file_paths.xml

 <?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path name="external_files" path="." />
    <external-files-path name="extfiles" path="." />
    <external-files-path name="external" path="." />
    <external-files-path name="my_images" path="." />
    <external-files-path name="my_videos" path="." />
    <external-media-path name="external_files" path="." />
    <external-media-path name="extfiles" path="." />
    <external-media-path name="my_images" path="." />
    <external-media-path name="my_videos" path="." />
    <external-path name="external_files" path="."/>
    <external-path name="extfiles" path="."/>
    <external-path name="external" path="."/>
    <external-path name="my_images" path="."/>
    <external-path name="my_videos" path="."/>
    <files-path name="external_files" path="."/>
    <files-path name="extfiles" path="."/>
    <files-path name="external" path="."/>
    <files-path name="my_images" path="."/>
    <files-path name="my_videos" path="."/>
    <files-path name="files" path="."/>
</paths>
 

Вот код в MainActivity.java

 @SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})

public class MainActivity extends AppCompatActivity {

    private WebView mWebView;
    private ValueCallback<Uri[]> mFilePathCallback;
    private String mCameraPhotoPath;
    private String mCameravideoPath;
    private static final int INPUT_FILE_REQUEST_CODE = 1;

    // FILE IMAGE
    private File createImageFile() throws IOException {

        int timeStamp = (new Random().nextInt((1000000 - 1)   1)   1);
        String imageFileName = "JPEG_"   timeStamp   "_";
        File storageDir = getCacheDir();
        return File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",         /* suffix */
                storageDir      /* directory */
        );

    }

    // FILE VIDEO
    private File createVideoFile() throws IOException {

        int timeStamp = (new Random().nextInt((1000000 - 1)   1)   1);
        String videoFileName = "VID_"   timeStamp   "_";
        File storageDir = getCacheDir();
        return File.createTempFile(
                videoFileName,
                ".mp4",
                storageDir
        );

    }

    // FOR FILE UPLOAD
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
            super.onActivityResult(requestCode, resultCode, data);
            return;
        }

        Uri[] results = null;

        if (resultCode == Activity.RESULT_OK) {

            if (data == null || data.getDataString() == null) {
                // If there is not data, then we may have taken a photo
                if (mCameraPhotoPath != null) {
                    results = new Uri[]{Uri.parse(mCameraPhotoPath)};
                    Log.e("imgFileU","88 " mCameraPhotoPath);
                }
            } else {
                String dataString = data.getDataString();
                if (dataString != null) {
                    results = new Uri[]{Uri.parse(dataString)};
                    Log.e("imgFileU","94 " Arrays.toString(results));
                }
            }

        }
        else {
            if (mCameraPhotoPath != null) {
                File file = new File(Uri.parse(mCameraPhotoPath).toString());
                results = new Uri[]{Uri.parse(file.getPath())};
            }
            Log.e("imgFileU","104 result "  Arrays.toString(results));
        }

        mFilePathCallback.onReceiveValue(results);
        mFilePathCallback = null;

    }

    @Override
    protected void onStart() {
        super.onStart();

        String[] permissions = {
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.CAMERA,
                Manifest.permission.RECORD_AUDIO,
                Manifest.permission.MODIFY_AUDIO_SETTINGS,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };

        requestPermissions(permissions, 0);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        getWindow().requestFeature(Window.FEATURE_NO_TITLE);

        String appNAME = getString(R.string.app_name);
        String stubdomain = getString(R.string.stubdomain);
        AtomicReference<String> fireToken = new AtomicReference<>("");
        int randy = (new Random().nextInt((10000000 - 1)   1)   1);

        mWebView = new WebView(this);
        WebSettings webSettings = mWebView.getSettings();
        webSettings.setLoadWithOverviewMode(true);
        webSettings.setUseWideViewPort(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setDatabaseEnabled(true);
        webSettings.setGeolocationEnabled(true);
        webSettings.setBuiltInZoomControls(true);
        webSettings.setDisplayZoomControls(false);
        webSettings.setSupportZoom(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setJavaScriptEnabled(true);
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setDatabaseEnabled(true);
        webSettings.setMediaPlaybackRequiresUserGesture(false);
        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        webSettings.setUserAgentString("stubfeedandroid " appNAME " " stubdomain " " webSettings.getUserAgentString());

        // FOR FILE UPLOAD
        mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

        // LINKS HANDLING
        mWebView.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {

                String url = request.getUrl().toString();

                int opensInWexView = 1;

                // IF FILE
                if (    url.contains(".pdf") || url.contains(".mov") || url.contains(".mp") ||
                        url.contains(".hv") || url.contains(".aif") || url.contains(".wav") ||
                        url.contains(".xls") || url.contains(".doc") || url.contains(".txt")
                ) {
                    opensInWexView = 0;
                }

                // URL SCHEME
                if (    url.startsWith("tel:") || url.startsWith("sms:") ||
                        url.startsWith("mms:") || url.startsWith("mailto:") ||
                        url.startsWith("fax:") || url.startsWith("fb:")
                ) {
                    opensInWexView = 0;
                }

                // STUBSHARE
                if ( url.startsWith("stubshare:") ) { opensInWexView = 3; }

                switch (opensInWexView) {
                    case 0:
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                        startActivity(intent);
                        break;
                    case 1:
                        view.loadUrl(url);
                        break;
                    case 3:
                        Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                        String urlinhttp = url.replace("stubshare://","https://www.");
                        sharingIntent.putExtra(Intent.EXTRA_TEXT, urlinhttp);
                        sharingIntent.setType("text/plain");
                        startActivity(Intent.createChooser(sharingIntent, "Share"));
                        break;
                }

                return true;

            }
        });

        // WEBCHROME
        mWebView.setWebChromeClient(new WebChromeClient() {

            public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {
                // Double check that we don't have any existing callbacks
                if (mFilePathCallback != null) {
                    mFilePathCallback.onReceiveValue(null);
                }
                mFilePathCallback = filePath;

                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                    // Create the File where the photo should go
                    File photoFile = null;
                    try {
                        photoFile = createImageFile();
                        takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
                    } catch (IOException ex) {
                        // Error occurred while creating the File
                        Log.e("imgFileU", "Unable to create Image File", ex);
                    }
                    // Continue only if the File was successfully created
                    if (photoFile != null) {
                        mCameraPhotoPath = "file:"   photoFile.getAbsolutePath();
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                    } else {
                        takePictureIntent = null;
                    }
                }

                Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
                if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
                    // Create the File where the video should go
                    File videoFile = null;
                    try {
                        videoFile = createVideoFile();
                        takeVideoIntent.putExtra("VideoPath", mCameravideoPath);
                    } catch (IOException ex) {
                        // Error occurred while creating the File
                        Log.e("vfile", "Unable to create Image File", ex);
                    }
                    // Continue only if the File was successfully created
                    if (videoFile != null) {
                        mCameravideoPath = "file:"   videoFile.getAbsolutePath();
                        takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(videoFile));
                    } else {
                        takeVideoIntent = null;
                    }
                }

                Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                contentSelectionIntent.setType("image/*, video/*");
                contentSelectionIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                contentSelectionIntent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*"});
                contentSelectionIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/* video/*");

                Intent[] intentArray;
                if (takePictureIntent != null amp;amp; takeVideoIntent != null) {
                    intentArray = new Intent[]{takePictureIntent, takeVideoIntent};
                } else if (takePictureIntent != null) {
                    intentArray = new Intent[]{takePictureIntent};
                } else if (takeVideoIntent != null) {
                    intentArray = new Intent[]{takeVideoIntent};
                } else {
                    intentArray = new Intent[0];
                }

                Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
                chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                chooserIntent.putExtra(Intent.EXTRA_TITLE, "Upload");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
                startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
                return true;
            }

        });

        this.setContentView(mWebView);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater myMenuInflater = getMenuInflater();
        myMenuInflater.inflate(R.menu.super_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        if (itemId == R.id.myMenuOne) {
            onBackPressed();
        } else if (itemId == R.id.myMenuTwo) {
            GoForward();
        }
        return true;
    }

    private void GoForward() {
        if (mWebView.canGoForward()) {
            mWebView.goForward();
        } else {
            Toast.makeText(this, "Can't go further!", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onBackPressed() {
        if (mWebView.canGoBack()) {
            mWebView.goBack();
        }
    }

    @Override
    public boolean onKeyDown(final int keyCode, final KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) amp;amp; mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

}
 

Комментарии:

1. Вы должны использовать класс FileProvidet для обслуживания вашего файла и получить uri схемы содержимого для пути к файлу.

2. @blackapps Это проблема, потому что каждый раз, когда я пытаюсь следовать учебникам, они указывают androidManifest.xml и добавь <provider android:name="android.support.v4.content.FileProvider" … но Android беспокоит меня, когда я это делаю, я получаю ТОННЫ предупреждений об устаревании…. плюс «Библиотека поддержки Android подошла к концу своего срока службы. 28.0 был последним выпуском пространства имен поддержки Android, и пространство имен больше не поддерживается» … есть ли более новый способ сделать это ?

3. Если вы используете FileProvider в файле java вашей деятельности, Android Studio предложит импортировать, если импорт еще не выполнен. Если есть, то удалите его и выберите правильный импорт. Используйте то же самое в манифесте.

4. @Jintor, почему вы используете старую поддержку FileProvider ? Видишь developer.android.com/reference/androidx/core/content/.

5. @CoolMind Я искал повсюду, много-много-много ответов, и все это заканчивается файлом:/data…. вместо [content://com.a…… Я не могу понять, почему и не могу это исправить, не могли бы вы подробнее ответить на этот вопрос ? Я действительно застрял. попробовал «androidx.core.контент. Файлообменник» безуспешно… Я также пробовал Uri.parse(new File(mCameraPhotoPath).toString()) то же самое, всегда, возвращается file:/...