Android 通过WebView的文件上传表单不';t使用相机(牛轧糖)的即时点击功能
我叫丹尼尔,正在学习Android应用程序开发 使用下面的代码,可以通过文件浏览选择附加文件,但我还需要调用本机android camera应用程序,用相机拍摄即时照片,并提供上传表单到文件的正确路径 在一些测试中,我可以记录文件的路径,它显示了一个有效的路径,因为我到了那里,可以看到创建的照片 我在网络上尝试了几种解决方案,但找不到API 25及以上版本的任何特定解决方案,这似乎是问题的原因Android 通过WebView的文件上传表单不';t使用相机(牛轧糖)的即时点击功能,android,webview,upload,camera,android-7.0-nougat,Android,Webview,Upload,Camera,Android 7.0 Nougat,我叫丹尼尔,正在学习Android应用程序开发 使用下面的代码,可以通过文件浏览选择附加文件,但我还需要调用本机android camera应用程序,用相机拍摄即时照片,并提供上传表单到文件的正确路径 在一些测试中,我可以记录文件的路径,它显示了一个有效的路径,因为我到了那里,可以看到创建的照片 我在网络上尝试了几种解决方案,但找不到API 25及以上版本的任何特定解决方案,这似乎是问题的原因 package br.com.fahrenheitdlp.ouvidoria; import and
package br.com.fahrenheitdlp.ouvidoria;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private WebView webView;
private static final String TAG = MainActivity.class.getSimpleName();
private String mCM;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private final static int FCR = 1;
private final int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
@SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
// Chamando o teste de permissões
checkingForPermissions();
// Ajustando o WebView
webView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setUseWideViewPort(true);
webSettings.setDomStorageEnabled(true);
if (Build.VERSION.SDK_INT >= 21) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}else if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}else if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 19) {
webView.requestFocus();
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webView.setVerticalScrollBarEnabled(false);
webView.setWebViewClient(new Callback());
// Carrega a página da ouvidoria
webView.loadUrl("http://suporte.mesquita.rj.gov.br/ouvidoriaweb/");
// webView.loadUrl("http://files.fm");
// Configura o upload de arquivos apartir do armazenamento externo ou câmera
webView.setWebChromeClient(new WebChromeClient(){
//For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
startActivityForResult(Intent.createChooser(i,"Escolha um arquivo"), FCR);
}
// For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
public void openFileChooser(ValueCallback uploadMsg, String acceptType){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
startActivityForResult(Intent.createChooser(i, "File Browser"), FCR);
}
//For Android 4.1+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
startActivityForResult(Intent.createChooser(i, "File Chooser"), FCR);
}
//For Android 5.0+
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams){
if (mUMA != null){
mUMA.onReceiveValue(null);
}
mUMA = filePathCallback;
Intent takePictureIntent = new Intent();
takePictureIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(getPackageManager()) != null){
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCM);
} catch (IOException ex) {
Log.e(TAG, "Image file creation failed", ex);
}
String authorities = getApplicationContext().getPackageName() + ".fileprovider";
Uri imageUri = FileProvider.getUriForFile(MainActivity.this, authorities, photoFile);
Log.v(TAG, imageUri.toString());
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
Log.d(TAG, "TakePicture não é NULL");
intentArray = new Intent[]{takePictureIntent};
} else {
Log.d(TAG, "TakePicture é NULL");
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Escolha um arquivo");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, FCR);
return true;
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) {
if (requestCode != FCR || mUMA == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (data == null || data.getDataString() == null) {
// If there is not data, then we may have taken a photo
if (mCM != null) {
results = new Uri[]{Uri.parse(mCM)};
}
} else {
String dataString = data.getDataString();
if (dataString != null) {
results = new Uri[]{Uri.parse(dataString)};
}
}
}
mUMA.onReceiveValue(results);
mUMA = null;
} else {
if (requestCode == FCR) {
if (null == mUM) return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
mUM.onReceiveValue(result);
mUM = null;
}
}
// ScanFile so it will be appeared on Gallery
Uri imageUri = Uri.parse(mCM);
MediaScannerConnection.scanFile(MainActivity.this,
new String[]{imageUri.getPath()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
}
// Criando um arquivo de imagem
private File createImageFile() throws IOException{
@SuppressLint("SimpleDateFormat")
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date());
String imageFileName = "OW_"+timeStamp+"_";
//File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File storageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "Camera");
File imageFile = File.createTempFile(
imageFileName,
".jpg",
storageDir
);
mCM = imageFile.getAbsolutePath();
return imageFile;
}
// Função para checagem de permissões
private void checkingForPermissions() {
if (Build.VERSION.SDK_INT < 23 && Build.VERSION.SDK_INT >= 16) {
int hasReadExtPermission = ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
int hasCameraPermission = ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CAMERA);
if (hasReadExtPermission != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showMessageOKCancel("You need to allow access to Contacts",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
}
if (hasCameraPermission != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.CAMERA)) {
showMessageOKCancel("You need to allow access to Contacts",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CAMERA},
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
}
}
} else {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE))
permissionsNeeded.add("Cartão de Memória");
if (!addPermission(permissionsList, Manifest.permission.CAMERA))
permissionsNeeded.add("Câmera");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Será necessário usar Rationale
String message = "Para anexar arquivos, por favor conceda acesso ao(à): " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
}
}
// Função para o agrupamento das permissões que não foram cedidas
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Checa o uso do Rationale
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
{
Map<String, Integer> perms = new HashMap<String, Integer>();
// Inicializando o HashMap perms
perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
// Preenchendo com os resultados
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Determinando as permissões já cedidas
if (perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|| perms.get(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// Alguma das permissões foi negada em algum momento
Toast.makeText(MainActivity.this, "Alguma permissão foi negada", Toast.LENGTH_SHORT)
.show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
// Cuidado do alerta de permissão
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(MainActivity.this)
.setMessage(message)
.setPositiveButton("Permitir", okListener)
.setNegativeButton("Negar", null)
.create()
.show();
}
// Callback do WebView
private class Callback extends WebViewClient {
@SuppressWarnings("deprecation")
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
Toast.makeText(getApplicationContext(), "Something Went Wrong!", Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event){
if(event.getAction() == KeyEvent.ACTION_DOWN){
switch(keyCode){
case KeyEvent.KEYCODE_BACK:
if(webView.canGoBack()){
webView.goBack();
}else{
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
}
package br.com.fahrenheitdlp.ouvidoria;
导入android.Manifest;
导入android.annotation.SuppressLint;
导入android.app.Activity;
导入android.app.AlertDialog;
导入android.content.DialogInterface;
导入android.content.Intent;
导入android.content.pm.PackageManager;
导入android.content.res.Configuration;
导入android.media.MediaScannerConnection;
导入android.net.Uri;
导入android.os.Build;
导入android.os.Bundle;
导入android.os.Environment;
导入android.provider.MediaStore;
导入android.support.annotation.NonNull;
导入android.support.v4.app.ActivityCompat;
导入android.support.v4.content.ContextCompat;
导入android.support.v4.content.FileProvider;
导入android.support.v7.app.AppActivity;
导入android.util.Log;
导入android.view.KeyEvent;
导入android.view.view;
导入android.webkit.ValueCallback;
导入android.webkit.WebChromeClient;
导入android.webkit.WebResourceError;
导入android.webkit.WebResourceRequest;
导入android.webkit.WebSettings;
导入android.webkit.WebView;
导入android.webkit.WebViewClient;
导入android.widget.Toast;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
导入java.io.File;
导入java.io.IOException;
导入java.text.simpleDataFormat;
导入java.util.Date;
公共类MainActivity扩展了AppCompatActivity{
私有网络视图;
私有静态最终字符串标记=MainActivity.class.getSimpleName();
私有字符串mCM;
私人财产;
私人资产管理公司;
专用最终静态整数FCR=1;
私有最终整数请求\代码\请求\多个权限=124;
@SuppressLint({“SetJavaScriptEnabled”,“ErrorViewCast”})
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
//许可证测试
检查权限();
//Ajustando网络视图
webView=(webView)findViewById(R.id.webView1);
WebSettings WebSettings=webView.getSettings();
setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
setAllowFileAccessFromFileURLs(true);
setAllowUniversalAccessFromFileURL(true);
webSettings.setUseWideViewPort(true);
webSettings.setDomStorageEnabled(true);
如果(Build.VERSION.SDK_INT>=21){
webView.setLayerType(View.LAYER\u TYPE\u硬件,空);
webSettings.setMixedContentMode(webSettings.MIXED内容总是允许);
}else if(Build.VERSION.SDK_INT>=19){
webView.setLayerType(View.LAYER\u TYPE\u硬件,空);
}else if(Build.VERSION.SDK_INT>=14&&Build.VERSION.SDK_INT<19){
requestFocus();
webView.setLayerType(View.LAYER\u TYPE\u软件,空);
}
webView.setVerticalScrollBarEnabled(false);
setWebViewClient(新回调());
//卡雷加奥维多利亚酒店
webView.loadUrl(“http://suporte.mesquita.rj.gov.br/ouvidoriaweb/");
//webView.loadUrl(“http://files.fm");
//Armzenameto externo ou c–mera公寓的上传配置
setWebView.WebChromeClient(新WebChromeClient(){
//适用于Android 3.0+
public void openFileChooser(ValueCallback uploadMsg){
mUM=上传msg;
意向i=新意向(意向.行动\u获取\u内容);
i、 addCategory(意图。类别可打开);
i、 集合类型(“*/*”);
startActivityForResult(Intent.createChooser(i,“Escolha um arquivo”),FCR);
}
//对于Android 3.0+,上述方法在某些Android 3+版本中不受支持,在这种情况下,我们使用此方法
public void openFileChooser(ValueCallback uploadMsg,String acceptType){
mUM=上传msg;
意向i=新意向(意向.行动\u获取\u内容);
i、 addCategory(意图。类别可打开);
i、 集合类型(“*/*”);
startActivityForResult(Intent.createChooser(i,“文件浏览器”),FCR);
}
//适用于Android 4.1+
public void openFileChooser(ValueCallback uploadMsg、字符串接受类型、字符串捕获){
mUM=上传msg;
意向i=新意向(意向.行动\u获取\u内容);
i、 addCategory(意图。类别可打开);
i、 集合类型(“*/*”);
startActivityForResult(Intent.createChooser(i,“文件选择器”),FCR);
}
//适用于Android 5.0+
公共布尔onShowFileChooser(WebView、WebView、ValueCallback、filePathCallback、,
WebChromeClient.FileChooserParams文件选择器参数){
如果(mUMA!=null){
mUMA.onReceiveValue(空);
}
mUMA=filePathCallback;
Intent takePictureIntent=新Intent();
takePictureContent.setAction(MediaStore.ACTION\u IMAGE\u CAPTURE);
if(takePictureContent.resolveActivity(getPackageManager())!=null){
文件photoFile=null;
试一试{
photoFile=createIm
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="br.gov.rj.mesquita.ouvidoriaweb">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>
<uses-feature android:name="android.hardware.camera"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="Ouvidoria Web"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:name=".App"
tools:ignore="AllowBackup" >
<activity
android:name=".SplashActivity"
android:label="Ouvidoria Web"
android:screenOrientation="portrait"
android:theme="@style/SplashTheme" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity" />
<provider
android:authorities="${applicationId}.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
</manifest>