android getContentResolver().insert() occasionally returning null - android

I have a piece of code that aims to launch the android camera, let the user take a photo and eventually keep the uri of the image once it is saved.
So far I have managed to get it working. However, it seems like a 50/50 chance that the app will crash with a NPE. I have no idea why this is happening
my code:
private Uri mImageCaptureUri;
private void doTakePhotoAction() {
String fileName = "temp.jpg";
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
mImageCaptureUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
startActivityForResult(intent, PICK_FROM_CAMERA);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case PICK_FROM_CAMERA:
String[] projection = { MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery(mImageCaptureUri, projection, null, null, null);
int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String capturedImageFilePath = cursor.getString(column_index_data);
Intent intent = new Intent(this, CropImage.class);
intent.putExtra("image-path", capturedImageFilePath);
intent.putExtra("scale", true);
startActivity(intent);
break;
}
}
The NPE error refers me back to the line
Cursor cursor = managedQuery(mImageCaptureUri, projection, null, null, null);
and it is being thrown because mImageCaptureUri is null. Does anyone have any ideas on how to fix / work around this or why this is in fact happening

You really have to take to heart the first rule of Android Activities: Android may decide at any time to kill your activity, resetting all member variables in the process. It will simply rebuild the activity once it needs to handle onActivityResult... but as you initialized mImageCaptureUri in your specific handler, it will now be null.
The classic cause in your example would be an orientation change during the launched "capture an image" activity (orientation changes will typically kill the activity), but there is a myriad of other reasons why android would decide to terminate it (lack of memory, incoming calls, phone having a bad hair day, etc).
The solution is to store and restore state like mImageCaptureUri in onSaveInstanceState(), and restore it in the onCreate() of the Activity, i.e.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState != null)
{
mImageCaptureUri = savedInstanceState.getParcelable("imageCaptureUri");
}
}
protected void onSaveInstanceState(Bundle outState)
{
outState.putParcelable("imageCaptureUri", mImageCaptureUri);
}

Related

Intent extras are null when picking an image from gallery

I have been researching on this but I am not able to find an answer for this.
I am picking an image from the gallery using media store intent and I am able to get the image file path in onActivityResult method. (I know how to get the URI in the intent and filepath).
I am passing in some intent extras on starting the activity (startActivityForResult) but all the intent extras are null.
Code snippets (in case):
This is my onActivityResult code which is working and i get the image path
/* On activity result from image button */
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
System.out.println("Result Code" + resultCode);
if(requestCode == FavoriteListAdapter.IMAGE_PICK_CODE && data != null && data.getData() != null && resultCode == FragmentActivity.RESULT_OK) {
Uri _uri = data.getData();
//User had pick an image.
Cursor cursor = getContentResolver().query(_uri, new String[] { android.provider.MediaStore.Images.ImageColumns.DATA }, null, null, null);
cursor.moveToFirst();
//Link to the image
String imageFilePath = cursor.getString(0);
System.out.println("imagefilepath" + imageFilePath);
System.out.println(data.getStringExtra("exp"));
cursor.close();
}
}
I am starting my activity with startActivityForResult
Intent imageIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imageIntent.setType("image/*");
imageIntent.putExtra("exp", "testing");
((FragmentActivity)view.getContext()).startActivityForResult(imageIntent, IMAGE_PICK_CODE);
I should be able to get the string "testing" in onActivityForResult but all I get is null.
Any ideas and suggestions will be appreciated. THnkas a lot.
Actually I figured it out .. When you are sending an intent to a system activity like MediaStore or the camera etc... the onActivityResult will not have the intent extras you sent while calling the activity.
This is probably by design and will only contain the extras given by the system activity. For instance after picking an image from the gallery, the returning intent from the gallery will only the URI containing the image path.
Same goes to camera or any system activites.

Playing a file in android mediaplayer

