Usar una vista web para navegar por la galería de fotos

Min SDK API 15 

Hola,

Utilizo una vista web que tiene un botón que explorará la galería de fotos de las aplicaciones.

Sin embargo, cuando se hace clic en el botón en la vista web, no pasa nada.

La url tiene el formato:

 https://www.xxxxxxxxxxx 

He agregado los siguientes permisos:

     

Tengo un fragmento que cargará la vista web en el método onCreateView (solo fragmento) con javascript habilitado.

 if(!message.isEmpty()) { WebView webView = (WebView)view.findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webView.setWebViewClient(new WebViewClient()); webView.loadUrl(message); } 

He creado una página html simple para probar:

     Test Android Popup     

Por lo tanto, la URL se cargará en la vista web. La vista web muestra un botón en el que el usuario hará clic para explorar las fotos en su galería.

La vista web se ve así: enter image description here

Ninguno de los botones funciona cuando hago clic en ellos.

Muchas gracias por las sugerencias,

Este fragmento de código funciona para <4.3. Sin embargo, 4.4 y 5.0 falla.

  webView.setWebChromeClient(new WebChromeClient() { /* Open File */ public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { mImageFilePath = uploadMsg; Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); startActivityForResult(intent, FILECHOOSER_RESULTCODE); } public void openFileChooser(ValueCallback uploadMsg, String acceptType) { mImageFilePath = uploadMsg; Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); startActivityForResult(intent, FILECHOOSER_RESULTCODE); } }); 

crea este archivo y colócalo en tu carpeta de activos: webdemo.html

     title   

Web View Demo



File Uri:
File Path:

concéntrate en el javascript escrito aquí.

escriba su actividad de la siguiente manera: WebViewDemo.java

 public class WebViewDemo extends Activity { private WebView webView; final int SELECT_PHOTO = 1; @SuppressLint("SetJavaScriptEnabled") public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.show_web_view); webView = (WebView) findViewById(R.id.webView1); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setLoadWithOverviewMode(true); // Other webview settings webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY); webView.setScrollbarFadingEnabled(false); webView.getSettings().setBuiltInZoomControls(true); webView.getSettings().setPluginState(PluginState.ON); webView.getSettings().setAllowFileAccess(true); webView.getSettings().setSupportZoom(true); webView.addJavascriptInterface(new MyJavascriptInterface(this), "Android"); webView.loadUrl("file:///android_asset/webdemo.html"); } class MyJavascriptInterface { Context mContext; /** Instantiate the interface and set the context */ MyJavascriptInterface(Context c) { mContext = c; } /** Show a toast from the web page */ @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } @JavascriptInterface public String choosePhoto() { // TODO Auto-generated method stub String file = "test"; Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); startActivityForResult(photoPickerIntent, SELECT_PHOTO); return file; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { switch (requestCode) { case SELECT_PHOTO: if (resultCode == RESULT_OK) { Uri selectedImage = intent.getData(); webView.loadUrl("javascript:setFileUri('" + selectedImage.toString() + "')"); String path = getRealPathFromURI(this, selectedImage); webView.loadUrl("javascript:setFilePath('" + path + "')"); } } } public String getRealPathFromURI(Context context, Uri contentUri) { Cursor cursor = null; try { String[] proj = { MediaStore.Images.Media.DATA }; cursor = context.getContentResolver().query(contentUri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } finally { if (cursor != null) { cursor.close(); } } } } 

usa este fragmento de código y mira si funciona.

esta captura de pantalla a continuación está tomada de un dispositivo Android 4.4 Kitkat.

mira esta captura de pantalla

No sé si esta solución te funciona o no. Puede ser solo una solución o un avance para usted. Espero que una parte de esto ayude.

Desafortunadamente, como dijo el usuario Slartibartfast en uno de los comentarios a su pregunta, el tipo de entrada “archivo” no funcionará en 4.4 dispositivos. Existe un problema en el código de Google que establece que se trata de un comportamiento previsto (Estado: WorkingAsIntended).

Aun así, el código que proporcionó funciona en 4.4.4 (probado en una tableta Nexus 7) y en versiones de <4.4 os.

