android使用webview上传文件(支持相册和拍照)

===文一==================================================================
mWebView.setWebChromeClient(new TestWebChromeClient(new WebChromeClient()) {@Override
                        public void openFileChooser(ValueCallback<Uri> uploadFile) {
                                // TODO Auto-generated method stub

                                if (mUploadMessage != null)
                                        return;
                                mUploadMessage = uploadFile;
                                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                                i.addCategory(Intent.CATEGORY_OPENABLE);
                                i.setType("*/*");
                                TestActivity.this.startActivityForResult(Intent.createChooser(
                                                i, getString(R.string.choose_upload)), FILE_SELECTED);
                        }
                });

===文二===================================================================

网页上的button定义 <input tyoe="file" />

方法一,也是网上能搜到最多的解决方案
参考网址:http://stackoverflow.com/questions/4944102/android-webview-file-input-field-filechooser-doesnt-show-up
        http://m0s-programming.blogspot.tw/2011/02/file-upload-in-through-webview-on.html

复制代码
       @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if(requestCode==FILECHOOSER_RESULTCODE) {  
               if (null == mUploadMessage) return;  
                        Uri result = data == null || resultCode != RESULT_OK ? null  
                                : data.getData();  
                        mUploadMessage.onReceiveValue(result);  
                        mUploadMessage = null;  
                          
              }
          }
复制代码

          在WebChromeClient的设定中加入如下代码:

复制代码
        setting.setWebChromeClient(new WebChromeClient() {
             // For Android 3.0+
         public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {  
                if (mUploadMessage != null) return;
                mUploadMessage = uploadMsg;   
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                    startActivityForResult( Intent.createChooser( i, "File Chooser" ), BrowserActivity.FILECHOOSER_RESULTCODE );
                 }
             // For Android < 3.0
         public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                openFileChooser( uploadMsg, "" );
         }
           });
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg, acceptType);
}
复制代码

          openFileChooser为隐藏方法。
           这样可以实现打开目录上传文件。不过在3.0以后的版本中,如果同样的网页在android自带的浏览器打开会发现,
           还有照相,录音的功能,然后直接将生成的图片或音频文件上传,这样就要使用下面的方法。
方法二,参考自com.android.browser的源码程式。

复制代码
   @Override
       protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if(requestCode==FILECHOOSER_RESULTCODE) {  
               if (null == mUploadMessage) return;  
                        Uri result = data == null || resultCode != RESULT_OK ? null  
                                : data.getData();
                            if (result == null && data == null && resultCode == Activity.RESULT_OK) {
                            File cameraFile = new File(mCameraFilePath);
                            if (cameraFile.exists()) {
                                result = Uri.fromFile(cameraFile);
                                // Broadcast to the media scanner that we have a new photo
                                // so it will be added into the gallery for the user.
                                sendBroadcast(
                                        new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
                                    }
                             }
                        mUploadMessage.onReceiveValue(result);  
                        mUploadMessage = null;
              }
          }
复制代码

          在WebChromeClient的设定中加入如下代码:
      

复制代码
setting.setWebChromeClient(new WebChromeClient() {
             // For Android 3.0+
         public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {  
                if (mUploadMessage != null) return;
                mUploadMessage = uploadMsg;
                startActivityForResult(createDefaultOpenableIntent(),
                        BrowserActivity.FILECHOOSER_RESULTCODE);
            }
                 }
             // For Android < 3.0
         public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                openFileChooser( uploadMsg, "" );
         }
  });
复制代码

     

复制代码
private Intent createDefaultOpenableIntent() {
           // Create and return a chooser with the default OPENABLE
           // actions including the camera, camcorder and sound
           // recorder where available.
             Intent i = new Intent(Intent.ACTION_GET_CONTENT);
             i.addCategory(Intent.CATEGORY_OPENABLE);
             i.setType("*/*");

             Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
                    createSoundRecorderIntent());
            chooser.putExtra(Intent.EXTRA_INTENT, i);
            return chooser;
        }
        
        private Intent createChooserIntent(Intent... intents) {
            Intent chooser = new Intent(Intent.ACTION_CHOOSER);
            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
            chooser.putExtra(Intent.EXTRA_TITLE, "File Chooser");
           return chooser;
          }

    private Intent createCameraIntent() {
          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";
          cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
          return cameraIntent;
        }

    private Intent createCamcorderIntent() {
         return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        }

    private Intent createSoundRecorderIntent() {
         return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
        }
