Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Monday, July 4, 2016

Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work

Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


I am trying to get an image from the gallery app from one of the folders from the Google+ synced photos. After selecting the image, the Uri is being passed back correctly. But when I try to get the actual path of that image on the storage device, so that I can use it, it crashes. The problem seems to be specifically with the picasa content provider.

Tested on Nexus S and Nexus 7, and other devices as well.

  E/AndroidRuntime(14572): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://com.google.android.gallery3d.provider/picasa/item/5427003652908228690 }}  

Here, the dat field seems to be correctly passing the Uri, but when I try to fetch the image's location, it crashes with the following error.

  W/GalleryProvider(14381): unsupported column: _data  

Seems that the content provider for Picasa albums doesn't have a _data field.

The code for getting the location is:

  // imageUri is the Uri from above.  String[] proj = { MediaStore.Images.Media.DATA };  Cursor cursor = context.getContentResolver().query(imageUri, proj,null, null, null);  int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);  cursor.moveToFirst();    String filePath = cursor.getString(column_index);  cursor.close();  

The only columns that seem to be supported for this image are: [user_account, picasa_id, _display_name, _size, mime_type, datetaken, latitude, longitude, orientation]

How do we get the actual location of this image. And if we are not supposed to work with this image, these images shouldn't be shown to the user in the first place.

The Intent to launch the gallery app is:

  Intent intent = new Intent();  intent.setType("image/*");  intent.setAction(Intent.ACTION_GET_CONTENT);  

Answer by Leonidos for Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


I faced the same problem about year ago.. I show you my solution (code is quite messy, please refactor it). So, you have the image URI which was returned from gallery:

    ImageInfo getImage(URI imageUri) {            ImageInfo result = null;            final String[] cursorColumns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.ORIENTATION};            // some devices (OS versions return an URI of com.android instead of com.google.android          if (imageUri.toString().startsWith("content://com.android.gallery3d.provider"))  {              // use the com.google provider, not the com.android provider.              imageUri = Uri.parse(imageUri.toString().replace("com.android.gallery3d","com.google.android.gallery3d"));          }            Cursor cursor = App.getContext().getContentResolver().query(imageUri, cursorColumns, null, null, null);          if (cursor != null) {                int dataColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);              int orientationColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION);                cursor.moveToFirst();                // if it is a picasa image on newer devices with OS 3.0 and up              if (imageUri.toString().startsWith("content://com.google.android.gallery3d")) {                    result = new ImageInfo(downloadImage(imageUri), "0");                                       } else { // it is a regular local image file                    result = new ImageInfo(cursor.getString(dataColumnIndex), cursor.getString(orientationColumnIndex));                }                cursor.close();            } else {              result = new ImageInfo(downloadImage(imageUri), "0");          }            return result;                        }  

And now we need function to download image:

private String downloadImage(URI imageUri) {        File cacheDir;      // if the device has an SD card      if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {          cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),".OCFL311");      } else {          // it does not have an SD card          cacheDir = App.getContext().getCacheDir();      }        if(!cacheDir.exists()) cacheDir.mkdirs();      File f = new File(cacheDir, PUT_HERE_FILE_NAME_TO_STORE_IMAGE);        try {            InputStream is = null;          if (imageUri.toString().startsWith("content://com.google.android.gallery3d")) {              is = App.getContext().getContentResolver().openInputStream(imageUri);          } else {              is = new URL(imageUri.toString()).openStream();          }            OutputStream os = new FileOutputStream(f);          Utils.InputToOutputStream(is, os);            return f.getAbsolutePath();      } catch (Exception ex) {          Log.d(this.getClass().getName(), "Exception: " + ex.getMessage());          // something went wrong          ex.printStackTrace();          return null;      }  }  

ImageInfo is my class to store path to image and its orientation.

public static class ImageInfo {      public final String filePath;      public final String imageOrientation;        public ImageInfo(String filePath, String imageOrientation) {          this.filePath = filePath;            if (imageOrientation == null) imageOrientation = "0";          this.imageOrientation = imageOrientation;                 }  }  

Answer by Kumar Bibek for Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


After a lot of research, I felt that there were too many workarounds to do something which seems to be quite simple. So, I went ahead a wrote a small library that handles all the complex if elses and happens to work for all possible scenarios that I can think of. Do give it a try and see if this helps.

http://techdroid.kbeanie.com/2013/03/easy-image-chooser-library-for-android.html

This is an initial implementation. Although it handles almost every situation, there could be a few bugs. If you use this library, please let me know your feedback and if at all it could be improved any further.

Answer by drindt for Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


I wasted now lots of hours and now i found a solution which works in all cases without any magic downloading in special threads or something. The following method returns a stream from the content which the user selected and this works with everything in the wild.

FileInputStream getSourceStream(Uri u) throws FileNotFoundException {      FileInputStream out = null;      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {          ParcelFileDescriptor parcelFileDescriptor =                  mContext.getContentResolver().openFileDescriptor(u, "r");          FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();          out = new FileInputStream(fileDescriptor);      } else {          out = (FileInputStream) mContext.getContentResolver().openInputStream(u);      }      return out;  }  

Answer by Naveed Ahmad for Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


I used this approach, works fine for me, hope this will helps you ....

ACTIVITYRESULT_CHOOSEPICTURE is the int you use when calling startActivity(intent, requestCode);

public void onActivityResult(int requestCode, int resultCode, Intent data) {    if(requestCode == ACTIVITYRESULT_CHOOSEPICTURE) {      BitmapFactory.Options options = new BitmapFactory.Options();      final InputStream ist = ontext.getContentResolver().openInputStream(intent.getData());      final Bitmap bitmap = BitmapFactory.decodeStream(ist, null, options);      ist.close();    }  }  

if above code doesn't work than just refer this link... it will surly shows the way

http://dimitar.me/how-to-get-picasa-images-using-the-image-picker-on-android-devices-running-any-os-version/

Answer by Adarsh Yadav for Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


Finally ended with a classic solution...By using Document.util, which covers all authority :-1-Inside your onActivityResult():-

case GALLERY_CAPTURE_IMAGE_REQUEST_CODE:                      String filePath = DocumentUtils.getPath(MainContainerActivity.this,data.getData();                        break;  

2- Create class DocumentUtils:-

public class DocumentUtils {    @TargetApi(Build.VERSION_CODES.KITKAT)  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          String url;          if (isGooglePhotosUri(uri)) {              url = getDataColumnWithAuthority(context, uri, null, null);              return getDataColumn(context, Uri.parse(url), null, null);          }            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 column_index = cursor.getColumnIndexOrThrow(column);              return cursor.getString(column_index);          }      } finally {          if (cursor != null)              cursor.close();      }      return null;  }  /**   * Function for fixing synced folder image picking bug   *   * **/  public static String getDataColumnWithAuthority(Context context, Uri uri, String selection, String[] selectionArgs) {      Bitmap bitmap = null;      InputStream is = null;      if (uri.getAuthority()!=null){          try {              is = context.getContentResolver().openInputStream(uri);          } catch (FileNotFoundException e) {              e.printStackTrace();          }          Bitmap bmp = BitmapFactory.decodeStream(is);          return ImageLoader.getImageUri(context,bmp).toString();      }        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) {      if(uri.getAuthority()!=null)          return true;      return false;  }  

}

