Retrieve Image from google photos library after dowloading - android

I am launching an intent to get photos from gallery and when I am using nexus google photo app in my gallery everything works fine.
But if the image is not on the phone (on the Google Photos online service) it will download it for me. After selecting the image I am sending the image to another activity for cropping but in case of download the image sent to the crop activity is null since the download is not finished yet.
How can I know when the download is finished to send the image to the cropping activity?
Here is my code:
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();
}
}
any help would be appreciated.

I think you can't crop images when you download selected image from google photos. you can only crop your local storage images
But for checking whether selected image is downloadable or from local storage you can do like this in your onActivityResult() method.
#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);
}
}
}
Here is getPath() method which is used in 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 "";
}
I hope it helps you.

you can not download images from google drive below are the steps to download images or files from drive.
To download images or file from google drive you need a library
google-api-services-drive-v2-rev9-1.8.0-beta.jar()
SETTING UP THE CONSOLE
next go to Google Consol
Make a new project. Under Services, you'll need to turn on two things: DRIVE API and DRIVE SDK! They are separate, one does not automatically turn the other on, and YOU MUST TURN BOTH ON! (Figuring this out wasted at least 20 hours of my time alone.)
Still on the console, go to API Access. Create a client, make it an Android app. Give it your bundle ID. I don't think the fingerprints thing is actually important, as I'm pretty sure I used the wrong one, but try to get that right anyways (Google provides instructions for it.)
It'll generate a Client ID. You're going to need that. Hold onto it.
THE ANDROID CODE - Set Up and Uploading
First, get an auth token:
AccountManager am = AccountManager.get(activity);
am.getAuthToken(am.getAccounts())[0],
"oauth2:" + DriveScopes.DRIVE,
new Bundle(),
true,
new OnTokenAcquired(),
null);
Next, OnTokenAcquired() needs to be set up something like this:
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...
}
}
}
THE ANDROID CODE - Downloading
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;
}
}

You can use AsyncTask for downloading (or copying local image), then process it.
In your Activity create:
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
}
}
}
Call it from 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;
}
}

Related

Android 11 / API 30 Access Android/data and media Directory to list files

I had some troubles to access Android/media or Android/data directory, today I found an solution, you can see it down below.
And yes I know it is not recommended to load many bitmaps in the main thread, it was just for testing.
Hope I could help you with that.
String stringWA = "primary:Android/media/com.whatsapp/WhatsApp/Media/.Statuses/";
LinearLayout ll;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = findViewById(R.id.ll_add);
Button btn = findViewById(R.id.button);
btn.setOnClickListener(v -> {
openDirectory();
});
}
public void openDirectory() {
// Choose a directory using the system's file picker.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
// Optionally, specify a URI for the directory that should be opened in
// the system file picker when it loads.
startActivityForResult(intent.putExtra("android.provider.extra.INITIAL_URI", (Parcelable)DocumentsContract.buildDocumentUri((String)"com.android.externalstorage.documents", (String)stringWA)), 1234);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
if (requestCode == 1234 && resultCode == Activity.RESULT_OK) {
// The result data contains a URI for the document or directory that
// the user selected.
Uri uri = null;
if (resultData != null) {
uri = resultData.getData();
try{
loadImageIntoView(uri);
}catch (Exception e){
}
}
}
}
private void loadImageIntoView(Uri uri) {
DocumentFile dir = DocumentFile.fromTreeUri(this, uri);
DocumentFile[] fileListed = dir.listFiles();
for(int i = 0;i < fileListed.length;i++){
ImageView iv = new ImageView(this);
iv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));
try{
InputStream is = getContentResolver().openInputStream(fileListed[i].getUri());
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
iv.setImageBitmap(bitmap);
}catch (Exception e){
iv.setImageResource(R.drawable.ic_baseline_error_24);
}
ll.addView(iv);
}
}

android Get file name and path from Download directory