I want to play a video file recorded to be played in the mediaplayer of android.I want to call the media player through the intent and want to play the corresponding file of the passed uri.When I was trying I am getting an exception ActivityNotFound can anyone help me with a code.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_VIDEO_CAPTURED) {
uriVideo = data.getData();
Toast.makeText(VedioRecording.this, uriVideo.getPath(),
Toast.LENGTH_LONG).show();
}
} else if (resultCode == RESULT_CANCELED) {
uriVideo = null;
Toast.makeText(VedioRecording.this, "Cancelled!", Toast.LENGTH_LONG)
.show();
}
if (requestCode == 2) {
selectedImageUri = data.getData();
// OI FILE Manager
filemanagerstring = selectedImageUri.getPath();
// MEDIA GALLERY
selectedImagePath = getPath(selectedImageUri);
Intent intent1 = new Intent(android.provider.MediaStore.INTENT_ACTION_MUSIC_PLAYER).setData(selectedImageUri);
startActivityForResult(intent1, 3);
// videoviewPlay.setVideoURI(selectedImageUri);
// videoviewPlay.start();
}
if (requestCode == 3) {
}
}
private String getPath(Uri uri) {
String[] projection = { MediaStore.Video.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if (cursor != null) {
// HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
// THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} else {
return null;
}
}
}
this is my code i am geting activitynotfound exception
The most common scenario in which you get an ActivityNotFound exception is when you attempt to launch an Activity you have created without declaring it in the manifest.
Post your code that you use to launch the Activity to be sure. If you're trying to use an activity that should be provided by the framework externally from your application, you may just be setting up the Intent incorrectly
Update after code posted...
Your code seems to be using the intent action INTENT_ACTION_MUSIC_PLAYER and passing an image url as data (is it the path to an image or are your variables just misnamed?). You get an ActivityNotFoundException because the system doesn't have any intent receivers registered to handle that scenario. Also, if you look at the documentation for this constant, you'll see that they marked it deprecated at some point:
http://developer.android.com/reference/android/provider/MediaStore.html#INTENT_ACTION_MUSIC_PLAYER
I would normally use Intent.ACTION_VIEW and pass a mime type along with the data. Something like the following...
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(pathToVideoFile), "video/*");
startActivity(intent);
By passing the mime type of "video/*" to setDataAndType, you're being more specific with your request to the system.
If you want to query the system to find out if an Intent can be handled (meaning that the user's device running your code has an Activity registered that can handle the Intent), you can use the PackageManager.queryIntentActivities method:
queryIntentActivities
String extension = MimeTypeMap
.getFileExtensionFromUrl(selectedImagePath);
String mimeType = MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(extension);
Intent mediaIntent = new Intent(Intent.ACTION_VIEW);
mediaIntent.setDataAndType(Uri.parse(selectedImagePath),
mimeType);
startActivity(mediaIntent);
this is the code that helped me

How can I use the camera in Droid X by Android application

In my two to three application I have to used camera activity from application. User taken the picture using camera and set that image on image View.
It works for all devices excepting Droid X. When the user takes the picture from Droid X mobile, application is forced close.
Here is my code for start camera activity:
public void startCameraActivity()
{
_path = Environment.getExternalStorageDirectory() + "/default.jpg";
File file = new File( _path );
Uri outputFileUri = Uri.fromFile( file );
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra( MediaStore.EXTRA_OUTPUT, outputFileUri );
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_PIC_REQUEST) {
_taken = true;
bita = BitmapFactory.decodeFile( _path);
imv.setImageBitmap(bita);
}
}
So what should I do to run camera activity successfully in Droid X? I wasn't able to find what the problem is.
The issue here is not a memory issue as Andro has commented on this, and other similar postings.
The issue is simply related to how the Droid X camera intent differs from other devices's.
In my case, I was receiving a NullPointerException when attempting to grab my specified URI that I passed to the camera as using "intent.putExtra( MediaStore.EXTRA_OUTPUT, imageUri );". Some device camera's do not take in this extra properly, and those cases need to be handled separately. (see accepted answer here).
Also in my case, with a Droid X running 2.3.3, the returned intent was null as well. My debugger would detach during the camera intent, indicating that there was something wrong outside of my control. The best I could do is follow the accepted answer here.
So I added a capture for when my desired imageUri is null, and since my returned intent was null, I added logic to grab the most recent photo taken (using this as an example).
if ( imageUri == null ) {
String[] projection = new String[] { MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, MediaStore.Images.ImageColumns.DATE_TAKEN, MediaStore.Images.ImageColumns.MIME_TYPE };
final Cursor cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC" );
int column_index = cursor.getColumnIndexOrThrow( MediaStore.Images.Media.DATA );
cursor.moveToFirst();
fileUri = cursor.getString( column_index );
}
I hope this helps!

