Is it possible to post a picture in a friend's wall?
I'm using this code :
Bundle postdata = new Bundle();
postdata.putString("message", msg);
postdata.putByteArray("picture", pic);
// this code, i found it in another questions but it doesn't
// seem to help much:
postdata.putString("target_id", usr);
// then i use the Asynchronous request.
mAsyncRunner.request(usr+"/feed", postdata, "POST",new WallRequestListener(), null);
where pic is the picture as a byteArray and usr is the friend's ID.
It just shows the message on the friend's wall but no picture at all.
This is what I use in my app. And it works.
protected void uploadPhoto() {
if (!Utility.mFacebook.isSessionValid()) {
Util.showAlert(this, "Warning", "You must first log in.");
} else {
if (targetUri != null) {
Bundle params = new Bundle();
try {
params.putByteArray("photo", Utility.scaleImage(getApplicationContext(), targetUri));
} catch (Exception e) {
e.printStackTrace();
}
params.putString("caption", txtPhotoCaption.getText().toString());
Utility.mAsyncRunner.request( "replace this with the users ID"+ "/photos&access_token=" + Utility.mFacebook.getAccessToken(),
params, "POST", new PhotoUploadListener(), null);
txtPhotoCaption.setText("");
Toast.makeText(getApplicationContext(), "Photo uploaded successfully", Toast.LENGTH_SHORT).show();
this.finish();
}
}
}
Please note, that I am using the same method as used in the sample app. Without getting into the pros or cons of scaling or not scaling the image. The "caption" attribute is being pulled from an EditText. And the actual image is in the field "targetUri", which is declared as a global variable. It's fetching the image using the default Gallery on the device. For the sake of completeness, this is the code to grab the image from the default Gallery app. (this prompts the user to select the app)
btnAddPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}
});
And it is processed in the onActivityResult() here:
NOTE: I am also setting the selected image in an ImageView as a preview to the logged in user
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Bitmap bitmap = null;
if (resultCode == RESULT_OK) {
targetUri = data.getData();
Log.e("IMG URI", targetUri.toString());
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri));
try {
Utility.scaleImage(getApplicationContext(), targetUri);
imgDisplaySelectedImage.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
I have again tested an upload to a friends wall before I posted the code here as an answer. And it really works. Hope this helps you as well.
EDIT:
As mentioned in the latest comment, using Intent.ACTION_GET_CONTENT did not play nice with the preview image display under the onActivityResult(). Modifying the code a little worked.
What I find strange is the fact that in the "Complete action using" popup, I did not get the Astro File Manager nor the Gallery on my Galaxy S. It gives me File Manager (off the market, not the stock) and Quickoffice Pro. That being said, selections from either the two still works and photos still upload.
According to the documentation the name of the parameter for the picture is not "picture" but "source".
So your code should be:
Bundle postdata = new Bundle();
postdata.putString("message", msg);
postdata.putByteArray("source", pic);
mAsyncRunner.request(usr + "/feed", postdata, "POST", new WallRequestListener(), null);
Related
I am developing an Android app. In my app, I want to let user to choose multiple when user clicks upload button. So I used this library. I can successfully pop up dialog and choose multiple files. But the problem is when I convert URI of selected images to bitmap in onActivityResult, it is giving me error.
This is how I pop up picker in activity:
private void getImages() {
Intent intent = new Intent(GalleryActivity.this, ImagePickerActivity.class);
nl.changer.polypicker.Config pickerConfig = new nl.changer.polypicker.Config(R.color.white,R.color.blue,10,R.color.green);
ImagePickerActivity.setConfig(pickerConfig);
startActivityForResult(intent, INTENT_REQUEST_GET_IMAGES);
}
This is how I am converting to bitmap on result:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == INTENT_REQUEST_GET_IMAGES) {
Parcelable[] parcelableUris = data.getParcelableArrayExtra(ImagePickerActivity.EXTRA_IMAGE_URIS);
if (parcelableUris == null) {
return;
}
// Java doesn't allow array casting, this is a little hack
Uri[] uris = new Uri[parcelableUris.length];
System.arraycopy(parcelableUris, 0, uris, 0, parcelableUris.length);
if (uris != null) {
bitmaps = new ArrayList<Bitmap>();
for (Uri uri : uris) {
try{
if(uri!=null)
{
Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
bitmaps.add(bmp);
}
}
catch (IOException e)
{
Toast.makeText(getBaseContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
if(bitmaps.size()>0)
{
confirmFileUpload();
}
}
}
}
}
As you can see above my code, it will reach to io exception block of try-catch statement.
This is the example of error toasted:
That kind of error throw whatever image I select. What is wrong with my code and how can I fix it?
Finally I found the solution. I problem was when I parse uri to string, the format is something like this:
/sdcard/download/filename.png
The uri string must be in this format:
file:///sdcard/download/filename.png
No Content Provider Found exception throws because my uri string does not have required prefix. So I convert the uri to string. Then added the prefix. Then I parse that string to URI back. Then it worked successfully.
I'm trying to have an Intent that allows user to pick a photo or a video from the phone, then post the image to a server.
Here is how I do it :
public void lookForMedia(View v) {
KeyboardHelper.hideKeyboard(this, postContentEtx);
Intent myIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI);
myIntent.setType("image/*,video/*");
myIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(myIntent, MEDIA_GALLERY);
}
Then :
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case MEDIA_GALLERY:
if (resultCode == RESULT_OK) {
if (requestCode == PICTURE_SELECTED) {
mediaUri = data.getData();
ContentResolver cR = NewPostActivity.this.getContentResolver();
if (mediaUri == null) {
Toast.makeText(NewPostActivity.this, "Error while retrieving the media", Toast.LENGTH_LONG).show();
return;
}
String type = cR.getType(mediaUri);
if (type.startsWith("image")) {
mediaThumbnailImv.setImageURI(mediaUri);
videoUri = null;
thumbnailUri = null;
mediaRll.setVisibility(View.VISIBLE);
mediaThumbnailImv.setVisibility(View.VISIBLE);
mediaThumbnailNetworkImv.setVisibility(View.GONE);
} else if (type.startsWith("video")) {
videoUri = mediaUri;
mediaUri = null;
Bitmap videoThumbnail = ThumbnailUtils.createVideoThumbnail(FileUtil.getRealPathFromURI(NewPostActivity.this, videoUri), MediaStore.Images.Thumbnails.MINI_KIND);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
FileOutputStream out = null;
try {
String filename = "thumb_" + timeStamp + "kfkb.png";
out = new FileOutputStream(NewPostActivity.this.getFilesDir() + filename);
videoThumbnail.compress(Bitmap.CompressFormat.PNG, 90, out);
thumbnailUri = Uri.fromFile(new File(NewPostActivity.this.getFilesDir() + filename));
mediaThumbnailImv.setImageURI(thumbnailUri);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (Throwable ignore) {
}
}
mediaRll.setVisibility(View.VISIBLE);
mediaThumbnailImv.setVisibility(View.VISIBLE);
mediaThumbnailNetworkImv.setVisibility(View.GONE);
} else {
Toast.makeText(NewPostActivity.this, "Invalid media", Toast.LENGTH_LONG).show();
return;
}
}
}
break;
}
}
It works fine on the devices I tried (Nexus 5, LG G3, Samsung Galaxy S3, Wiko Cink Five), but some users told me that they couldn't see their photos or videos when clicking on the button (it seems that it occurs on older version of Android, but I cannot have more precise information right now). Is there a different way to do this, and to be sure that it works on most devices ? Is there something that I am doing wrong ?
First of all i think you doesn't understand correct that is the cross-platform.
Cross-Platform - is the independent from OS code that will be executed equally on each OS. For each OS - will be compiled executable file. For Android - apk. For Windows - exe. etc...
To your problem. If the users complained about incorrect logic working i recommend to you several things :
Log your stack trace with device_info into dump file to sdcard. And ask the user before application end - send this log to your email. Or something like this.
Try to find alternative way for picking image. For the worst case - write your own activity and scan system for images.
I am building a photo upload form which has to grab an image either from the camera or gallery or whatever other resource is available (Dropbox/Google Drive/Astro File Manager, etc.). I think I have it all working except for one small component.
When the selected image is coming from a network resource, such as Google Drive, it can take a long time to return back to the activity. I would like to make this asynchronous to avoid having the user stare at a black screen while the image downloads.
There's a lot of code that I've written to get this whole thing to work, but here's the general process of it:
The Activity starts and displays the form.
The Intent chooser automatically opens and asks the user to select an image from either the camera or another app.
The user selects some app such as Google Drive, selects an image and that app closes, returning the selected image Uri as the result.
Cache the contents of the file to workaround KitKat permissions which can block from re-reading the image if the Activity closes and needs to resume.
Asynchronously display the scaled bitmap using the cached file as the source.
The Intent chooser closes, the image is displayed in an ImageButton and the form is visible to the user to be filled out before submission.
Once the submit button is tapped, an asynchronous task starts which allows for the multipart upload to the server.
The asynchronous upload uses a callback function to notify the user of the upload progress.
I'm getting stuck in the transition between #3 and #4.
If I use a Thread or AsyncTask
The Intent chooser will remain open, but the image will also be displayed on the form.
If I simply force the user to wait (serially)
The user is stuck looking at a black screen, then the Intent Chooser closes and the image is displayed on the form.
Opening the Intent chooser
/**
* see http://stackoverflow.com/a/12347567/940217
*/
private void openImageIntent() {
// Camera.
final List<Intent> cameraIntents = new ArrayList<Intent>();
final PackageManager packageManager = getPackageManager();
Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile;
try {
uploadableImage.makeCameraTempFile();
photoFile = uploadableImage.getCameraTempFile();
uploadableImage.setCameraFilepath(photoFile.getAbsolutePath());
} catch (IOException ex) {
// Error occurred while creating the File
photoFile = null;
uploadableImage.invalidate();
Log.e(TAG, "Error while creating the temporary file needed for image capture from camera.");
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null && packageManager != null) {
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
for (ResolveInfo res : listCam) {
// Create the File where the photo should go
if (res.activityInfo == null) {
continue;
}
final String packageName = res.activityInfo.packageName;
final Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
cameraIntents.add(intent);
}
} else {
Toast.makeText(this, "Could not make temporary file.", Toast.LENGTH_LONG).show();
}
// Filesystem.
final Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
// Chooser of filesystem options.
final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source");
// Add the camera options.
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[cameraIntents.size()]));
startActivityForResult(chooserIntent, REQUEST_IMAGE_CAPTURE);
}
onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {
if (tempUpFile != null){
tempUpFile.invalidate();
}
if (data == null) {
Log.d(TAG, "Data was null -- source was from camera");
uploadableImage.preserveCameraFile();
setPic();
} else {
Uri selectedImageUri = data.getData();
if (selectedImageUri == null) {
Log.e(TAG, "An error that should never occur has occurred -- selectedImageUri was null when trying to get the data from the Image Capture activity result.");
Toast.makeText(this, "Unexpected error when trying to get an image from the gallery or file manager.", Toast.LENGTH_LONG).show();
return;
}
uploadableImage.setSourceImageUri(selectedImageUri, imageButton);
setPic(); // only do this if doing this serially.
}
} else if (resultCode == RESULT_CANCELED){
uploadableImage.invalidate();
if (tempUpFile != null){
uploadableImage = tempUpFile;
}
setPic();
}
}
UploadableImage#setSourceImageUri
public void setSourceImageUri(Uri selectedImageUri, final ImageView iView) {
// Important!! - clean up after ourselves!
deleteFile(this.cameraFile);
this.cameraFile = null;
InputStream tempInStream = null;
OutputStream tempOutStream = null;
try {
this.cacheFile = createFile();
tempInStream = context.getContentResolver().openInputStream(selectedImageUri);
tempOutStream = new FileOutputStream(this.cacheFile);
} catch (IOException e) {
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
if (tempInStream == null || tempOutStream == null){
Toast.makeText(context, "Error while trying to "+(tempInStream == null ? "read" :"store")+" the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "Error while trying to get the " + (tempInStream == null ? "input" : "output") + " stream");
return;
}
// Works, but makes the UI hang on a black screen while waiting for the resource.
try {
copy(tempInStream, tempOutStream);
}catch (IOException e){
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
/*
// Works, but leaves the IntentChooser open
final InputStream inStream = tempInStream;
final OutputStream outStream = tempOutStream;
new Thread(new Runnable() {
public void run() {
try {
copy(inStream, outStream);
// FIXME: somehow notify/display the bitmap in the UI
// --maybe use Message and Handler? callback Interface?
} catch (IOException e) {
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
}
}).start();
*/
}
Edit:
I've found that this will/will not occur depending on API level.
Does not occur:
KitKat (Nexus 4)
ICS MR1 (emulator)
Does occur:
KitKat (emulator)
ICS MR1 (Galaxy Tab 10.1)
Edit 2:
Here are some screenshots of what should not happen; images are from KitKat emulator.
Start the Activity
Select an image from the gallery or some other resource
The onActivityResult returns and the chooser remains open
This is how it should look after onActivityResult
Feeling pretty stupid, but I found the solution.
The issue was in step two: "The Intent chooser automatically opens..."
In order to do this, I was checking to see if a bitmap was available, and if it wasn't then it should display the placeholder image and then open the Intent chooser. I had this logic inside the onStart method which normally gets run after onActivityResult. However, because this was all happening asynchronously, I could not rely on this order.
What I had to do was put in a boolean flag which could tell me if we were waiting for a bitmap, and then not open the chooser if we were.
I'm new to android. Now, i'm doing image capturing function using:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE );
The problem is after I capture my photo, the new captured photo does not display on the image display page.
Does anyone here know where there is code that can help me refresh my android or any step that I need to do so that my image display page can be updated once I capture a new photo?
Any help would be very appreciated and many thanks to you first.
Updated answer:
I use this, may be this can help others:
mScanner = new MediaScannerConnection(
Camera.this,
new MediaScannerConnection.MediaScannerConnectionClient() {
public void onMediaScannerConnected() {
mScanner.scanFile(outputFileUri.getPath(), null /* mimeType */);
}
public void onScanCompleted(String path, Uri uri) {
//we can use the uri, to get the newly added image, but it will return path to full sized image
//e.g. content://media/external/images/media/7
//we can also update this path by replacing media by thumbnail to get the thumbnail
//because thumbnail path would be like content://media/external/images/thumbnail/7
//But the thumbnail is created after some delay by Android OS
//So you may not get the thumbnail. This is why I started new UI thread
//and it'll only run after the current thread completed.
if (path.equals(outputFileUri.getPath())) {
mScanner.disconnect();
//we need to create new UI thread because, we can't update our mail thread from here
//Both the thread will run one by one, see documentation of android
Camera.this
.runOnUiThread(new Runnable() {
public void run() {
}
});
}
}
});
mScanner.connect();
Sally, did you mean that after you take a photo you don't see it in the gallery or file-manager when you look at the directory you know the file to be in?
If so, you need to run the media-scanner like this:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
... where uri is the uri of the photo, since you know it already, although you can use the uri of the directory instead if that's easier (though it is slower - potentially very slow if the directory contains many files or nested directories).
you should take photo using below code::
Calendar cal = Calendar.getInstance();
File file = new File(Environment.getExternalStorageDirectory(),(cal.getTimeInMillis()+".jpg"));
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
selectedImageUri = Uri.fromFile(file);
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, selectedImageUri);
startActivityForResult(i, CAMERA_RESULT);
and on activity result you can use these code:::
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CAMERA_RESULT:
if (resultCode == RESULT_OK) {
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), selectedImageUri);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
You can refresh your activity with :
Intent myIntent = getIntent();
finish();
startActivity(myIntent);
Hi I am using this piece of code for camera in my activity.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == TAKE_PICTURE_WITH_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
// To Write the Images in SDCard
File f = new File(imgName);
try {
Uri capturedImage = Uri
.parse(android.provider.MediaStore.Images.Media
.insertImage(getContentResolver(),
f.getAbsolutePath(), null, null));
Log.i("camera",
"Selected image: " + capturedImage.toString());
pic.setImageURI(capturedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
Log.i("Camera", "Result code was " + resultCode);
}
}
}
I am trying to apply the image captured to my ImageView. The first time, the camera takes a picture and sets it to the ImageView. But when I run it for the second time, my app is not able to set the newly captured image to the imageView. It crashes after returning from the camera intent. How can I solve this?
Any help is appreciated.
In order to avoid this kind of error, the bitmap has to be scaled first. I have tried the below piece of code and it works fine.
bm1=Bitmap.createScaledBitmap(bm, 300, 300,true);
pic.setImageBitmap(bm1);
bm.recycle();
bm=null;
When reading about Camera, I think it is Hardware. Hardware always is using its own Thread. Perhaps you need to create a memory copyied image and serve it by dispatcher. I do not know your code but I am interested in receiving it to help you.
http://blog.lieberlieber.com/2009/07/09/controlinvoke-wpf-style-and-special-bitmapsource-handling/
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/f0c5e590-8bfe-4452-a784-4987af9fce89/