I'm trying to copy a file from download folder to another directory.
i used this code to get the file path
int PICKFILE_RESULT_CODE=1;
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult( chooseFile,PICKFILE_RESULT_CODE);
I also used
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent returnIntent) {
// If the selection didn't work
if (resultCode != RESULT_OK) {
// Exit without doing anything else
return;
} else {
returnUri = returnIntent.getData();
String src = returnUri.getPath();
Toast.makeText(this, src, Toast.LENGTH_SHORT).show();
}
}
The code works fine if the file is outside the download directory, when in it the path which i get is in the form of number not the actual name of the file like:
/document/2399
this gives an error of file not found
while the path from the root is:
/storage/emulated/0/myDB.db3
this works fine
pls help me to fix this
The code works fine if the file is outside the download directory
No, it does not. It works fine if the scheme of the Uri happens to be file. Most of the time, it will be content.
I'm trying to copy a file from download folder to another directory.
Use openInputStream() on a ContentResolver to get an InputStream on the content identified by the Uri. This works for both file and content schemes. Then, use standard Java I/O to copy the content from the InputStream to your desired location.
Here is the new code:
int PICKFILE_RESULT_CODE=1;
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult( chooseFile,PICKFILE_RESULT_CODE);
And used:
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent returnIntent) {
InputStream is = null;
// If the selection didn't work
if (resultCode != RESULT_OK) {
// Exit without doing anything else
return;
} else {
// Get the file's content URI from the incoming Intent
Uri returnUri = returnIntent.getData();
try {
is = getContentResolver().openInputStream(returnUri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
BackUpHelper.importDB(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void importDB(InputStream is) throws IOException {
OutputStream os = null;
try {
String currentDBPath = DataBaseHelper2.DB_PATH+DataBaseHelper2.DB_NAME;
File outPut = new File(currentDBPath);
os = new FileOutputStream(outPut);
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
os.write(buffer);
}
Toast.makeText(context, R.string.export_successful,
Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(context, R.string.export_failed, Toast.LENGTH_SHORT)
.show();
}finally {
os.flush();
os.close();
is.close();
}
}

Android: Upload image just taken bij camera

I'm trying to make an app that uses the camera to take photos and sends this to my NAS, I managed to do create an app through a tutorial, which takes a picture, saves the picture and shows it onscreen. Another tutorial shows me how to upload a "selected" image by pressing an "extra" button on the screen, it's just that I want to get rid of this step and instead of showing the picture, it directly sends the picture to my NAS.
The current app I created:
package com.deshpande.camerademo;
public class MainActivity extends AppCompatActivity {
private Button takePictureButton;
private ImageView imageView;
private Uri file;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
takePictureButton = (Button) findViewById(R.id.button_image);
imageView = (ImageView) findViewById(R.id.imageview);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
takePictureButton.setEnabled(false);
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == 0) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
takePictureButton.setEnabled(true);
}
}
}
public void takePicture(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
file = Uri.fromFile(getOutputMediaFile());
intent.putExtra(MediaStore.EXTRA_OUTPUT, file);
startActivityForResult(intent, 100);
}
private static File getOutputMediaFile(){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "WedCam");
if (!mediaStorageDir.exists()){
if (!mediaStorageDir.mkdirs()){
Log.d("WedCam", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
return new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) {
if (resultCode == RESULT_OK) {
try {
final FTPClient client = new FTPClient();
final File image = new File(file.getPath());
final FileInputStream fis = new FileInputStream(image);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
client.connect("ftp://127.0.0.1:2221");
client.login("francis", "francis");
client.storeFile(image.getName(), fis);
client.logout();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
Thanks to #Matthias F. I got it all working, this guy is great!
You need to use your saved URI from the camera for the FileInputStream. Try it with this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) {
if (resultCode == RESULT_OK) {
try {
final FTPClient client = new FTPClient();
final File image = new File(file.getPath());
final FileInputStream fis = new FileInputStream(image);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
client.connect("127.0.0.1", 2221);
client.login("francis", "francis");
client.setFileType(FTP.BINARY_FILE_TYPE);
client.storeFile(image.getName(), fis);
client.logout();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Now the FileInputStream points to the created image.
EDIT:
The problem was that the upload was executed on the ui thread and that is not allowed in android. Now a new thead is created for the upload process. Also I forgot to say that you need to access a android permission for using network functionalities. So you need to set
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> in the AndroidManifest.xml.

Android CSV Path is throwing FileNotFoundExpception

I want to import csv from external storage and then update my database but when I am selecting that csv from downloaded folder FileNotFoundExpception comes. Here is the exception System.err:
java.io.FileNotFoundException: /document/primary:Download/GuestCSV.csv: open failed: ENOENT (No such file or directory)
Here is my code. Kindly review my code and help me to find a solution.
importDatabase.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/*");
startActivityForResult(Intent.createChooser(intent, "Open CSV"), ACTIVITY_CHOOSE_FILE);
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ACTIVITY_CHOOSE_FILE: {
if (resultCode == RESULT_OK) {
onImport(new File(data.getData().getPath()));
Log.d(TAG, data.getData().getPath());
}
}
}
}
public void onImport(File files) {
try {
String[] nextLine;
try {
CSVReader reader = new CSVReader(new FileReader(files.getAbsolutePath()));
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
String emailID = nextLine[0];
String guestName = nextLine[1];
String guestSource = nextLine[2];
String guestPhone = nextLine[3];
String guestCount = nextLine[4];
String guestCreatedDate = nextLine[5];
String guestModifiedDate = nextLine[6];
GuestDetails guestDetails = new GuestDetails();
guestDetails.setEmail(emailID);
guestDetails.setUsername(guestName);
guestDetails.setPhone(guestPhone);
guestDetails.setSource(guestSource);
guestDetails.setCount(Integer.valueOf(guestCount));
guestDetails.setCreatedDate(guestCreatedDate);
guestDetails.setModifiedDate(guestModifiedDate);
try {
helper.insertGuest(guestDetails);
} catch (SQLiteConstraintException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), "Data inserted into table...", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
There is no guaranty that the URI you are receiving as result is a file (and thus that the path part is an actual filesystem path).
It may be a content: URI, in with case the path only makes sense for the corresponding ContentProvider.
This kind of URI should be read using ContentResolver.openInputStream() or queried via ContentResolver.query().
See A Uri Is Not (Necessarily) a File for more details.

Android capture image and get actual path

I want to create an application that takes picture/video and send it to my FTP server.
Here is my onActivityResult code;
#Override
protected void onActivityResult(int requestCode, int resultCode,final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PHOTO_CAPTURE && resultCode == RESULT_OK) {
// Upload sdcard file
new AsyncTask(){
#Override
protected Object doInBackground(Object[] params) {
File f = new File(data.getData() + "");
try {
uploadFile(f);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
// Toast.makeText(this, "Photo saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();
}
if (requestCode == VIDEO_CAPTURE && resultCode == RESULT_OK) {
// Upload sdcard file
new AsyncTask(){
#Override
protected Object doInBackground(Object[] params) {
File f = new File(data.getData() + "");
try {
uploadFile(f);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
// Toast.makeText(this, "Video saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();
}
}
Error says no such file or directory. How can I get the actual path of a video or an image taken?
Thank you for your time.
EDIT - EDIT - EDIT
I have used another method to get the path
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
Now I don't get any error but when I open my ftp folder I cant see the uploaded image :S
Here is my uploadFile method;
public void uploadFile(File fileName) throws IOException {
SimpleFTP ftp = new SimpleFTP();
// Connect to an FTP server on port 21.
ftp.connect(server, port, user, pass);
// Set binary mode.
ftp.bin();
// Change to a new working directory on the FTP server.
ftp.cwd("upload");
// Upload some files.
ftp.stor(fileName.getAbsoluteFile());
// Quit from the FTP server.
ftp.disconnect();
}
you have to use getAbsolutePath() from File object it returns path of the file.
Change this code from you activity, see below:
if (requestCode == VIDEO_CAPTURE && resultCode == RESULT_OK) {
// Upload sdcard file
new AsyncTask(){
#Override
protected Object doInBackground(Object[] params) {
try {
//Create a empty file what you want...
File f = new File("Write here your path what you want");
//Open OutputStream
FileOutputStream fos = new FileOutputStream(f);
//Write file
fos.write(data);
//File is created in your path
uploadFile(f);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
// Toast.makeText(this, "Video saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();
}
Tell me if I helped you with this changes and good programming!

Categories

Resources