【问题标题】:Retrieve Image from google photos library after dowloading下载后从谷歌照片库中检索图像
【发布时间】:2018-04-11 01:41:27
【问题描述】:

我打算从图库中获取照片,当我在图库中使用 nexus google photo 应用程序时,一切正常。

但如果图片不在手机上(在 Google 相册在线服务上),它会为我下载。选择图像后,我将图像发送到另一个活动进行裁剪,但在下载的情况下,发送到裁剪活动的图像为空,因为下载尚未完成。

我如何知道下载完成以将图像发送到裁剪活动?

这是我的代码:

private void pickFromGallery()
{
    Intent galleryIntent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(galleryIntent, RESULT_LOAD_IMG);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    try {
        // When an Image is picked
        if (requestCode == RESULT_LOAD_IMG && resultCode == Activity.RESULT_OK
                && null != data) {
            // Get the Image from data

            Uri selectedImage = data.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};

            // Get the cursor
            Cursor cursor = getApplicationContext().getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            // Move to first row
            assert cursor != null;
            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            imgDecodableString = cursor.getString(columnIndex);
            cursor.close();
            startCrop(imgDecodableString);
        }
    } catch (Exception e) {
        Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG)
                .show();
    }
    }

任何帮助将不胜感激。

【问题讨论】:

  • 请使用点和逗号,长句不好读。

标签: android image google-photos


【解决方案1】:

我认为当您从谷歌照片下载选定的图像时,您无法裁剪图像。您只能裁剪本地存储图像

但要检查所选图像是否可下载或从本地存储中下载,您可以在 onActivityResult() 方法中执行此操作。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RESULT_LOAD_IMG && resultCode == Activity.RESULT_OK
                && null != data) {

                Uri selectedImageUri = data.getData();
                String tempPath = getPath(selectedImageUri, getActivity());
                String url = data.getData().toString();
                if (url.startsWith("content://com.google.android.apps.photos.content")){
                    try {
                        InputStream is = getActivity().getContentResolver().openInputStream(selectedImageUri);
                        if (is != null) {
                            Bitmap pictureBitmap = BitmapFactory.decodeStream(is);
                            //You can use this bitmap according to your purpose or Set bitmap to imageview
                        }
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }else {
                     startCrop(tempPath);

             }
         }

}

这里是getPath() 方法,用于onActivityResult()

public String getPath(Uri uri, Activity activity) {
    Cursor cursor = null;
    try {
        String[] projection = {MediaStore.MediaColumns.DATA};
        cursor = activity.getContentResolver().query(uri, projection, null, null, null);
        if (cursor.moveToFirst()) {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
            return cursor.getString(column_index);
        }
    } catch (Exception e) {
    } finally {
        cursor.close();
    }
    return "";
}

希望对你有帮助。

【讨论】:

  • 它的投掷FileNotFoundException :(
【解决方案2】:

您无法从谷歌驱动器下载图像以下是从驱动器下载图像或文件的步骤。

要从谷歌驱动器下载图像或文件,您需要一个库

  • google-api-services-drive-v2-rev9-1.8.0-beta.jar()

设置控制台

  • 接下来转到Google Consol

  • 创建一个新项目。在服务下,您需要打开两件事:DRIVE API 和 DRIVE SDK!它们是分开的,一个不会自动打开另一个,您必须同时打开! (弄清楚这一点浪费了我至少 20 个小时的时间。)

  • 仍在控制台上,转到 API 访问。创建一个客户端,使其成为 Android 应用程序。给它你的包 ID。我认为指纹这件事实际上并不重要,因为我很确定我使用了错误的指纹,但无论如何都要尽量做到这一点(Google 提供了相关说明。)

  • 它将生成一个客户端 ID。你会需要那个。坚持住。

ANDROID 代码 - 设置和上传

  • 首先,获取一个授权令牌:

    AccountManager am = AccountManager.get(activity); am.getAuthToken(am.getAccounts())[0], "oauth2:" + DriveScopes.DRIVE, 新捆绑(), 真的, 新的 OnTokenAcquired(), 空);

接下来,需要像这样设置 OnTokenAcquired():