复制代码

============文三=================================================

老夫最近需要做一个项目,需要调用服务器段的一些网页来选择文件,刚开始还挺纠结的,不知从何下手,网上大致预览了大神们走过的路,他们传统的方式都是使用一下代码:

[java] view plaincopy
  1. public void openFileChooser(ValueCallback<Uri> uploadMsg,  
  2.    String acceptType, String capture) {  
  3.   mUploadMessage = uploadMsg;  
  4.   Intent intent = new Intent(Intent.ACTION_GET_CONTENT);  
  5.   intent.addCategory(Intent.CATEGORY_OPENABLE);  
  6.   intent.setType("image/*");  
  7.   context.startActivityForResult(  
  8.     Intent.createChooser(intent, "完成操作需要使用"),  
  9.     WebMainActivity.FILECHOOSER_RESULTCODE);  
  10.   
  11.  }  

看了一下网上的朋友,基本上都是一样的代码,全部都是蜘蛛抓取别人的文档,恶心无比!本人很讨厌,直接导致了我要得到的搜索结果已经被海量的垃圾覆盖,不过,从http://stackoverflow.com/找到了我想要的代码,诶,蛮失望的,对国内的一些程序员博客等....
 

好了,废话,上叙的代码,其实根本就不满足我们的需要,至少我们的产品经理一般的想法就是希望我们能从相机中或者相册中选择图片的,这才是他们的核心要求,所以,我们必须自定义属于自己的弹出框界面的


不过,说这个上传前,先讲几个小知识吧;

如果你是使用webview的时候,会不会莫名其妙的打开系统的浏览器,是不是很纠结的!
其实要自定义属于我们自己的东西---WebViewClient,其实定义了就是啥操作也不错 呵呵 

[java] view plaincopy
  1. /*** 
  2.      * 自定义WebViewClient,否则会自动跳转到系统的浏览器的 
  3.      * @author spring sky 
  4.      * 创建时间:Aug 19, 20133:40:18 PM 
  5.      */  
  6.     private class MyWebViewClient extends WebViewClient{  
  7.         private Context mContext;  
  8.         public MyWebViewClient(Context context){  
  9.             super();  
  10.             mContext = context;  
  11.         }  
  12.           
  13.         @Override  
  14.         public void onPageStarted(WebView view, String url, Bitmap favicon) {  
  15.             Log.d(TAG,"URL地址:" + url);  
  16.             super.onPageStarted(view, url, favicon);  
  17.         }  
  18.   
  19.         @Override  
  20.         public void onPageFinished(WebView view, String url) {  
  21.             Log.i(TAG, "onPageFinished");  
  22.             super.onPageFinished(view, url);  
  23.         }  
  24.     }  
然后调用我们自定义的WebViewClient:
[java] view plaincopy
  1. mWebView.setWebViewClient(new MyWebViewClient(this));  

现在我们开始说说弹出框的问题吧,经过stackoverflow的牛人说明,android源码的html标记<input type=file> 在选择文件,其实就是自定义WebChromeClient,所以我们要在这个里面做处理,但是有一点,因为android的系统有一直升级(google为了追求完美),所以很多功能都是逐步的实现的,这就是照成了兼容性的问题,需要说明的是,这对我们的弹出框没任何影响,首先,我们要自定义我们的MyWebChromeClient

代码如下:

