从WebView输入字段上传相机照片和FileChooser



我的应用程序是基于网络的,我需要从输入现场训练营中上传图片。我有两种情况,因为我不知道另一种方法,具体取决于我选择一个或另一个的页面,请根据其URL请愿书:

a。文件拾取器

b。相机照片拍摄。

我已经处理了文件拾取器,并且完美地上传了文件,问题在于相机。一旦我尝试上传相机图片,它就会崩溃。据我所知,因为Uri。

a)文件选择器:content://媒体/外部/图像/1234

b)相机拍摄:file:///mnt/sdcard/pic.jpg

我找不到更改它的方法。

请参阅更新

它现在崩溃了,因为在尝试上传" content://媒体/external/images/1234"时,nullpointerexception崩溃了。(仅使用相机,而不是文件选择器。)。另外,如果关闭Chooser/Camera(后按钮),我将无法再次称呼它。

案例a)和b)100%工作,这是工作代码,包括我如何知道filechooser或相机的调用:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (resultCode != RESULT_OK) {
    /** fixed code **/
            //To be able to use the filechooser again in case of error
            mUploadMessage.onReceiveValue(null);
    /** fixed code **/
            return;
    }
    if (mUploadMessage==null) {
        Log.d("androidruntime","no mUploadMessage");
        return;
    }
    if (requestCode == FILECHOOSER_RESULTCODE) {
        Uri selectedImage= intent == null || resultCode != RESULT_OK ? null : intent.getData();
        Log.d("androidruntime","url: "+selectedImage.toString());
    }else if (requestCode == CAMERAREQUEST_RESULTCODE) { 
        if(mCapturedImageURI==null){
            Log.d("androidruntime","no mCapturedImageURI");
            return;
        }
      /** fixed code **/
        getContentResolver().notifyChange(mCapturedImageURI, null);
        ContentResolver cr = getContentResolver();
        Uri uriContent= Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), photo.getAbsolutePath(), null, null));
        photo = null;
      /** fixed code **/
    }
    mUploadMessage.onReceiveValue(selectedImage);
    mUploadMessage = null;
}

    private static final int FILECHOOSER_RESULTCODE   = 2888;
    private static final int CAMERAREQUEST_RESULTCODE = 1888;
    private ValueCallback<Uri> mUploadMessage;
    private Uri mCapturedImageURI = null;
    protected class AwesomeWebChromeClient extends WebChromeClient{
        // Per Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType){  
           /**updated, out of the IF **/
                            mUploadMessage = uploadMsg;
           /**updated, out of the IF **/
            if(boolFileChooser){ //Take picture from filechooser
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);  
                i.addCategory(Intent.CATEGORY_OPENABLE);  
                i.setType("image/*");  
                MainActivity.this.startActivityForResult( Intent.createChooser( i, "Escoger Archivo" ), MainActivity.FILECHOOSER_RESULTCODE );  
            } else { //Take photo and upload picture
                Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
                File photo = new File(Environment.getExternalStorageDirectory(),  "Pic.jpg");
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(photo));
                mCapturedImageURI = Uri.fromFile(photo);
                startActivityForResult(cameraIntent, MainActivity.CAMERA_REQUEST);
            }
        }
        // Per Android < 3.0
        public void openFileChooser(ValueCallback<Uri> uploadMsg){
            openFileChooser(uploadMsg, "");
        }
        //Altre
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            openFileChooser(uploadMsg, "");
        }

        /** Added code to clarify chooser. **/
        //The webPage has 2 filechoosers and will send a console message informing what action to perform, taking a photo or updating the file
        public boolean onConsoleMessage(ConsoleMessage cm) {        
            onConsoleMessage(cm.message(), cm.lineNumber(), cm.sourceId());
            return true;
        }
        public void onConsoleMessage(String message, int lineNumber, String sourceID) {
            Log.d("androidruntime", "Per cònsola: " + cm.message());
            if(message.endsWith("foto")){ boolFileChooser= true; }
            else if(message.endsWith("pujada")){ boolFileChooser= false; }
        }
        /** Added code to clarify chooser. **/

    }

更新1

我可以获得" content://媒体/external/images/xxx" uri格式,但是该应用程序在尝试通过" muploadmessage.onreceive.onreceivevalue(selectedimage)"上载URI时仍会崩溃。现在我得到了nullpointerexception。


更新2

固定并工作。

我仅在文件 - 选择器案例中仅在本地变量中使用了" valueCallback uploadmsg",因此,当我尝试上传照片文件时,它一直给我一个例外,因为它是无效的。一旦我从If-Else声明中脱颖而出,所有人都起作用了。上一个更新是处理文件上传的最简单方法。