Android: No Application perform this action, why?

i want to browse all Audio files, but i am getting error like No application can perform this action.. this is my code for browse activity...
--> private static final int SELECT_MUSIC = 1;
String selectedImagePath;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.browse)).setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("music/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select File"), SELECT_MUSIC);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_MUSIC) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
}
}
}
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.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
and i have also added permission to menifest file:: READ_PHONE_STATE
what's problem? any idea?
Thanks..
It means that No Application perform that action. Why? because None of the installed Applications perform that action. It has nothing to do with permissions.
You are probably running this on an emulator, which does not include any directory browser application.
The setType method is working with MIME type values only.
If you really just need the handling of music files "audio/" should be ok (as mentioned before). To be more flexible, you should try to detect the MIME code of the file.
Here is a code snippit how this may look like:
FileNameMap fileNameMap = URLConnection.getFileNameMap();
type = fileNameMap.getContentTypeFor("file://" + file.getPath());
Or (pre Gingerbread)
if (!file.getName().contains("."))
return null;
String ext = (String) file.getName().subSequence(
file.getName().lastIndexOf(".") + 1,
file.getName().length());
MimeTypeMap mimeMap = MimeTypeMap.getSingleton();
type = mimeMap.getMimeTypeFromExtension(ext);
I usually use the combination of both methods (use the pre Gingerbread version if the first approach fails).
You can use:
intent.setType("audio/*"); instead of intent.setType("music/*");
Then you can choose a track, not a playlist.
Could you find a way to choose a playlist?
I have the same problem, looking for a way to open and choose a playlist.

Accessing Android native gallery via an intent

How can I get a user to select from the native gallery in Android, rather than other gallery-like applications such as ASTRO File Manager?
The following code gives a list of activities that can select an image:
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
List<ResolveInfo> infos = activity.getPackageManager().queryIntentActivities(intent, 0);
If I then do something like this:
activity.startActivityForResult(Intent.createChooser(intent, "Select Picture"), REQUEST_CHOOSE_IMAGE);
then if the user has more than one application that can act like a gallery (such as ASTRO File Manager), s/he is prompted to select one of them, with no "set as default" option.
I don't want the user to be prompted to choose between them each time, so I'd like to just use the native gallery.
The hacky code sample below uses a whitelist to test for known native gallery names:
for (ResolveInfo info : infos) {
if ( 0==info.activityInfo.name.compareTo("com.cooliris.media.Gallery")
|| 0==info.activityInfo.name.compareTo("com.htc.album.CollectionsActivity")
) {
// found the native gallery
doSomethingWithNativeGallery();
}
}
Feels kinda dirty. Is there a better way? I suspect I'm missing something in my intent.
I didn't get last part of your code.
To start the native gallry what i did is -
public void upload(){
Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
photoPickerIntent.setType("image/jpg");
photoPickerIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/Pictures/image.jpg"));
startActivityForResult(photoPickerIntent, 1);
}
Call the upload() where you like to start the native gallery.
Then to get that image info i did -
/**
* Retrieves the returned image from the Intent, inserts it into the MediaStore, which
* automatically saves a thumbnail. Then assigns the thumbnail to the ImageView.
* #param requestCode is the sub-activity code
* #param resultCode specifies whether the activity was cancelled or not
* #param intent is the data packet passed back from the sub-activity
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_CANCELED) {
return;
}
else if(resultCode == RESULT_OK) {
Uri uri = intent.getData();
String path = getPath(uri);
Log.i("PATH", path);
data = path;
return;
}
uplad();
}
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);
}
If you wouldn't get your answer, clear what you like to do

Categories

Resources