2016-01-20 20 views
14

Ziel: in der Lage sein, eine Datei eines beliebigen Typs an eine <input type="file" /> in einer webview in Android 4.1+ anhängen. (Android 5+ ist in Ordnung)Dateiname fehlen für openFileChooser Android 4.4.4

Ich setzte openFileChooser, wie ich sah, basierend auf einigen Beispielen, die ich gefunden habe. Es funktioniert auf 4.1, aber nicht auf 4.4.4, wobei die angehängten Dateien nicht korrekt ihren Dateinamen haben.
Statt als Dateiname des letzten Weg der intent.mData Rückkehr zu onActivityResult, .e.g für einen mData Wert von content://com.android.providers.downloads.documents/document/2 gesetzt ist, wird der Dateiname 2 -ohne Erweiterung der seinen Kurs-während des Name image.png sein sollte.

Was kann ich tun, um es zu beheben? Würde es in meinem Code ein Problem geben?

ich meine Tests auf einem Emulator: Galaxy Nexus, API 19, Ziel: Standard
Siehe Code unten.

webView.setWebChromeClient(new WebChromeClient() { 
    public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) { 
     if (UseWebViewActivity.this.valueCallback != null) { 
      UseWebViewActivity.this.valueCallback.onReceiveValue(null); 
     } 
     UseWebViewActivity.this.valueCallback = valueCallback; 

     Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); 
     contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); 
     contentSelectionIntent.setType("*/*"); 
     startActivityForResult(Intent.createChooser(contentSelectionIntent, 
      getString(R.string.file_chooser_title)), INPUT_FILE_REQUEST_CODE); 
    } 
}); 

// ... 

protected void onActivityResult(int requestCode, int resultCode, Intent intent) { 
    if (requestCode == INPUT_FILE_REQUEST_CODE && valueCallback != null) { 
     Uri result = null; 
     if (resultCode == Activity.RESULT_OK) { 
      result = intent.getData(); 
     } 
     valueCallback.onReceiveValue(result); 
     valueCallback = null; 
    } 
} 

Antwort

4

Versuchen aFileChooser mit Komplikationen, die mit API-Ebene Kompatibilitäten zu vermeiden (die Bibliothek hat es behandelt):

aFileChooser ist ein Android-Library Project, das den Prozess präsentieren eine Dateiauswahl vereinfacht auf Android 2.1 und höher.

Intents bieten die Möglichkeit, zur Inhaltsauswahl in Drittanbieter-App-Komponenten einzubinden. Dies funktioniert gut für Mediendateien, aber wenn Sie möchten, dass Benutzer in der Lage sind, eine beliebige Datei auszuwählen, muss eine vorhandene Datei-Explorer-App installiert sein. Da viele Android-Geräte keine Stock File Explorers haben, muss der Entwickler den Benutzer oft anweisen, selbst zu installieren oder selbst zu erstellen. aFileChooser löst dieses Problem.

Eigenschaften:

Full file explorer 
Simplify GET_CONTENT Intent creation 
Hooks into Storage Access Framework 
Determine MIME data types 
Follows Android conventions (Fragments, Loaders, Intents, etc.) 
Supports API 7+ 

Überprüfen Sie die readme.md auf The repo's GitHub page für die Einrichtung und Gebrauchsanweisungen.

+0

Möchten Sie wissen, wie es zu tun, ohne die Verwendung von Bibliotheken? – oldergod

+0

Sie Vielleicht möchten Sie den Quellcode dieser Bibliothek durchsuchen und sehen, wie sie das gemacht haben.Repo-Link in der Antwort: – AndroidMechanic

2

Android 4.1 und 4.4 haben unterschiedliche Funktionen hier seit Storage Access Framework in Android 4.4 eingeführt wurde (API-Ebene 19). Um den Dateinamen abzurufen, können Sie so etwas wie dies versuchen:

Uri uri = intent.getData(); 
    File imageFile = new File(uri); 
    if(imageFile.exists()){ 
    String name = imageFile.getName(); 
    } 
+0

Ich habe auch einen Weg gefunden, den Dateinamen abzurufen, habe aber keinen Weg gefunden, ihn zu setzen o die ''. Kennst du irgendwelche ? – oldergod

+0

beziehen sich auf [dies] (http://stackoverflow.com/questions/5907369/file-upload-in-webview) und [dies] (http://stackoverflow.com/questions/19882331/html-file-input- in-android-webview-android-4-4-kitkat) frage. – Piyush

5

Das Problem ist in der onActivityResult() -Methode für KitKat, die die URI zurückgibt. Sie müssen den Realpath der Imagedatei abrufen.

Beachten Sie, wie ich den wahren Weg des IMG erhalten durch den Aufruf:

KitkatPath = Uri.parse ("file: //" + getPath (MobilestyxAppActivity.this, Ergebnis)); in der onActivityResult().

Sie müssen die Zeichenfolge "file: //" hinzufügen, damit es funktioniert.

PS: Ich habe den Code aus verschiedenen Quellen gesammelt und modifiziert.

Schauen Sie auf meinen Code, der für Kitkat & Lolipop und andere niedrige Versionen von Android funktioniert.

/** CODE FOR FILE UPLOAD*/ 
private static final int INPUT_FILE_REQUEST_CODE = 1; 
private static final int FILECHOOSER_RESULTCODE = 1; 
private ValueCallback<Uri> mUploadMessage; 
private Uri mCapturedImageURI = null; 
private ValueCallback<Uri[]> mFilePathCallback; 
private String mCameraPhotoPath; 
Uri KitkatPath ; 

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 



    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) { 
      super.onActivityResult(requestCode, resultCode, data); 
      return; 
     } 
     Uri[] results = null; 
     // Check that the response is a good one 
     if (resultCode == Activity.RESULT_OK) { 
      if (data == null) { 
       // If there is not data, then we may have taken a photo 
       if (mCameraPhotoPath != null) { 
        results = new Uri[]{Uri.parse(mCameraPhotoPath)}; 
       } 
      } else { 
       String dataString = data.getDataString(); 
       if (dataString != null) { 
        results = new Uri[]{Uri.parse(dataString)}; 
       } 
      } 
     } 
     mFilePathCallback.onReceiveValue(results); 
     mFilePathCallback = null; 
    } 




    else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { 
     System.out.println("In KitKat Condition"); 

     if (requestCode != FILECHOOSER_RESULTCODE || mUploadMessage == null) { 
      System.out.println("In != Null"); 
      super.onActivityResult(requestCode, resultCode, data); 
      return; 
     } 
     if (requestCode == FILECHOOSER_RESULTCODE) { 

      System.out.println("requestCode == FileChooser ResultCode"); 
      if (null == this.mUploadMessage) { 
       System.out.println("In null == this.mUploadMessage"); 
       return; 
      } 
      Uri result = null; 
      try { 
       if (resultCode != RESULT_OK) { 

        result = null; 
       } else { 

        //newcode 

        // retrieve from the private variable if the intent is null 
        result = data == null ? mCapturedImageURI : data.getData(); 

        KitkatPath = Uri.parse("file://"+getPath(MobilestyxAppActivity.this, result)); 
        System.out.println("KitkatPath== "+KitkatPath); 
        System.out.println("result = "+result); 
       } 
      } catch (Exception e) { 
       // Toast.makeText(getApplicationContext(), "activity :" + e,       Toast.LENGTH_LONG).show(); 
       e.printStackTrace(); 
      } 
      // mUploadMessage.onReceiveValue(result); 
      mUploadMessage.onReceiveValue(KitkatPath); 
      System.out.println("mUploadMessage = "+mUploadMessage); 
      mUploadMessage = null; 
     } 
    } 
    return; 
} 



