Android 通过WebView的文件上传表单不';t使用相机(牛轧糖)的即时点击功能

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

我叫丹尼尔,正在学习Android应用程序开发

使用下面的代码,可以通过文件浏览选择附加文件,但我还需要调用本机android camera应用程序,用相机拍摄即时照片,并提供上传表单到文件的正确路径

在一些测试中,我可以记录文件的路径,它显示了一个有效的路径,因为我到了那里,可以看到创建的照片

我在网络上尝试了几种解决方案,但找不到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);
    }
}
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>