001package com.gigya.android.sdk.ui.plugin;
002
003import android.Manifest;
004import android.content.Intent;
005import android.content.pm.PackageManager;
006import android.net.Uri;
007import android.os.Build;
008import android.provider.MediaStore;
009import android.support.annotation.NonNull;
010import android.support.v4.app.Fragment;
011import android.support.v4.content.ContextCompat;
012import android.webkit.ValueCallback;
013import android.webkit.WebChromeClient;
014import android.webkit.WebView;
015
016import com.gigya.android.sdk.GigyaLogger;
017import com.gigya.android.sdk.utils.FileUtils;
018
019import java.io.File;
020import java.lang.ref.WeakReference;
021
022import static android.app.Activity.RESULT_OK;
023
024public class GigyaPluginFileChooser extends WebChromeClient {
025
026    private final WeakReference<Fragment> _fragmentRef;
027
028    GigyaPluginFileChooser(Fragment fragment) {
029        _fragmentRef = new WeakReference<>(fragment);
030    }
031
032    private Fragment getFragment() {
033        return _fragmentRef.get();
034    }
035
036    private static final String LOG_TAG = "GigyaPluginFileChooser";
037
038    static final int FIRE_ACCESS_PERMISSION_REQUEST_CODE = 14;
039    static final int FILE_CHOOSER_MEDIA_REQUEST_CODE = 15;
040    private String _cameraTempImagePath;
041    private ValueCallback<Uri[]> _imagePathCallback;
042
043    @Override
044    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
045        GigyaLogger.debug(LOG_TAG, "onShowFileChooser: ");
046        if (getFragment() == null) {
047            return false;
048        }
049
050        if (_imagePathCallback != null) {
051            _imagePathCallback.onReceiveValue(null);
052        }
053        _imagePathCallback = filePathCallback;
054
055        final int externalStoragePermission = ContextCompat.checkSelfPermission(webView.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
056        if (externalStoragePermission == PackageManager.PERMISSION_GRANTED) {
057            sendImageChooserIntent();
058        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
059            getFragment().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, FIRE_ACCESS_PERMISSION_REQUEST_CODE);
060        } else {
061            GigyaLogger.error(LOG_TAG, "Application must include Manifest.permission.WRITE_EXTERNAL_STORAGE in order to communicate with file system");
062            return false;
063        }
064        return true;
065    }
066
067    private void sendImageChooserIntent() {
068        if (getFragment() == null) {
069            return;
070        }
071        GigyaLogger.debug(LOG_TAG, "Sending image chooser intent.");
072        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
073        if (takePictureIntent.resolveActivity(getFragment().getActivity().getPackageManager()) != null) {
074            File imageFile = null;
075            try {
076                imageFile = FileUtils.createImageFile();
077                takePictureIntent.putExtra("imagePath", _cameraTempImagePath);
078            } catch (Exception ex) {
079                ex.printStackTrace();
080            }
081            if (imageFile != null) {
082                _cameraTempImagePath = "file:" + imageFile.getAbsolutePath();
083                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
084            } else {
085                takePictureIntent = null;
086            }
087        }
088
089        // Set up an image file chooser intent.
090        final Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
091        contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
092        contentSelectionIntent.setType("image/*");
093
094        final Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
095        chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
096        chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
097        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, takePictureIntent != null ?
098                new Intent[]{takePictureIntent} : new Intent[0]);
099        getFragment().startActivityForResult(chooserIntent, FILE_CHOOSER_MEDIA_REQUEST_CODE);
100    }
101
102    void onActivityResult(int resultCode, Intent data) {
103        Uri[] results = null;
104        if (resultCode == RESULT_OK) {
105            if (data != null && data.getDataString() != null) {
106                String dataString = data.getDataString();
107                results = new Uri[]{Uri.parse(dataString)};
108            }
109            // If there is not data, then we may have taken a photo
110            else if (_cameraTempImagePath != null) {
111                results = new Uri[]{Uri.parse(_cameraTempImagePath)};
112            }
113        }
114        _imagePathCallback.onReceiveValue(results);
115        _imagePathCallback = null;
116    }
117
118    void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
119        GigyaLogger.debug(LOG_TAG, "onRequestPermissionsResult:");
120        if (requestCode == FIRE_ACCESS_PERMISSION_REQUEST_CODE) {
121            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
122                GigyaLogger.debug(LOG_TAG, "External storage permission explicitly granted.");
123                if (_imagePathCallback != null) {
124                    sendImageChooserIntent();
125                }
126            } else {
127                // Permission denied by the user.
128                GigyaLogger.debug(LOG_TAG, "External storage permission explicitly denied.");
129            }
130        }
131    }
132}