zoukankan      html  css  js  c++  java
  • 真正可用的安卓webview html图片上传限制突破处理(拍照+相册都可以用)

    两篇起步使用webview参考文章,第一篇解除限制,但会调用外部浏览器打开链接,第二篇 覆盖shouldOverrideUrlLoading return true

    https://www.jb51.net/article/104199.htm

    https://www.cnblogs.com/sohowang/p/3998155.html

    android 多媒体和相机详解五(先学习下相机和相册的基本操作)

    https://www.2cto.com/kf/201207/143320.html

    有拍照和选相册(拍照后无法上传,相册选择可以)

    https://blog.csdn.net/a_running_wolf/article/details/77983739

    https://download.csdn.net/download/st666/9621904?locationNum=4

    真正可用的拍照上传例子在这(可正常拍照,但没有选择相册)

    https://download.csdn.net/download/wangchsh2008/10232317

    但是上面这些例子都没有图片压缩功能,上传拍照的照片过大(>2M)通过流量的会失败,看来还是有一定的实用限制

    H5异步上传前台(支持选择后即时查看图片)

    <input type="file" name="thefile" id="j-file">
     <img src="" id='j-img' alt="" width="100%">
     <button id='j-btn'>upload</button>
     <script type="text/javascript">
      var o_file = document.getElementById('j-file'),
          o_btn = document.getElementById('j-btn'),
          o_img = document.getElementById('j-img'),
          target_file = null;
    
      o_file.addEventListener('change',function(event){
          var file = event.target.files[0];
          if(!file) return;
          target_file = file;
          var url = window.URL.createObjectURL(target_file);
          if(/image/.test(target_file.type)){
              o_img.setAttribute('src',url);
          }else{
              console.log('请选择图片');
          }
      },false);
    
      o_btn.onclick = function(){
          if(!target_file) return;
          //数据处理
          var data = new FormData();
          data.append('thefile',target_file);
        
          var xhr = new XMLHttpRequest();
    
          if(xhr.upload){
            xhr.upload.addEventListener("progress", function(e){
              var loaded = e.loaded;    //已经上传大小情况 
              var tot = e.total;      //附件总大小 
              var per = Math.floor(100*loaded/tot);  //已经上传的百分比 
              console.log(per+'%');//进度
            }, false);
          }
        
          xhr.onreadystatechange = function(e) {
              if (xhr.readyState == 4) {
                if (xhr.status >=200&&xhr.status<300||xhr.status==304) {
                    //上传成功                 
                }
              }
          }; 
          xhr.onloadend = function(){
            //无论失败或成功
          }
          xhr.onerror = function(){          
              //网络失败
          }
          // 开始上传
          xhr.open("POST",'/LBM/Home/SspBuzPicMng/uploadFile', true); 
          xhr.send(data); 
      }
     </script>

    安卓代码(拍照+相册选择都可以哦,流量上传超过2M容易失败)

    package com.gtj.admin.gapt;
    
    import android.Manifest;
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.content.ClipData;
    import android.content.ContentValues;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.graphics.Bitmap;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Parcelable;
    import android.os.StrictMode;
    import android.provider.MediaStore;
    import android.support.annotation.RequiresApi;
    import android.support.v4.app.ActivityCompat;
    import android.text.format.DateFormat;
    import android.util.Log;
    import android.webkit.ValueCallback;
    import android.webkit.WebChromeClient;
    import android.webkit.WebResourceRequest;
    import android.webkit.WebSettings;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    import android.widget.Toast;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.Calendar;
    import java.util.Locale;
    
    public class MainActivity extends Activity {
    
        private static final String TAG = MainActivity.class.getSimpleName();
        private WebView mWebView;
        private String TMP_URL = "http://221.2.169.102:50001/LBM";
        private ValueCallback<Uri> mUploadMessage;// 表单的数据信息
        private ValueCallback<Uri[]> mUploadCallbackAboveL;
        private final static int FILECHOOSER_RESULTCODE = 1;// 表单的结果回调</span>
        private Uri imageUri;
        File file;
    
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mWebView = (WebView) findViewById(R.id.main_web);
    
            mWebView.loadUrl(TMP_URL);
            mWebView.getSettings().setJavaScriptEnabled(true);
            //mWebView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
            WebSettings settings = mWebView.getSettings();
            settings.setDomStorageEnabled(true);
            settings.setUseWideViewPort(true);
            settings.setLoadWithOverviewMode(true);
            settings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true
            settings.setAllowFileAccess(true);    // 是否可访问本地文件,默认值 true
            // 是否允许通过file url加载的Javascript读取本地文件,默认值 false
            settings.setAllowFileAccessFromFileURLs(false);
            // 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false
            settings.setAllowUniversalAccessFromFileURLs(false);
            settings.setJavaScriptEnabled(true);
            settings.setSupportZoom(true);
            //检查权限
            checkAppPermission();
            mWebView.setWebViewClient(new WebViewClient() {
                @TargetApi(Build.VERSION_CODES.LOLLIPOP)
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
                {
                    //返回false,意味着请求过程里,不管有多少次的跳转请求(即新的请求地址),均交给webView自己处理,这也是此方法的默认处理
                    //返回true,说明你自己想根据url,做新的跳转,比如在判断url符合条件的情况下,我想让webView加载http://ask.csdn.net/questions/178242
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (request.getUrl().toString().contains("sina.cn")){
                            view.loadUrl("http://ask.csdn.net/questions/178242");
                            return true;
                        }
                    }
    
                    view.loadUrl(request.getUrl().toString());
                    return true;
                }
    
                @Override
                public void onPageStarted(WebView view, String url, Bitmap favicon) {
                    // TODO Auto-generated method stub
                    super.onPageStarted(view, url, favicon);
                }
    
                @Override
                public void onPageFinished(WebView view, String url) {
                    // TODO Auto-generated method stub
                    super.onPageFinished(view, url);
                }
            });
            mWebView.setWebChromeClient(new WebChromeClient() {
                @Override
                // onShowFileChooser详解 http://teachcourse.cn/2224.html
                public boolean onShowFileChooser(WebView webView,
                                                 ValueCallback<Uri[]> filePathCallback,
                                                 FileChooserParams fileChooserParams) {
                    mUploadCallbackAboveL = filePathCallback;
                    take();
                    return true;
                }
    
                public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                    mUploadMessage = uploadMsg;
                    take();
                }
    
                public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                    mUploadMessage = uploadMsg;
                    take();
                }
    
                public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                    mUploadMessage = uploadMsg;
                    take();
                }
            });
    
            //android 7.0系统解决拍照的问题
    //        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    //        StrictMode.setVmPolicy(builder.build());
    //        builder.detectFileUriExposure();
        }
    
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == FILECHOOSER_RESULTCODE) {
                updatePhotos();
                if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (mUploadCallbackAboveL != null) {
                    onActivityResultAboveL(requestCode, resultCode, data);
                } else if (mUploadMessage != null) {
                    Log.e("result", result + "");
                    if (result == null) {
    //                        mUploadMessage.onReceiveValue(imageUri);
                        mUploadMessage.onReceiveValue(imageUri);
                        mUploadMessage = null;
    
                        Log.e("imageUri", imageUri + "");
                    } else {
                        mUploadMessage.onReceiveValue(result);
                        mUploadMessage = null;
                    }
    
    
                }
            }
        }
    
    
        @SuppressWarnings("null")
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
            if (requestCode != FILECHOOSER_RESULTCODE
                    || mUploadCallbackAboveL == null) {
                return;
            }
    
            Uri[] results = null;
            if (resultCode == Activity.RESULT_OK) {
                if (data == null) {
                    results = new Uri[]{imageUri};
                } else {
                    String dataString = data.getDataString();
                    ClipData clipData = data.getClipData();
    
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
    
                    if (dataString != null)
                        results = new Uri[]{Uri.parse(dataString)};
                }
            }
            if (results != null) {
                mUploadCallbackAboveL.onReceiveValue(results);
                mUploadCallbackAboveL = null;
            } else {
                results = new Uri[]{imageUri};
                mUploadCallbackAboveL.onReceiveValue(results);
                mUploadCallbackAboveL = null;
            }
    
            return;
        }
    
    
        private void take() {
    //        int hasCameraContactsPermission = ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA);
    //        if (hasCameraContactsPermission != PackageManager.PERMISSION_GRANTED) {
    //            String[] PERMISSIONS_STORAGE = {
    //                    Manifest.permission.CAMERA};
    //
    //            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE,
    //                    1);
    //        }
    //
    //        int hasWriteContactsPermission = ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE);
    //        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
    //            String[] PERMISSIONS_STORAGE = {
    //                    Manifest.permission.WRITE_EXTERNAL_STORAGE};
    //
    //            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE,
    //                    1);
    //        }
            Log.i(TAG,""+Environment.getExternalStorageDirectory().getPath());
            // 指定拍照存储位置的方式调起相机
            String filePath = Environment.getExternalStorageDirectory() + File.separator
                    + Environment.DIRECTORY_PICTURES + File.separator;
            String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
            file = new File(filePath + fileName);
            imageUri = Uri.fromFile(file);
    
            //调用照相机和浏览图片库代码
    //        Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    //        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    //
    //        Intent Photo = new Intent(Intent.ACTION_PICK,
    //                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    //
    //        Intent chooserIntent = Intent.createChooser(Photo, "Image Chooser");
    //        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
    //        startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
    
            //调用系统相机,此代码在android 7.0以上有问题,需要在onCreate方法加入StrictMode.VmPolicy.Builder解决办法
    //        Intent intentCamera = new Intent();
    //        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    //            intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件
    //        }
    //        intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
    //        //将拍照结果保存至photo_file的Uri中,不保留在相册中
    //        intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    //        startActivityForResult(intentCamera, FILECHOOSER_RESULTCODE);
    
            //Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            //captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    
    
            //兼容android 7.0+版本的照相机调用代码
            Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (captureIntent.resolveActivity(getPackageManager()) != null) {
                 /*获取当前系统的android版本号*/
                int currentapiVersion = android.os.Build.VERSION.SDK_INT;
                Log.e("currentapiVersion","currentapiVersion====>"+currentapiVersion);
                if (currentapiVersion<24){
                    captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                    //startActivityForResult(intent, FILECHOOSER_RESULTCODE);
                }else {
                    ContentValues contentValues = new ContentValues(1);
                    contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
                    Uri uri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
                    captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                    //startActivityForResult(intent, FILECHOOSER_RESULTCODE);
                }
            } else {
                Toast.makeText(this, "照相机不存在", Toast.LENGTH_SHORT).show();
                return;
            }
    
            Intent Photo = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            Intent chooserIntent = Intent.createChooser(Photo, "Image Chooser");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
            startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
        }
    
        private void updatePhotos() {
            // 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            intent.setData(imageUri);
            sendBroadcast(intent);
        }
    
        //这里检查了存储权限,如果有需要,可以先检查下相机权限。  此方法用户对权限禁止或允许 未做判断,需要进一步完善
        private void checkAppPermission(){
            int permission = ActivityCompat.checkSelfPermission(this,
                    Manifest.permission.READ_EXTERNAL_STORAGE);
    
            if (permission != PackageManager.PERMISSION_GRANTED) {
                String[] PERMISSIONS_STORAGE = {
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE};
    
                final int REQUEST_EXTERNAL_STORAGE = 1;
                ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE,
                        REQUEST_EXTERNAL_STORAGE);
            }
        }
    }

     AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.gtj.admin.gapt" >
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
    
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme" >
            <activity android:name=".MainActivity" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity><!-- ATTENTION: This was auto-generated to add Google Play services to your project for
         App Indexing.  See https://g.co/AppIndexing/AndroidStudio for more information. -->
            <meta-data
                android:name="com.google.android.gms.version"
                android:value="@integer/google_play_services_version" />
        </application>
    
    </manifest>
  • 相关阅读:
    win32 tcp文件传输客户端
    Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析
    和菜鸟一起深入学习国嵌实验之vim常用命令
    和菜鸟一起深入学习国嵌实验之linux常用命令
    和菜鸟一起深入学习国嵌实验之文件编程
    和菜鸟一起深入学习国嵌实验之gcc分步编译&&gdb调试
    和菜鸟一起深入学习国嵌实验之简单Makefile
    获得创建表脚本
    oralce中获得创建脚本
    所有数据库连接字符串
  • 原文地址:https://www.cnblogs.com/coolzdp/p/9968865.html
Copyright © 2011-2022 走看看