/** CODE FOR FILE UPLOAD*/ 



public static String getPath(final Context context, final Uri uri) { 

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; 

    // DocumentProvider 
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { 
     // ExternalStorageProvider 
     if (isExternalStorageDocument(uri)) { 
      final String docId = DocumentsContract.getDocumentId(uri); 
      final String[] split = docId.split(":"); 
      final String type = split[0]; 

      if ("primary".equalsIgnoreCase(type)) { 
       return Environment.getExternalStorageDirectory() + "/" + split[1]; 
      } 

      // TODO handle non-primary volumes 
     } 
     // DownloadsProvider 
     else if (isDownloadsDocument(uri)) { 

      final String id = DocumentsContract.getDocumentId(uri); 
      final Uri contentUri = ContentUris.withAppendedId(
        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); 

      return getDataColumn(context, contentUri, null, null); 
     } 
     // MediaProvider 
     else if (isMediaDocument(uri)) { 
      final String docId = DocumentsContract.getDocumentId(uri); 
      final String[] split = docId.split(":"); 
      final String type = split[0]; 

      Uri contentUri = null; 
      if ("image".equals(type)) { 
       contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 
      } else if ("video".equals(type)) { 
       contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 
      } else if ("audio".equals(type)) { 
       contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
      } 

      final String selection = "_id=?"; 
      final String[] selectionArgs = new String[] { 
        split[1] 
      }; 

      return getDataColumn(context, contentUri, selection, selectionArgs); 
     } 
    } 
    // MediaStore (and general) 
    else if ("content".equalsIgnoreCase(uri.getScheme())) { 

     // Return the remote address 
     if (isGooglePhotosUri(uri)) 
      return uri.getLastPathSegment(); 

     return getDataColumn(context, uri, null, null); 
    } 
    // File 
    else if ("file".equalsIgnoreCase(uri.getScheme())) { 
     return uri.getPath(); 
    } 

    return null; 
} 

/** 
* Get the value of the data column for this Uri. This is useful for 
* MediaStore Uris, and other file-based ContentProviders. 
* 
* @param context The context. 
* @param uri The Uri to query. 
* @param selection (Optional) Filter used in the query. 
* @param selectionArgs (Optional) Selection arguments used in the query. 
* @return The value of the _data column, which is typically a file path. 
*/ 
public static String getDataColumn(Context context, Uri uri, String selection, 
     String[] selectionArgs) { 

    Cursor cursor = null; 
    final String column = "_data"; 
    final String[] projection = { 
      column 
    }; 

    try { 
     cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, 
       null); 
     if (cursor != null && cursor.moveToFirst()) { 
      final int index = cursor.getColumnIndexOrThrow(column); 
      return cursor.getString(index); 
     } 
    } finally { 
     if (cursor != null) 
      cursor.close(); 
    } 
    return null; 
} 


/** 
* @param uri The Uri to check. 
* @return Whether the Uri authority is ExternalStorageProvider. 
*/ 
public static boolean isExternalStorageDocument(Uri uri) { 
    return "com.android.externalstorage.documents".equals(uri.getAuthority()); 
} 

/** 
* @param uri The Uri to check. 
* @return Whether the Uri authority is DownloadsProvider. 
*/ 
public static boolean isDownloadsDocument(Uri uri) { 
    return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 
} 

/** 
* @param uri The Uri to check. 
* @return Whether the Uri authority is MediaProvider. 
*/ 
public static boolean isMediaDocument(Uri uri) { 
    return "com.android.providers.media.documents".equals(uri.getAuthority()); 
} 

/** 
* @param uri The Uri to check. 
* @return Whether the Uri authority is Google Photos. 
*/ 
public static boolean isGooglePhotosUri(Uri uri) { 
    return "com.google.android.apps.photos.content".equals(uri.getAuthority()); 
} 

