2017-07-10 1 views
3

so hier ist mein Problem, ich muss eine Datei in Telefon und dann auf meinen Parse-Server hochladen. Ich habe eine Dateiauswahl für Dokument, Download, externe, Medien-Ordner gemacht, aber Android-Datei-Chooser auch Google Drive-Option vorschlagen. Also habe ich Te Uri bekommen, aber ich kann keinen Weg finden, auf diese "lokale Kopie" zuzugreifen.Holen Sie sich die richtige Uri von Datei-Chooser mit Google Drive

Muss ich das Google Drive SDK verwenden, um darauf zuzugreifen? Oder kann Androide nicht schlau genug sein und mir Methoden geben, mit diesem Uri umzugehen?

Ich habe erfolgreich den Dateinamen abgerufen.

content://com.google.android.apps.docs.storage/document/ 

Hier sind meine Dateiauswahl und Handler:

public static void pick(final Controller controller) { 
     final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT); 
     chooseFileIntent.setType("application/pdf"); 
     chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE); 
     if (chooseFileIntent.resolveActivity(controller.getContext().getPackageManager()) != null) { 
      controller.startActivityForResult(chooseFileIntent, Configuration.Request.Code.Pdf.Pdf); 
     } 
    } 

    private static boolean isExternalStorageDocument(Uri uri) { 
     return "com.android.externalstorage.documents".equals(uri.getAuthority()); 
    } 

    private static boolean isDownloadsDocument(Uri uri) { 
     return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 
    } 

    private static boolean isMediaDocument(Uri uri) { 
     return "com.android.providers.media.documents".equals(uri.getAuthority()); 
    } 

    private static boolean isGooglePhotosUri(Uri uri) { 
     return "com.google.android.apps.photos.content".equals(uri.getAuthority()); 
    } 

    private static boolean isGoogleDriveUri(Uri uri) { 
     return "com.google.android.apps.docs.storage".equals(uri.getAuthority()); 
    } 

    private 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; 
    } 

    private static String getPath(Context context, Uri uri) { 
     if (DocumentsContract.isDocumentUri(context, uri)) { 
      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]; 
       } 
      } else if (isGoogleDriveUri(uri)) { 
//    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); 
//    if (cursor != null) { 
//     int fileNameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); 
//     cursor.moveToFirst(); 
//     Log.d("=== TAG ===", cursor.getString(fileNameIndex)); 
//     Log.d("=== TAG ===", uri.getPath()); 
//     cursor.close(); 
//    } 
      } 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); 
      } 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); 
      } 
     } 
     else if ("content".equalsIgnoreCase(uri.getScheme())) { 
      if (isGooglePhotosUri(uri)) 
       return uri.getLastPathSegment(); 
      return getDataColumn(context, uri, null, null); 
     } 
     else if ("file".equalsIgnoreCase(uri.getScheme())) { 
      return uri.getPath(); 
     } 
     return null; 
    } 

    public static void upload(final Context context, final String name, final ParseObject dataSource, final String field, final Uri uri, final Handler handler) { 
     if (context != null && name != null && dataSource != null && field != null && uri != null) { 
      String path = getPath(context, uri); 
      if (path != null) { 
       final File file = new File(path); 
       dataSource.put(field, new ParseFile(file)); 
       dataSource.getParseFile(field).saveInBackground(new SaveCallback() { 
        @Override 
        public void done(ParseException e) { 
         if (e == null) { 
          if (handler != null) { 
           handler.success(); 
          } 
         } 
        } 
       }, new ProgressCallback() { 
        @Override 
        public void done(Integer percentDone) { 
         if (handler != null) { 
          handler.progress(percentDone); 
         } 
        } 
       }); 
      } 
     } 
    } 

EDIT:

ich einigen Versuch gemacht habe, aber ich habe ein Problem, wenn die temporäre Datei zu löschen Hier ist meine code:

public static void copyFile(final Context context, final Uri uri, final ParseObject dataSource, final String field, final String name, final Data.Source target, final Handler handler) { 
     new AsyncTask<Void, Void, Boolean>() { 
      @Override 
      protected Boolean doInBackground(Void... params) { 
       try { 
        InputStream inputStream = context.getContentResolver().openInputStream(uri); 
        if (inputStream != null) { 
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
         byte[] bytes = new byte[1024]; 
         int length; 
         while ((length = inputStream.read(bytes)) != -1) { 
          byteArrayOutputStream.write(bytes, 0, length); 
         } 
         dataSource.put(field, new ParseFile(name, byteArrayOutputStream.toByteArray())); 
         byteArrayOutputStream.close(); 
         inputStream.close(); 
         return true; 
        } else { 
         return false; 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
        return false; 
       } 
      } 

      @Override 
      protected void onPostExecute(final Boolean success) { 
       dataSource.getParseFile(field).saveInBackground(new SaveCallback() { 
        @Override 
        public void done(ParseException e) { 
         if (e == null) { 
          if (handler != null) { 
           handler.success(); 
          } 
         } 
        } 
       }, new ProgressCallback() { 
        @Override 
        public void done(Integer percentDone) { 
         if (handler != null) { 
          handler.progress(percentDone); 
         } 
        } 
       }); 
      } 
     }.execute(); 
    } 

Endgültige Edi t:

Hier ist mein Code korrekt, temporäre Datei erstellt und in den Cache von Parse selbst, so dass es außerhalb meiner Reichweite. Hoffe, er kann helfen.

Antwort

3

Also habe ich te Uri, aber ich kann keinen Weg finden, auf diese "lokale Kopie?" Zuzugreifen.

Es gibt keine "lokale Kopie", mindestens eine, auf die Sie zugreifen können.

Oder kann Android nicht einfach schlau genug sein und mir Methoden geben, diesen Uri zu behandeln?

Verwenden ContentResolver und openInputStream() ein InputStream auf dem Inhalt der Uri identifiziert zu bekommen. Verwenden Sie das entweder direkt mit Ihrem "parse-server" oder verwenden Sie es, um eine temporäre "lokale Kopie" für eine von Ihnen kontrollierte Datei zu erstellen. Laden Sie diese lokale Kopie hoch und löschen Sie sie, wenn Sie fertig sind.

Hier ist meine Dateiauswahl und Handler:

pick() ist in Ordnung. upload() könnte in Ordnung sein; Ich habe Parse nicht benutzt. Der Rest dieses Codes ist Junk, kopiert von vorherigem Müll. Es macht viele unbegründete, unzuverlässige Annahmen und es funktioniert nicht für Uri Werte von beliebigen Apps (z. B. über FileProvider bedient).

+0

Haben Sie eine Lösung, die mit den meisten Uri funktioniert? Muss ich eine Bibliothek der dritten Schicht verwenden? Ich habe keine Zeit, all das wirklich zu entwickeln. Danke für die Antwort! – Nek

+0

@Nek: "Hast du eine Lösung, die mit den meisten Uri funktioniert?" - per Definition ist das nicht möglich. Ein 'Uri' mit einem 'content'-Schema kann auf alles zeigen, was' ContentProvider' will, und das muss keine Datei sein, geschweige denn eine Datei im Dateisystem, auf die Sie zugreifen können. Verwenden Sie 'ContentResolver' und' openInputStream() '. "Ich habe keine Zeit, all das zu entwickeln" - das Kopieren von Daten von einem "InputStream" zu einem "FileOutputStream" ist trivial, so wie man es in einem Buch über Java-Programmierung lesen kann. – CommonsWare

+0

Okey also, wenn ich es bekomme, sollte ich eine Dateiauswahl, die immer OpenInputStream und eine lokale temporäre Kopie verwenden, um die allgemeinste möglich sein? – Nek

Verwandte Themen