3- Also you will need following function in ImageLoader.java:-

public static Uri getImageUri(Context inContext, Bitmap inImage) {      ByteArrayOutputStream bytes = new ByteArrayOutputStream();      inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);      String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);      return Uri.parse(path);  }  

Answer by Akhil for Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


Below trick worked for me, what i am doing here is if there is any authority url in URI, then i am creating a temporary image using below code & returning the Content URI of the same.

I have answered similar question here as well..

public static String getImageUrlWithAuthority(Context context, Uri uri) {      InputStream is = null;      if (uri.getAuthority() != null) {          try {              is = context.getContentResolver().openInputStream(uri);              Bitmap bmp = BitmapFactory.decodeStream(is);              return writeToTempImageAndGetPathUri(context, bmp).toString();          } catch (FileNotFoundException e) {              e.printStackTrace();          }finally {              try {                  is.close();              } catch (IOException e) {                  e.printStackTrace();              }          }      }      return null;  }    public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) {      ByteArrayOutputStream bytes = new ByteArrayOutputStream();      inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);      String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);      return Uri.parse(path);  }  

Answer by Youngjae for Getting an image from Gallery on from the Picasa//Google + synced folders doesn't work


Based on @drindt answer, below codes give downloaded temporary File path from Google Photo cloud-synced-but-not-in-device file.

@SuppressLint("NewApi")  public static String getFilePath(final Context context, final Uri uri) {        // Google photo uri example      // content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2FAF1QipMObgoK_wDY66gu0QkMAi/ORIGINAL/NONE/114919        if ("content".equalsIgnoreCase(uri.getScheme())) {          String result = getDataColumn(context, uri, null, null); //           if (TextUtils.isEmpty(result))              if (uri.getAuthority().contains("com.google.android")) {                  try {                      File localFile = createImageFile(context, null);                      FileInputStream remoteFile = getSourceStream(context, uri);                      if(copyToFile(remoteFile, localFile))                          result = localFile.getAbsolutePath();                      remoteFile.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }          return result;      }      // 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.   */  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 column_index = cursor.getColumnIndexOrThrow(column);              return cursor.getString(column_index);          }      } finally {          if (cursor != null)              cursor.close();      }        return null;  }      /**   * Copy data from a source stream to destFile.   * Return true if succeed, return false if failed.   */  private static boolean copyToFile(InputStream inputStream, File destFile) {      if (inputStream == null || destFile == null) return false;      try {          OutputStream out = new FileOutputStream(destFile);          try {              byte[] buffer = new byte[4096];              int bytesRead;              while ((bytesRead = inputStream.read(buffer)) >= 0) {                  out.write(buffer, 0, bytesRead);              }          } finally {              out.close();          }          return true;      } catch (IOException e) {          return false;      }  }    public static String getTimestamp() {      try {          return new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ROOT).format(new Date());      } catch (RuntimeException e) {          return new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());      }  }    public static File createImageFile(Context context, String imageFileName) throws IOException {      if (TextUtils.isEmpty(imageFileName))          imageFileName = getTimestamp(); // make random filename if you want.        final File root;      imageFileName = imageFileName;      root = context.getExternalCacheDir();        if (root != null && !root.exists())          root.mkdirs();      return new File(root, imageFileName);  }      public static FileInputStream getSourceStream(Context context, Uri u) throws FileNotFoundException {      FileInputStream out = null;      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {          ParcelFileDescriptor parcelFileDescriptor =                  context.getContentResolver().openFileDescriptor(u, "r");          FileDescriptor fileDescriptor = null;          if (parcelFileDescriptor != null) {              fileDescriptor = parcelFileDescriptor.getFileDescriptor();              out = new FileInputStream(fileDescriptor);          }      } else {          out = (FileInputStream) context.getContentResolver().openInputStream(u);      }      return out;  }  


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.