private File createImageFile() throws IOException { 
    // Create an image file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date(heightDiff)); 
    String imageFileName = "JPEG_" + timeStamp + "_"; 
    File storageDir = Environment.getExternalStoragePublicDirectory(
      Environment.DIRECTORY_PICTURES); 
    File imageFile = File.createTempFile(
      imageFileName, /* prefix */ 
      ".jpg",   /* suffix */ 
      storageDir  /* directory */ 
    ); 
    return imageFile; 
} 

& jetzt in der WebViewChromeClient ---

browser.setWebChromeClient (neu WebChromeClient() {

   // For Android 5.0 
       public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) { 
        System.out.println("in 5.0"); 

        // Double check that we don't have any existing callbacks 
        if (mFilePathCallback != null) { 
         mFilePathCallback.onReceiveValue(null); 
        } 
        mFilePathCallback = filePath; 
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) { 
         // Create the File where the photo should go 
         File photoFile = null; 
         try { 
          photoFile = createImageFile(); 
          takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath); 
         } catch (IOException ex) { 
          // Error occurred while creating the File 
          // Log.e(TAG, "Unable to create Image File", ex); 
         } 
         // Continue only if the File was successfully created 
         if (photoFile != null) { 
          mCameraPhotoPath = "file:" + photoFile.getAbsolutePath(); 
          takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, 
            Uri.fromFile(photoFile)); 
         } else { 
          takePictureIntent = null; 
         } 
        } 
        Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); 
        contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); 
        contentSelectionIntent.setType("image/*"); 
        Intent[] intentArray; 
        if (takePictureIntent != null) { 
         intentArray = new Intent[]{takePictureIntent}; 
        } else { 
         intentArray = new Intent[0]; 
        } 
        Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); 
        chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); 
        chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); 
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); 
        startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE); 
        return true; 
       } 
       // openFileChooser for Android 3.0+ 
       public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { 
        System.out.println("in 3.0+"); 
        mUploadMessage = uploadMsg; 
        // Create AndroidExampleFolder at sdcard 
        // Create AndroidExampleFolder at sdcard 
        File imageStorageDir = new File(
          Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES) 
          , "AndroidExampleFolder"); 
        if (!imageStorageDir.exists()) { 
         // Create AndroidExampleFolder at sdcard 
         imageStorageDir.mkdirs(); 
        } 
        // Create camera captured image file path and name 
        File file = new File(
          imageStorageDir + File.separator + "IMG_" 
            + String.valueOf(System.currentTimeMillis()) 
            + ".jpg"); 
        mCapturedImageURI = Uri.fromFile(file); 


        // 

        // Camera capture image intent 
        final Intent captureIntent = new Intent(
          android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI); 
        Intent i = new Intent(Intent.ACTION_GET_CONTENT); 
        i.addCategory(Intent.CATEGORY_OPENABLE); 
        i.setType("image/*"); 
        // Create file chooser intent 
        Intent chooserIntent = Intent.createChooser(i, "Image Chooser"); 
        // Set camera intent to file chooser 
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS 
          , new Parcelable[] { captureIntent }); 
        // On select image call onActivityResult method of activity 






        startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE); 
       } 
       // openFileChooser for Android < 3.0 
       public void openFileChooser(ValueCallback<Uri> uploadMsg) { 
        System.out.println("in <3.0"); 
        openFileChooser(uploadMsg, ""); 
       } 

       // openFileChooser for other Android versions 
       public void openFileChooser(ValueCallback<Uri> uploadMsg, 
         String acceptType, String capture) { 
        System.out.println("in OTHER"); 
        openFileChooser(uploadMsg, acceptType); 

       } 
+0

Danke! Ich habe es auf den meisten Android-Versionen außer 4.2.1 funktioniert. Die Dateiauswahl wird nicht gestartet. Irgendwelche Ideen warum das sein könnte? – CacheMeOutside

Verwandte Themen