private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
    @Override
    public void run(AccountManagerFuture<Bundle> result) {
        try {
            final String token = result.getResult().getString(AccountManager.KEY_AUTHTOKEN);
            HttpTransport httpTransport = new NetHttpTransport();
            JacksonFactory jsonFactory = new JacksonFactory();
            Drive.Builder b = new Drive.Builder(httpTransport, jsonFactory, null);
            b.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
                @Override
                public void initialize(JSonHttpRequest request) throws IOException {
                    DriveRequest driveRequest = (DriveRequest) request;
                    driveRequest.setPrettyPrint(true);
                    driveRequest.setKey(CLIENT ID YOU GOT WHEN SETTING UP THE CONSOLE BEFORE YOU STARTED CODING)
                    driveRequest.setOauthToken(token);
                }
            });

            final Drive drive = b.build();

            final com.google.api.services.drive.model.File body = new com.google.api.services.drive.model.File();
            body.setTitle("My Test File");
    body.setDescription("A Test File");
    body.setMimeType("text/plain");

            final FileContent mediaContent = new FileContent("text/plain", an ordinary java.io.File you'd like to upload. Make it using a FileWriter or something, that's really outside the scope of this answer.)
            new Thread(new Runnable() {
                public void run() {
                    try {
                        com.google.api.services.drive.model.File file = drive.files().insert(body, mediaContent).execute();
                        alreadyTriedAgain = false; // Global boolean to make sure you don't repeatedly try too many times when the server is down or your code is faulty... they'll block requests until the next day if you make 10 bad requests, I found.
                    } catch (IOException e) {
                        if (!alreadyTriedAgain) {
                            alreadyTriedAgain = true;
                            AccountManager am = AccountManager.get(activity);
                            am.invalidateAuthToken(am.getAccounts()[0].type, null); // Requires the permissions MANAGE_ACCOUNTS & USE_CREDENTIALS in the Manifest
                            am.getAuthToken (same as before...)
                        } else {
                            // Give up. Crash or log an error or whatever you want.
                        }
                    }
                }
            }).start();
            Intent launch = (Intent)result.getResult().get(AccountManager.KEY_INTENT);
            if (launch != null) {
                startActivityForResult(launch, 3025);
                return; // Not sure why... I wrote it here for some reason. Might not actually be necessary.
            }
        } catch (OperationCanceledException e) {
            // Handle it...
        } catch (AuthenticatorException e) {
            // Handle it...
        } catch (IOException e) {
            // Handle it...
        }
    }
}

安卓代码 - 下载

private java.io.File downloadGFileToJFolder(Drive drive, String token, File gFile, java.io.File jFolder) throws IOException {
    if (gFile.getDownloadUrl() != null && gFile.getDownloadUrl().length() > 0 ) {
        if (jFolder == null) {
            jFolder = Environment.getExternalStorageDirectory();
            jFolder.mkdirs();
        }
        try {

            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(gFile.getDownloadUrl());
            get.setHeader("Authorization", "Bearer " + token);
            HttpResponse response = client.execute(get);

            InputStream inputStream = response.getEntity().getContent();
            jFolder.mkdirs();
            java.io.File jFile = new java.io.File(jFolder.getAbsolutePath() + "/" + getGFileName(gFile)); // getGFileName() is my own method... it just grabs originalFilename if it exists or title if it doesn't.
            FileOutputStream fileStream = new FileOutputStream(jFile);
            byte buffer[] = new byte[1024];
            int length;
            while ((length=inputStream.read(buffer))>0) {
                fileStream.write(buffer, 0, length);
            }
            fileStream.close();
            inputStream.close();
            return jFile;
        } catch (IOException e) {        
            // Handle IOExceptions here...
            return null;
        }
    } else {
        // Handle the case where the file on Google Drive has no length here.
        return null;
    }
}

【讨论】:

  • 问题提到了谷歌照片,而不是谷歌云端硬盘。无论如何 - 您可以使用 DocumentsProvider 从 Google Drive 获取文件。
  • @MilosFec google drive 是 google 的一部分,google 总是将照片存储在 google drive 上。
  • 那不相关。安装 Google Photos 后,您可以使用 Intent.ACTION_PICK 获取照片。如果您已安装 Google Drive,则可以使用 Intent.ACTION_OPEN_DOCUMENT 获取任何文件。
【解决方案3】:

您可以使用 AsyncTask 下载(或复制本地图像),然后进行处理。

在您的活动中创建:

private class PictureAsyncTask extends AsyncTask<Void, Void, String> {
    private Uri mUri;

    public PictureAsyncTask(Uri uri) {
        mUri = uri;
    }

    @Override
    protected String doInBackground(Void... params) {
        InputStream inputStream = null;
        try {
            inputStream = getContentResolver().openInputStream(mUri);
            String path = null; // Path of downloaded image
            // Download image from inputStream
            return path;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null
    }

    @Override
    protected void onPostExecute(String path) {
        if (path == null) {
            // Process image
            // Maybe another AsyncTask or background thread?
        } else {
            // Download failed
        }
    }
}

从 onActivityResult 调用它:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case RESULT_LOAD_IMG:
            if (resultCode == RESULT_OK) {
                if (data != null) {
                    Uri uri = data.getData();
                    if (uri != null) {
                        new PictureAsyncTask(uri).execute();
                    } else {
                        // No data
                    }
                } else {
                    // No picture selected?
                }
            }
            break;
    }
}

【讨论】:

  • 我只是想知道在使用谷歌照片应用程序作为图库时何时处理下载
  • 您应该始终在后台线程中处理它,即使它是本地图片。 IE。而不是下载,您可以使用 BitmapFactory.decodeStream(inpustStream) 创建位图并处理位图。这可能需要一些时间,因此在主线程上执行此操作并不好。
猜你喜欢
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多