我已经添加了一个'muploadmessage.onreceivevalue(null);'如果取消相机/FILECHOOSER的意图(您必须在网页中处理它),则如果没有,您将无法再次启动输入字段(意图)。


更新3

在awesomechromeclient中添加了代码的一部分以区分选项,拍照或选择文件。它是我的方法并通过请愿书添加,我敢肯定还有很多其他有效的方法做,

现在功能上的代码为100%。如果指示是否要图片或文件选择器

这是我从WebView Input字段实现相机上传和FILECHOOSER的方式:

以下是此重要主题的代码。删除了非相关代码。

public class MainActivity extends Activity {
private WebView webView;
private String urlStart = "http://www.example.com/mobile/";
//File choser parameters
private static final int FILECHOOSER_RESULTCODE   = 2888;
private ValueCallback<Uri> mUploadMessage;
//Camera parameters
    private Uri mCapturedImageURI = null;
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    webView = (WebView) findViewById(R.id.webView);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setLoadWithOverviewMode(true);
    webView.getSettings().setAllowFileAccess(true);
    webView.loadUrl(urlStart);
    webView.setWebChromeClient(new WebChromeClient() {
        // openFileChooser for Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { 
            mUploadMessage = uploadMsg;
            try{
                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File externalDataDir = Environment.getExternalStoragePublicDirectory(
                          Environment.DIRECTORY_DCIM);
                File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
                          File.separator + "browser-photos");
                cameraDataDir.mkdirs();
                String mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
                          System.currentTimeMillis() + ".jpg";
                mCapturedImageURI = Uri.fromFile(new File(mCameraFilePath));
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
                Intent i = new Intent(Intent.ACTION_GET_CONTENT); 
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("image/*");
                Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[] { cameraIntent });
                startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
              }
             catch(Exception e){
                 Toast.makeText(getBaseContext(), "Camera Exception:"+e, Toast.LENGTH_LONG).show();
             }
           }
        // For Android < 3.0
       @SuppressWarnings("unused")
    public void openFileChooser(ValueCallback<Uri> uploadMsg ) {
               openFileChooser(uploadMsg, "");
           }
    // For Android  > 4.1.1
        @SuppressWarnings("unused")
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
               openFileChooser(uploadMsg, acceptType);
           }

           public boolean onConsoleMessage(ConsoleMessage cm) {        
               onConsoleMessage(cm.message(), cm.lineNumber(), cm.sourceId());
               return true;
           }
           public void onConsoleMessage(String message, int lineNumber, String sourceID) {
               Log.d("androidruntime", "www.example.com: " + message);
             }
    });
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    // TODO Auto-generated method stub
    if(requestCode==FILECHOOSER_RESULTCODE)  
     {  
            if (null == this.mUploadMessage) {
                return;
            }
           Uri result=null;
           try{
                if (resultCode != RESULT_OK) {
                    result = null;
                } else {
                    // retrieve from the private variable if the intent is null
                    result = intent == null ? mCapturedImageURI : intent.getData(); 
                } 
            }
            catch(Exception e)
            {
                Toast.makeText(getApplicationContext(), "activity :"+e, Toast.LENGTH_LONG).show();
            }
            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
     }
}

我希望这对某人有帮助:)

已解决。在我的问题中,有功能代码,以防任何人需要它。

这是问题的解决方案:

  1. 如果我以前打开并取消了:

    ,无法打开相机/filechooser:
    //inside onActivityResult
    if (resultCode != RESULT_OK) {
         mUploadMessage.onReceiveValue(null);
         return;
    }
    
  2. 获取" content://Media/external/images/xxx" uri格式,通过" muploadmessage.onreceivevalue(selectedImage)上传URI";避免使用NullPoInterException

    //inside OnActivityResult
    getContentResolver().notifyChange(mCapturedImageURI, null);
    ContentResolver cr = getContentResolver();
    Uri uriContent = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), photo.getAbsolutePath(), null, null));
    

解决了且工作正常。

只需查看Web Cromeclient类的代码即可。您会发现参数已从早期更改。

public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                       throw new RuntimeException("Stub!");
    }

解决方案:

您只需在此GitHub链接中按照最新的ChromeBrowser代码github上的Android Chrome浏览器代码

为您的项目使用相同的GitHub代码。

注意:Android 4.4 Kitkat版本仍然存在问题。除了Android 4.4的其他版本的Android。

因为这仍然是Google的开放缺陷。请检查以下链接。

单击Android 4.4 WebView

时未调用OpenFileChooser

最新更新