我的名字是Daniel,我正在学习Android App Dev。
使用下面的代码可以附加一个文件通过文件浏览选择它,但我还需要调用本机Android相机应用程序与相机拍摄即时照片,并提供上传表格正确的路径文件。
在某些测试中,我可以log.v指向文件的路径,该路径显示了一个有效的路径,因为到达那里并且可以看到创建的照片。
我已在网络上尝试了多种解决方案,无法找到API 25及更高版本的特定内容,这似乎是问题的原因。
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);
}
}
这是我的清单:
<?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>
先谢谢大家!
祝你好运, 丹尼尔。