En 5.0, agregaron un método documentado para hacer esto. Estoy usando el siguiente código:

 mWebView.setWebChromeClient(new WebChromeClient() { // For Android < 3.0 - undocumented method @SuppressWarnings("unused") public void openFileChooser( ValueCallback uploadMsg ) { openFileChooser( uploadMsg, "" ); } // For Android 3.0+ - undocumented method public void openFileChooser( ValueCallback uploadMsg, String acceptType ) { mUploadCallback = uploadMsg; openFileChooserActivity(); } // For Android > 4.1 - undocumented method @SuppressWarnings("unused") public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture){ openFileChooser( uploadMsg, "" ); } // For Android > 5.0 public boolean onShowFileChooser (WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { mUploadCallbackLollipop = filePathCallback; openFileChooserActivity(); return true; } }); 

Tome nota del parámetro de callback cambiado para> 5.0: de ValueCallback a ValueCallback .

Entonces, para> = 4.4 y <4.4.4, debe implementar su propio mecanismo de carga de archivos. Algunas sugerencias:

  • verifique con javascript la versión del sistema operativo Android y proporcione un donde funciona. En las versiones 4.4 crea un elemento html con tu propio esquema de url (como dijo Sushant, por ejemplo,

    ). A continuación, puede verlo en shouldOverrideUrlLoading y llamar a una función javascript desde java con la ruta del archivo, pero no podrá acceder al contenido de su archivo. Para archivos pequeños, puede pasar el contenido del archivo en base64, como un parámetro a su función javascript, pero para archivos más grandes, seguramente obtendrá una excepción OutOfMemory.

  • puede hacer los pasos anteriores pero manejar la carga del archivo en java y proporcionar solo la ruta a la función javascript. Un botón con submit podría hacer uso de lo que dijo Amrut Bidri para que lo cargue en java.

Entonces, como conclusión, veo dos opciones para las versiones de sistema operativo entre 4.4 y 4.4.4: o use javascript para cargar el archivo (problemas de memoria) o cárguelo en Java e implemente su propio mecanismo de comunicación entre su aplicación y la vista web. Para ambos, debes tener acceso a la página web que estás cargando en la vista web.

Utilicé el método de carga de JavaScript, ya que estamos usando archivos pequeños y fue un poco más rápido de implementar:

 public boolean shouldOverrideUrlLoading(WebView view, String url) { ... else if (url.startsWith(UPLOAD_FILE_URL_PREFIX)) { openFileChooserActivity(); return true; } return false; } 

En el resultado de la actividad, hago algo como esto para las versiones 4.4 (la función javascript insertFileForUpload maneja la carga del archivo):

 private void invokeJavascriptWithFileContent(Uri fileUri) { String fileContentInBase64 = readAndConvertFileToBase64(fileUri); if (!fileContentInBase64.isEmpty()) { String fileMimeType = getMimeType(activity, fileUri); String fileName = getFileName(activity, fileUri); // invoke javascript String js = String.format("javascript:insertFileForUpload(\"%s\",\"%s\",\"%s\")", fileName, fileMimeType, fileContentInBase64 ); mWebView.loadUrl(js); } } public static String getMimeType(Context context, Uri fileUri) { ContentResolver cR = context.getContentResolver(); MimeTypeMap mime = MimeTypeMap.getSingleton(); String type = mime.getExtensionFromMimeType(cR.getType(fileUri)); return type; } 

Además, con respecto a https://github.com/delight-im/Android-AdvancedWebView , parece que la carga de archivos funciona, pero dicen: ‘Las cargas de archivos se manejan automáticamente (verifique la disponibilidad con AdvancedWebView.isFileUploadAvailable ())’ y ‘isFileUploadAvailable ‘contiene el siguiente código:

 /** * Returns whether file uploads can be used on the current device (generally all platform versions except for 4.4) * * @return whether file uploads can be used */ public static boolean isFileUploadAvailable() { return isFileUploadAvailable(false); } /** * Returns whether file uploads can be used on the current device (generally all platform versions except for 4.4) * * On Android 4.4.3/4.4.4, file uploads may be possible but will come with a wrong MIME type * * @param needsCorrectMimeType whether a correct MIME type is required for file uploads or `application/octet-stream` is acceptable * @return whether file uploads can be used */ public static boolean isFileUploadAvailable(final boolean needsCorrectMimeType) { if (Build.VERSION.SDK_INT == 19) { final String platformVersion = (Build.VERSION.RELEASE == null) ? "" : Build.VERSION.RELEASE; return !needsCorrectMimeType && (platformVersion.startsWith("4.4.3") || platformVersion.startsWith("4.4.4")); } else { return true; } } 

Entonces, es posible que tenga los mismos problemas con la vista web normal, pero no he probado la biblioteca, así que no puedo decirlo.

Pude haber creado una confusión de respuestas, pero espero que puedas encontrar algo útil.

Bueno, puedes lograrlo así

  webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.equals("alert://alert")) { Toast.makeText(this, "alert", Toast.LENGTH_LONG).show(); } else if (url.equals("choose://image")) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); startActivityForResult(intent, FILECHOOSER_RESULTCODE); } return true; } }); 

y tu html debería ser así

     Test Android Popup    

A través de este código podría tomar la ruta del archivo móvil, solo que no puedo subir el archivo en php. A continuación está el código php que estoy usando:

 $arquivo = $_POST['lblpath']; $url = "file:///storage/external_SD/fotos/IMG10022.jpg"; //url da imagem que venha de um textField //PEGA INFORMAÇÕES DA IMAGEM $file_info = getimagesize($url); //VERIFICA EXTENSÃO DA IMAGEM if ($file_info['mime'] == "image/jpeg") $img = imagecreatefromjpeg($url); else if ($file_info['mime'] == "image/gif") $img = imagecreatefromgif($url); else if ($file_info['mime'] == "image/png") $img = imagecreatefrompng($url); $altura = $file_info[1]; //PASSA AS MEDIDAS PARA A IMAGEM $x = imagesx($img); $y = imagesy($img); $largura = ($altura * $x)/$y; //CRIA A IMAGEM $nova = imagecreatetruecolor($largura, $altura); imagealphablending( $nova, false ); imagesavealpha( $nova, true ); imagecopyresampled($nova, $img, 0, 0, 0, 0, $largura, $altura, $x, $y); //NOME DA IMAGEM $imgName = end(explode("/", $url)); //LOCAL PARA SALVAR $pasta = "images/"; // defina sua path $local = $pasta . $imgName; //SALVA NOVA IMAGEM if ($file_info['mime'] == "image/jpeg") imagejpeg($nova, $local, 100); else if ($file_info['mime'] == "image/png") imagepng($nova, $local, 9); //DESTROI ELEMENTOS imagedestroy($img); imagedestroy($nova);