两篇起步使用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>

真正可用的安卓webview html图片上传限制突破处理(拍照+相册都可以用)的更多相关文章

  1. vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理

    一.前言 三年.net开发转前端已经四个月了,前端主要用webpack+vue,由于后端转过来的,前端不够系统,希望分享下开发心得与园友一起学习. 图片的上传之前都是用的插件(ajaxupload), ...

  2. MUI 单个图片上传预览(拍照+系统相册):先选择->预览->上传提交

    1 html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  3. [Nginx 2] form表单提交,图片上传

    导读:昨晚恶补了一些Nginx服务器的东西,从整体上对Nginx有一个初步的了解.上午去找师哥问了问目前项目中的使用情况,然后就开始上传图片了.这里就简单总结整理一下今天的成果,以后接着提升.简单粗暴 ...

  4. hybird app项目实例:安卓webview中HTML5拍照图片上传

    应用的平台环境:安卓webview: 涉及的技术点: (1) <input type="file" > :在开发中,安卓webview默认点击无法调用文件选择与相机拍照 ...

  5. java接受安卓及ios App上传的图片,并保存到阿里OSS

    做后台的时候,写了两个方法,分别用来获取安卓和苹果IOS端上传的头像,保存到阿里云OSS图片存储服务器上.(SMM框架) 安卓及H5版本: /** * 上传用户头像 */ @RequestMappin ...

  6. Android WebView 上传各种文件(包括拍照 录像 录音 文件 音乐 等,用到图片或拍照的,可以参考下)

    我也是从网上扒下来的,经过多次实验,找到了个好用的.网上能搜到最多的也就是这个解决方案,我英文不好,也没仔细研究,但大多数都是出自这: http://stackoverflow.com/questio ...

  7. 安卓自定义View实现图片上传进度显示(仿QQ)

    首先看下我们想要实现的效果如下图(qq聊天中发送图片时的效果): 再看下图我们实现的效果: 实现原理很简单,首先我们上传图片时需要一个进度值progress,这个不管是自己写的上传的方法还是使用第三方 ...

  8. 一个简单的安卓+Servlet图片上传例子

    例子比较 简单,服务端为Java Web Servlet,doPost方法中接收图片并保存,然后将保存的图片名返回给客户端,关键代码: @SuppressWarnings("deprecat ...

  9. HTML5笔记:跨域通讯、多线程、本地存储和多图片上传技术

    最近做项目在前端我使用了很多新技术,这些技术有bootstrap.angularjs,不过最让我兴奋的还是使用了HTML5的技术,今天我想总结一些HTML5的技术,好记性不如烂笔头,写写文章可以很好的 ...

随机推荐

  1. SQL 性能优化 总结

    SQL 性能优化 总结 (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving ...

  2. shullfe机制详解

    一.shuffle机制概述 shuffle机制就是发生在MR程序中,Mapper之后,Reducer之前的一系列分区排序的操作.shuffle的作用是为了保证Reducer收到的数据都是按键排序的. ...

  3. CodeForces 959E Mahmoud and Ehab and the xor-MST (MST+找规律)

    <题目链接> 题目大意: 给定一个数n,代表有一个0~n-1的完全图,该图中所有边的边权为两端点的异或值,求这个图的MST的值. 解题分析: 数据较大,$10^{12}$个点的完全图,然后 ...

  4. C#からネイティブDLLを呼び出す場合のVSからのデバッグのジレンマを解決する

    「C#を使う最大のメリットって.やっぱり.Visual Studioですよね!」って自信を持って言いたいですね. という心境ではあるんですが.私の仕事はどっちかというとC++よりなので.どうしても.D ...

  5. Tomcat 本地运行正常,服务器部署后乱码问题

    Tomcat 在本地运行项目没啥问题,可是部署到服务器后就会发现有乱码的问题,这问题还是一半一半的,有些有,有些没有,这不是接收数据的时候会出现的乱码,是后台管理的页面中文乱码,我也是醉了, 把解决方 ...

  6. centos官网下载地址

    CentOS 7官方下载地址:https://www.centos.org/download/ 源自博友的博客:https://blog.csdn.net/yf9595/article/details ...

  7. 【树状数组】区间出现偶数次数的异或和(区间不同数的异或和)@ codeforce 703 D

    [树状数组]区间出现偶数次数的异或和(区间不同数的异或和)@ codeforce 703 D PROBLEM 题目描述 初始给定n个卡片拍成一排,其中第i个卡片上的数为x[i]. 有q个询问,每次询问 ...

  8. 马昕璐201771010118《面向对象程序设计(java)》第七周学习总结

    第一部分:理论知识学习部分 Java用于控制可见性的4个访问权限修饰符: 1.private(只有该类可以访问) 2.protected(该类及其子类的成员可以访问,同一个包中的类也可访问) 3.pu ...

  9. 11. cookie_session_原生ajax_readyState的值_同源策略_跨域_jsonp的使用

    1. cookie 浏览器存储技术.(服务器将少量数据交于浏览器存储管理) 作用: 存储数据, 解决 http 协议无状态问题 工作流程: 浏览器发送请求给服务器,请求登录 服务器返回响应给浏览器,此 ...

  10. ASP.NET 创建WebService——简单例子

    Web service是一个基于可编程的web的应用程序,用于开发分布式的互操作的应用程序,也是一种web服务 WebService的特性有以下几点: 1.使用XML(标准通用标记语言)来作为数据交互 ...