[java] view plaincopy
  1. /*** 
  2.      * 自定义WebChromeClient,做选择图片处理 
  3.      * @author spring sky 
  4.      * 创建时间:Aug 19, 20133:40:46 PM 
  5.      */  
  6.     private class MyWebChromeClient extends WebChromeClient {  
  7.   
  8.         // For Android 3.0+  
  9.            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {    
  10.                if (mUploadMessage != nullreturn;  
  11.                mUploadMessage = uploadMsg;     
  12.                selectImage();  
  13.            }  
  14.             // For Android < 3.0  
  15.             public void openFileChooser(ValueCallback<Uri> uploadMsg) {  
  16.                    openFileChooser( uploadMsg, "" );  
  17.             }  
  18.             // For Android  > 4.1.1  
  19.           public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {  
  20.                   openFileChooser(uploadMsg, acceptType);  
  21.           }  
  22.   
  23.     }  

以上的代码就是已经兼容了目前的android所有市场版本了,需要说明的是:selectImage(); 就是我定义的一个方法,内容就是弹出来一个选择框,选择相册和camera,这点,我觉得没必要讲了吧,反正给你们要共享代码的,还有一点,就是很多朋友反馈我之前写的代码在选择相册或相机的时候程序崩溃,这次我彻底的解决了这个问题,还是版本兼容的问题,烦烦烦.....程序员的烦恼....伤不起....


服务器端我是用的是javaEE的struts上传,有地方说明一下吧:

1.我当时用的是apache-tomcat7作为我的服务器端,大家都知道上传文件,上传的时候都会先把客户端发过来的文件保存在临时的文件中,然后上传完成就会copy到正式的文件,之后临时文件会删除,至于为什么,如果你是一个多思考的人,你会明白为什么,如果不知道为什么,希望你去多想想为什么,人的大脑不是为了谈恋爱,赚钱的,是用来思考的,实在不明白为什么,请在思考了以后找我!QQ:840950105

我的电脑是mac系统,所以在struts.xml配置了这样的代码:

[html] view plaincopy
  1. <constant name="struts.multipart.saveDir" value="/Users/mac/Documents/tomcat/apache-tomcat-7.0.42/temp"/>  

希望各位大哥大姐一定要注意这点,因为之前很多人就问我,为什么我上传老是失败,需要先把临时目录配置好,如果是window系统的话,肯定找不到/Users/mac/Documents/
这呀的目录的,各位大哥大姐,小弟真心的希望你们在学习程序的过程中多注意别人说的每一个重点地方,多自己找找错误,解决问题,这样就能走出自己的路!


2.一下代码,如果稍微东一点点代码的人,都会看懂的,request存放两个值,一个上传的消息,一个上传后的文件路径!(顺便说一下,我的javaEE好多年没折腾了,都忘记的差不多了,随便写的服务器端,请大家多多见谅,诶,程序员伤不起,过两年回家种田了...产品经理折磨我...测试折磨我...尼玛客户这不懂那不明白的也折磨我...)

[html] view plaincopy
  1. ServletActionContext.getRequest(). setAttribute("typeError",  
  2.         result);  
  3. ServletActionContext.getRequest().setAttribute("uploadFile", rsImage);  


以上基本上都是核心的技术点了,没啥了!
需要说明的是,大家在拿到我的android客户端代码,请先把自己的webview需要load的url修改为自己部署javaEE的项目url,切记切记,不然,老夫真的要吐血身亡了!

废话不说了,哥讨厌那些使用蜘蛛爬来爬去的博客和网站,小弟恳请希望这些站长能活出自己的人生,别装逼的拿着别人的经验给自己做装逼炫耀的资本!路都是自己走出来的,别吃了别人拉下来的还喊香!

版权:spring sky
共享的代码如下:
android客户端代码
javaEE服务器端代码


顺便说一下,本人年纪不小了,为了能做出自己的一些事情,有点创业的想法,如果有创业的朋友缺忠诚的合作伙伴,请联系我!(专注于android ios开发,没有神一样的智商,但拥有不屈不服的心,不为困难而低头,只为理想而拼搏)


展开阅读全文

没有更多推荐了,返回首页