Android WebView File Upload

后端 未结 5 1677
灰色年华
灰色年华 2020-12-02 12:48

I am developing an Android app. Basically it is a WebView and a progressBar. Facebook\'s mobile site (m.facebook.com) is loaded into the WebView.

相关标签:
5条回答
  • 2020-12-02 12:58

    When invoking AlertDialog in WebChromeClient.OpenFileChooser, you need to notify webchrome that no selection was done in case of back button. Since Back button can be pressed in you dialog, you have to handle OnCancel of the dialog and tell WebChrome that selection was finished.

    eg:

    private ValueCallback<Uri> mUploadMessage;
    private final static int FILECHOOSER_RESULTCODE = 1;
    private final static int CAMERA_RESULTCODE = 2;
    
    ...
    
        webView.setWebChromeClient(new WebChromeClient() {
          public boolean onConsoleMessage(ConsoleMessage cm) {
            Log.d("MyApplication", cm.message() + " -- From line "
                                 + cm.lineNumber() + " of "
                                 + cm.sourceId() );
            return true;
          }
    
          public void onExceededDatabaseQuota(String url, String
                databaseIdentifier, long currentQuota, long estimatedSize, long
                totalUsedQuota, QuotaUpdater quotaUpdater) {
                                quotaUpdater.updateQuota(estimatedSize+65536);
                } 
    
         @SuppressWarnings("unused")
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) {
                this.openFileChooser(uploadMsg);
             }
    
         @SuppressWarnings("unused")
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) {
            this.openFileChooser(uploadMsg);
         }
    
         public void openFileChooser(ValueCallback<Uri> uploadMsg) {
    
             mUploadMessage = uploadMsg;
            PesScreen.this.openImageIntent();
         }
        });        
    

    ...

    private void openImageIntent() {
    
    final File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); //file storage
    
    
        root.mkdirs();
        int nCnt = 1;
        if ( root.listFiles() != null )
            nCnt = root.listFiles().length;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        final String fname =  String.format("/dest-%s-%d.jpg", sdf.format(Calendar.getInstance().getTime()), nCnt);
    
        final File sdImageMainDirectory = new File(root.getAbsolutePath() + fname);
        outputFileUri = Uri.fromFile(sdImageMainDirectory);
    //selection Photo/Gallery dialog
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
    
        alert.setTitle("Select source");
    
        final CharSequence[] items = {"Photo", "Gallery"};
        alert.setItems(items, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
    
                dialog.dismiss();
                if( whichButton == 0)
                {
                    Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
                    startActivityForResult(chooserIntent, CAMERA_RESULTCODE);
                }
                if( whichButton == 1)
                {
                    Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
                    chooserIntent.setType("image/*");
                    startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
                }
          }
        });
        alert.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
    
            //here we have to handle BACK button/cancel 
                if ( mUploadMessage!= null ){
                    mUploadMessage.onReceiveValue(null);
                }
                mUploadMessage = null;
                dialog.dismiss();
            }
        });
        alert.create().show();
    
    0 讨论(0)
  • 2020-12-02 13:04

    This code will help to solve the issue

    Just update the MainActivity.Java file with the bellow code

    public class MainActivity extends Activity{
        private WebView mWebview ;
        private ValueCallback<Uri> mUploadMessage;
        public ValueCallback<Uri[]> uploadMessage;
        public static final int REQUEST_SELECT_FILE = 100;
        private final static int FILECHOOSER_RESULTCODE = 1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
    
            mWebview  = (WebView) findViewById(R.id.help_webview);
            WebSettings webSettings = mWebview.getSettings();
            webSettings.setJavaScriptEnabled(true);
            webSettings.setUseWideViewPort(true);
            webSettings.setLoadWithOverviewMode(true);
            webSettings.setAllowFileAccess(true);
            webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
            webSettings.setBuiltInZoomControls(true);
            webSettings.setPluginState(WebSettings.PluginState.ON);
            webSettings.setSupportZoom(true);
            webSettings.setAllowContentAccess(true);
    
    
    
            final Activity activity = this;
            mWebview.setWebViewClient(new WebViewClient() {
                public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                    Toast.makeText(activity, description, Toast.LENGTH_SHORT).show();
                }
            });
    
            mWebview .loadUrl("http://www.google.com");
    
            String permission = Manifest.permission.CAMERA;
            int grant = ContextCompat.checkSelfPermission(this, permission);
            if (grant != PackageManager.PERMISSION_GRANTED) {
                String[] permission_list = new String[1];
                permission_list[0] = permission;
                ActivityCompat.requestPermissions(this, permission_list, 1);
            }
    
    
            mWebview.setWebChromeClient(new WebChromeClient()
            {
                // For 3.0+ Devices (Start)
                // onActivityResult attached before constructor
                protected void openFileChooser(ValueCallback uploadMsg, String acceptType)
                {
                    mUploadMessage = uploadMsg;
                    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                    i.addCategory(Intent.CATEGORY_OPENABLE);
                    i.setType("image/*");
                    startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
                }
    
    
                // For Lollipop 5.0+ Devices
                @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
                public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
                {
                    if (uploadMessage != null) {
                        uploadMessage.onReceiveValue(null);
                        uploadMessage = null;
                    }
    
                    uploadMessage = filePathCallback;
    
                    Intent intent = fileChooserParams.createIntent();
                    try
                    {
                        startActivityForResult(intent, REQUEST_SELECT_FILE);
                    } catch (ActivityNotFoundException e)
                    {
                        uploadMessage = null;
                        Toast.makeText(MainActivity.this.getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show();
                        return false;
                    }
                    return true;
                }
    
                //For Android 4.1 only
                protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
                {
                    mUploadMessage = uploadMsg;
                    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                    intent.addCategory(Intent.CATEGORY_OPENABLE);
                    intent.setType("image/*");
                    startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
                }
    
                protected void openFileChooser(ValueCallback<Uri> uploadMsg)
                {
                    mUploadMessage = uploadMsg;
                    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                    i.addCategory(Intent.CATEGORY_OPENABLE);
                    i.setType("image/*");
                    startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
                }
            });
    
    
    
        }
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent intent)
        {
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            {
                if (requestCode == REQUEST_SELECT_FILE)
                {
                    if (uploadMessage == null)
                        return;
                    uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
                    uploadMessage = null;
                }
            }
            else if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == mUploadMessage)
                    return;
                // Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
                // Use RESULT_OK only if you're implementing WebView inside an Activity
                Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : intent.getData();
                mUploadMessage.onReceiveValue(result);
                mUploadMessage = null;
            }
            else
                Toast.makeText(MainActivity.this.getApplicationContext(), "Failed to Upload Image", Toast.LENGTH_LONG).show();
        }
    

    Make sure to enable the permission in the AndroidManifest.xml update the following lines

     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
            <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
            <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    

    It worked for me try with this code.

    0 讨论(0)
  • 2020-12-02 13:05

    This is how i am using in my app

     private class MyWebChromeClient extends WebChromeClient {
        //The undocumented magic method override
        //Eclipse will swear at you if you try to put @Override here
    
    
        // For Android 3.0+
        public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
            mUploadMessage = uploadMsg;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
        }
    
        //For Android 4.1+ only
        protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            mUploadMessage = uploadMsg;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
        }
    
        protected void openFileChooser(ValueCallback<Uri> uploadMsg) {
            mUploadMessage = uploadMsg;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            startActivityForResult(Intent.createChooser(intent, "File Chooser"), FILECHOOSER_RESULTCODE);
        }
    
        // For Lollipop 5.0+ Devices
        public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
            if (uploadMessage != null) {
                uploadMessage.onReceiveValue(null);
                uploadMessage = null;
            }
    
            uploadMessage = filePathCallback;
            Intent intent = null;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                intent = fileChooserParams.createIntent();
            }
            try {
                startActivityForResult(intent, REQUEST_SELECT_FILE);
            } catch (ActivityNotFoundException e) {
                uploadMessage = null;
                Toast.makeText(getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show();
                return false;
            }
            return true;
        }
    
    0 讨论(0)
  • 2020-12-02 13:07

    Given the high number of votes I'm guessing no one has noticed the 3rd comment (from David Esteves) contains a link with to answer to this question.

    Michel Olivier said:

    This solution also works for Honeycomb and Ice Cream Sandwich. Seems like Google introduced a cool new feature (accept attribute) and forgot to to implement an overload for backwards compatibility.

    So you just need to add a openFileChooser overload to your MyWebChromeClient class that accepts the string parameter and then call the one that does not:

    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) 
    {  
        this.openFileChooser(uploadMsg);
    }
    

    Doing this I was able to make your code run as intended.

    0 讨论(0)
  • 2020-12-02 13:20

    Mike Olivier's reference shared by Fr33dan is important. I am sharing what worked for me under situation quite akin yours.

    wv.setWebChromeClient(new WebChromeClient()  {
    
    // For Android 3.0+
    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {  
    mUploadMessage = uploadMsg;  
    Intent i = new Intent(Intent.ACTION_GET_CONTENT);  
    i.addCategory(Intent.CATEGORY_OPENABLE);  
    i.setType("image/*");  
    MainActivity.this.startActivityForResult( Intent.createChooser( i, getString(R.string.fileselect) ), MainActivity.FILECHOOSER_RESULTCODE ); 
    }
    
    // For Android < 3.0
    public void openFileChooser( ValueCallback<Uri> uploadMsg ) {
    openFileChooser( uploadMsg, "" );
    }
    
    
    // For Android > 4.1
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
    openFileChooser( uploadMsg, "" );
    }
    });
    

    NOTE: I found this somewhere in stack overflow and m0s' blog.

    Also, Ignore lint warnings. This one works pretty well for API 8 and above.

    0 讨论(0)
提交回复
热议问题