I'm fetching a single image for a single person. Everything goes well but if there is no image in the database I get an exception (my app crashes). I do handle this with a else statement but it doesn't seem to work.
Here is the code:
private void Get_Image_From_Database(DataBaseHelper db,String query)// GET_IMAGE
{
Bitmap bitmap=null;
SQLiteDatabase db1 = db.getReadableDatabase();
Cursor c=db1.rawQuery(query, null);
if (c != null) {
if (c.moveToFirst())
{
do
{
byte[] blob = c.getBlob(0);
ByteArrayInputStream inputStream = new ByteArrayInputStream(blob);
bitmap = BitmapFactory.decodeStream(inputStream);
img.setImageBitmap(bitmap); // if there is a image it will render one
} while (c.moveToNext());
}
else{File imgfile=new File("/drawable/none.jpg"); //the else statement fails
Bitmap mybitmap=BitmapFactory.decodeFile(imgfile.getAbsolutePath());
img.setImageBitmap(mybitmap);}
}
}
My goal is to (as you can see) get a image from a database if exits and if not, then display a default image.
I suppose the drawable is in your resource inside of your project?
If yes, try this to get your drawable:
Drawable myDrawable = getResources().getDrawable(R.drawable.none);
img.setImageDrawable(myDrawable);
for loading images you can use universal imageLoader, it will also hellp you to cache the images
and it has a beautiful option
ex
options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisc(true)
.showImageOnLoading(R.drawable.placeholder)
.showImageForEmptyUri(R.drawable.placeholder)
.showImageOnFail(R.drawable.placeholder)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
as you can see if you dont have any image to display to can display the default image
If that image is in Drawable folder then just change your else part to
else
{
img.setImageResource(R.drawable.none);
}
I guess else part is at wrong place.
EDIT
If you're using try-catch block, then you can do like this in catch block
catch (Exception e)
{
img.setImageResource(R.drawable.none);
}
This solved my problem!
Thanx guys especially aniruddha!!
private void Get_Image_From_Database(DataBaseHelper db,String query)// GET_IMAGE
{
SQLiteDatabase db1 = db.getReadableDatabase();
Cursor c=db1.rawQuery(query, null);
c.moveToFirst();
if (c.isNull(0))
{
img.setImageResource(R.drawable.none);
}
else
{
byte[] blob = c.getBlob(0);
ByteArrayInputStream inputStream = new ByteArrayInputStream(blob);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
img.setImageBitmap(bitmap); // if there is a image it will render one
}
}
Related
I have to play a video in one of my screens of Android and I am using Video View intent for the same. The video gets played but there is no thumbnail appearing on the launch of the screen.
My code is like this
#OnClick(R.id.icon_play)
protected void playVideo(){
String videoUrl="https://someUrl/Video/v07.mp4";
if(!videoUrl.isEmpty()) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(videoUrl));
intent.setDataAndType(Uri.parse(videoUrl), "video/mp4");
startActivity(intent);
}
}
By thumbnail, I mean that when the screen is launched each video should have an image of its own. (something like YouTube)
I tried seekTo() for attaching the thumbnail, but it didn't work.
Please Help. Thanks.
I solve the problem using MediaMetaDataRetriever.
The code goes like this-
public static Bitmap retriveVideoFrameFromVideo(String videoPath)
throws Throwable
{
Bitmap bitmap = null;
MediaMetadataRetriever mediaMetadataRetriever = null;
try
{
mediaMetadataRetriever = new MediaMetadataRetriever();
if (Build.VERSION.SDK_INT >= 14)
mediaMetadataRetriever.setDataSource(videoPath, new HashMap<String, String>());
else
mediaMetadataRetriever.setDataSource(videoPath);
// mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime(-1,MediaMetadataRetriever.OPTION_CLOSEST);
}
catch (Exception e)
{
e.printStackTrace();
throw new Throwable(
"Exception in retriveVideoFrameFromVideo(String videoPath)"
+ e.getMessage());
}
finally
{
if (mediaMetadataRetriever != null)
{
mediaMetadataRetriever.release();
}
}
return bitmap;
}
Note that : Because my video link was in the form of server URL, that's why createThumnailUtils was returning a null when video Url was passed through it.
The below code works fine when the video is coming from local storage.
Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail("URL", MediaStore.Images.Thumbnails.MINI_KIND);
BitmapDrawable bitmapD = new BitmapDrawable(thumbnail);
VideoView.setBackground(Drawable bitmapD);
Hope this helps someone!!
Just looked at another example. Not 100% sure if it's going to work but worth a try.
Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail("URL", MediaStore.Images.Thumbnails.MINI_KIND);
BitmapDrawable bitmapD = new BitmapDrawable(thumbnail);
VideoView.setBackground(Drawable bitmapD);
Please note, I have written this over phone so there might be spelling errors.
Let me know if this works or if you find another alternative
this may be used i am using this method for thumbnail image of video on my list view of video player..
Cursor cursor = mContext.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, proj,
MediaStore.Video.Media.DISPLAY_NAME + "=?",
new String[]{localItem._display_name}, null);
cursor.moveToFirst();
long ids = cursor.getLong(cursor
.getColumnIndex(MediaStore.Video.Media._ID));
ContentResolver crThumb = mContext.getContentResolver();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap curThumb = MediaStore.Video.Thumbnails.getThumbnail(
crThumb, ids, MediaStore.Video.Thumbnails.MICRO_KIND,
options);
itemHolder.thumbImage.setImageBitmap(curThumb);
curThumb = null;
cursor.close();
try this way it may be helpful
above ans is now deprecated.
new updated answer with fast one solution
we just have to give the video data path
Bitmap bmThumbnail;
bmThumbnail = ThumbnailUtils.createVideoThumbnail(arraylist.get(i)._data, MediaStore.Video.Thumbnails.MICRO_KIND);
itemHolder.thumbImage.setImageBitmap(bmThumbnail);
where arraylist.get(i)._data => path of video.
and best way is to use Glide or any other image lodging async library for smooth scrolling of listview.
Recently Google added the Photos app for Google+ (plus) and it shows up when you launch an Intent to choose an image. However, if I select an image from Google+ Photos and try to use it in my application none of my current logic is able to return a usable URI or URL to actually get an image that I can download and manipulate. I'm currently using the "common" methods to try to manipulate the URI that can be found here on Stack Overflow and elsewhere. I can provide code if needed, but at this point I think it's kind of irrelevant since it works well for everything else except this new app. Any ideas on how to get a usable image?
The URI looks something like the following:
content://com.google.android.apps.photos.content/0/https%3A%2F%2Flh5.googleusercontent.com%<a bunch of letters and numbers here>
The MediaColumns.DATA info always returns null and the MediaColumns.DISPLAY_NAME always returns image.jpg no matter what I select from the Google Photos app. If I try to paste everything from https to the end in my browser, nothing comes up. Not sure how to get usable info from this.
When receiving the data intent, you should use the contentResolver to get the photos.
Here's what you should do:
String url = intent.getData().toString();
Bitmap bitmap = null;
InputStream is = null;
if (url.startsWith("content://com.google.android.apps.photos.content")){
is = getContentResolver().openInputStream(Uri.parse(url));
bitmap = BitmapFactory.decodeStream(is);
}
I did faced issues selecting images from new Google Photos app. I was able to resolve it by below code.
It works for me, basically what i did is i am checking if there is any authority is there or not in content URI. If it is there i am writing to temporary file and returning path of that temporary image. You can skip compression part while writing to temporary image
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);
}
P.S. : I have answered a similar question here
You have to use projection in order to get ImageColumns.DATA (or MediaColumns.DATA):
private String getRealPathFromURI(Uri contentURI) {
// Projection makes ContentResolver to get needed columns only
String[] medData = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(contentURI, medData, null, null, null);
// this is how you can simply get Bitmap
Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), contentURI);
// After using projection cursor will have needed DATA column
cursor.moveToFirst();
final int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
So I have the following code in an AsyncTask. The AsyncTask takes in a url to an image file, downloads it into a Bitmap, saves the Bitmap off to disk somewhere, and then displays the Bitmap in an existing ImageView.
Here's the implementation of the doInBackground() call for my AsyncTask:
protected Bitmap doInBackground(String... urls) {
try {
URL image_url = new URL(urls[0]);
String image_url_prefix_regex = "http://www\\.somewebsite\\.com";
if (externalStorageIsAvailable()) {
String file_path = getExternalFilesDir(null).getPath() + image_url.toString().replaceAll(image_url_prefix_regex, "");
File target_file = new File(file_path);
if (!target_file.getParentFile().exists()) {
target_file.getParentFile().mkdirs();
}
BitmapFactory.Options bitmap_options = new BitmapFactory.Options();
bitmap_options.inScaled = false;
bitmap_options.inDither = false;
bitmap_options.inPreferredConfig = Bitmap.Config.ARGB_8888;
bitmap_options.inPreferQualityOverSpeed = true;
bitmap_options.inSampleSize = 1;
Bitmap image = BitmapFactory.decodeStream(image_url.openStream(), null, bitmap_options);
image.compress(CompressFormat.JPEG, 100, new FileOutputStream(target_file));
return image;
}
}
catch (MalformedURLException e) {
Log.v(DEBUG_TAG, "Error: Caught MalformedURLException");
}
catch (IOException e) {
Log.v(DEBUG_TAG, "Error: Caught IOException");
}
return null;
}
Then later in the onPostExecute() call I have this:
protected void onPostExecute(Bitmap image) {
ImageView mImageView = (ImageView) findViewById(R.id.main_image);
mImageView.setImageBitmap(image);
}
Yet when the code downloads and displays the image, the image is reduced in size and quality. How do I make it so that the resulting image is full quality? Those BitmapFactory.Options settings are the things I've tried thus far, but they did not seem to work.
Note that I'm not asking about the image that gets saved to external storage. I think that one will likely be of lower quality due to getting compressed again, but that shouldn't affect the image I'm sending to my ImageView, which is what I'm asking about. Of course, if there's anything wrong with these assumptions please point them out.
Why you are using Bitmap factory options while decoding bitmap Stream ?
Just use the
Bitmap image = BitmapFactory.decodeStream(image_url.openStream());
instead of
Bitmap image = BitmapFactory.decodeStream(image_url.openStream(), null, bitmap_options);
I am trying to use an image from the sd card and set it as the background for a relativelayout. I have tried other solutions that i have found here and elsewhere but they havent seemed to work for me. here is my code. I have commented out other ways that i have tried and didnt work. the only thing that worked for me was using setBackgroudnResource and using a resource from the app, but this was just to test to make sure mRoot was set up correctly. when I have tried all the other ways, it just doesn't set anything. Anyone know what I am doing wrong, or if there is a better way to do this?
//one way i tired...
//String extDir = Environment.getExternalStorageDirectory().toString();
//Drawable d = Drawable.createFromPath(extDir + "/pic.png");
//mRoot.setBackgroundDrawable(d);
//another way tried..
//Drawable d = Drawable.createFromPath("/sdcard/pic.png");
//mRoot.setBackgroundDrawable(d);
//last way i tried...
mRoot.setBackgroundDrawable(Drawable.createFromPath(new File(Environment.getExternalStorageDirectory(), "pic.png").getAbsolutePath()));
//worked, only to verify mRoot was setup correctly and it could be changed
//mRoot.setBackgroundResource(R.drawable.bkg);
You do not load a drawable from SD card but a bitmap. Here is a method to load it with the reduced sampling (quality) so the program will not complain if the image is too large. Then I guess you need to process this bitmap i.e. crop it and resize for the background.
// Read bitmap from Uri
public Bitmap readBitmap(Uri selectedImage) {
Bitmap bm = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; //reduce quality
AssetFileDescriptor fileDescriptor =null;
try {
fileDescriptor = this.getContentResolver().openAssetFileDescriptor(selectedImage,"r");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
finally{
try {
bm = BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(), null, options);
fileDescriptor.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bm;
}
The Uri here can be supplied from a gallery picker activity.
The image then can be saved into application resources and loaded into an imageView
private void saveBackground(Bitmap Background) {
String strBackgroundFilename = "background_custom.jpg";
try {
Background.compress(CompressFormat.JPEG, 80, openFileOutput(strBackgroundFilename, MODE_PRIVATE));
} catch (Exception e) {
Log.e(DEBUG_TAG, "Background compression and save failed.", e);
}
Uri imageUriToSaveCameraImageTo = Uri.fromFile(new File(BackgroundSettings.this.getFilesDir(), strBackgroundFilename));
// Load this image
Bitmap bitmapImage = BitmapFactory.decodeFile(imageUriToSaveCameraImageTo.getPath());
Drawable bgrImage = new BitmapDrawable(bitmapImage);
//show it in a view
ImageView backgroundView = (ImageView) findViewById(R.id.BackgroundImageView);
backgroundView.setImageURI(null);
backgroundView.setImageDrawable(bgrImage);
}
File file = new File( url.getAbsolutePath(), imageUrl);
if (file.exists()) {
mDrawable = Drawable.createFromPath(file.getAbsolutePath());
}
I suggest checking that the drawable is being loaded correctly. Some things to try:
Try using a different image on the sd card
Put pic.png in R.drawable and make sure mRoot.setBackgroundResource() does what you expect
After loading the drawable, check d.getBounds() to make sure it is what you expect
Query to MediaStore.Video.Media.EXTERNAL_CONTENT_URI returns only video in /sdcard/DCIM/100MEDIA
But I want to get thumbnails for video in my /sdcard/Android/data/mypackage/files folder. Is it possible ?
Here is part of my code:
ContentResolver cr = getContentResolver();
String[] proj = {
BaseColumns._ID
};
Cursor c = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, proj, null, null, null);
if (c.moveToFirst()) {
do
{
int id = c.getInt(0);
Bitmap b = MediaStore.Video.Thumbnails.getThumbnail(cr, id, MediaStore.Video.Thumbnails.MINI_KIND, null);
Log.d("*****My Thumbnail*****", "onCreate bitmap " + b);
ImageView iv = (ImageView) findViewById(R.id.img_thumbnail);
iv.setImageBitmap(b);
}
while( c.moveToNext() );
}
c.close();
If you are on android-8 (Froyo) or above, you can use ThumbnailUtils.createVideoThumbnail:
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
Use Glide it will fetch the thumbnail in async.
Glide.with(context)
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
3 ways to get a thumbnail from a video:
The best way is to use Glide. It will do all the work in the background, load the thumbnail right into the ImageView and even can show animation when loading. It can work with Uri, byte[] and many other sources.
As #Ajji mentioned:
Glide.with(context)
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
If you just need a bitmap in the most efficient way - use ThumbnailUtils.
In my case, it produced a bitmap with a size of 294 912 bytes (video taken with a camera of Nexus5X - 1280x720) and the quality was the same as in the next approach. After you compress into JPEG with 90 it will generate a jpeg file of ~30Kb.
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
The last approach is to use MediaMetadataRetriever. But in my case, it produced a bitmap with size more than 6 times bigger than you got with ThumbnailUtils (with the same quality). So consider it as a last resort.
MediaMetadataRetriever mMMR = new MediaMetadataRetriever();
mMMR.setDataSource(mContext, mAttachment.getUri());
bmp = mMMR.getFrameAtTime();
P.S.: Don't forget that images in Bitmap, byte[] and real file .jpeg formats can be easily converted in any direction within these types. In case of Uri's you often don't have real path to the source file but you can always get the byte stream from it like this:
InputStream in = mContext.getContentResolver().openInputStream(uri);
and with this input stream you can do whatever you want.
You can just use FFmpegMediaMetadataRetriever and forget the reflection:
/**
*
* #param path
* the path to the Video
* #return a thumbnail of the video or null if retrieving the thumbnail failed.
*/
public static Bitmap getVideoThumbnail(String path) {
Bitmap bitmap = null;
FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();
try {
fmmr.setDataSource(path);
final byte[] data = fmmr.getEmbeddedPicture();
if (data != null) {
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
}
if (bitmap == null) {
bitmap = fmmr.getFrameAtTime();
}
} catch (Exception e) {
bitmap = null;
} finally {
fmmr.release();
}
return bitmap;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmapThumb = MediaStore.Video.Thumbnails.getThumbnail(mActivity.getContentResolver(),
Long.parseLong(video_id),
Images.Thumbnails.MINI_KIND,
options);
Use Options to load bitmap of decrease the bitmap size..
see #Ajji 's answer :
Glide.with(context)
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
It sometimes returns black image, this issue is already mentioned in Glide library's issues
Use this code:
BitmapPool bitmapPool = Glide.get(activity).getBitmapPool();
int microSecond = 6000000;// 6th second as an example
VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
Glide.with(activity)
.load(videoPath)
.asBitmap()
.override(50,50)// Example
.videoDecoder(fileDescriptorBitmapDecoder)
.into(holder.ivFirstUpload);
Get video thumbnail from VIDEO_ID:
public static Drawable getVideoThumbnail(Context context, int videoID) {
try {
String[] projection = {
MediaStore.Video.Thumbnails.DATA,
};
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(
MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI,
projection,
MediaStore.Video.Thumbnails.VIDEO_ID + "=?",
new String[] { String.valueOf(videoID) },
null);
cursor.moveToFirst();
return Drawable.createFromPath(cursor.getString(0));
} catch (Exception e) {
}
return null;
}
Here is a similar answer to Matthew Willis but with added reflection. Why? because science.
/**
*
* #param path
* the path to the Video
* #return a thumbnail of the video or null if retrieving the thumbnail failed.
*/
public static Bitmap getVidioThumbnail(String path) {
Bitmap bitmap = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
bitmap = ThumbnailUtils.createVideoThumbnail(path, Thumbnails.MICRO_KIND);
if (bitmap != null) {
return bitmap;
}
}
// MediaMetadataRetriever is available on API Level 8 but is hidden until API Level 10
Class<?> clazz = null;
Object instance = null;
try {
clazz = Class.forName("android.media.MediaMetadataRetriever");
instance = clazz.newInstance();
final Method method = clazz.getMethod("setDataSource", String.class);
method.invoke(instance, path);
// The method name changes between API Level 9 and 10.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD) {
bitmap = (Bitmap) clazz.getMethod("captureFrame").invoke(instance);
} else {
final byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance);
if (data != null) {
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
}
if (bitmap == null) {
bitmap = (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance);
}
}
} catch (Exception e) {
bitmap = null;
} finally {
try {
if (instance != null) {
clazz.getMethod("release").invoke(instance);
}
} catch (final Exception ignored) {
}
}
return bitmap;
}
If you are directly creating thumbnails as follows
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
Then there is a problem with this method if your are creating thumbnails for large video set(for large number of videos). the application will freeze until all the thumbnails are loaded because all the process are executing in the main thread.
Use SuziLoader
This loader will load the thumbnails for the videos which is locally stored on your filesystem in background.
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/video.mp4";
ImageView mThumbnail = (ImageView) findViewById(R.id.thumbnail);
SuziLoader loader = new SuziLoader(); //Create it for once
loader.with(MainActivity.this) //Context
.load(path) //Video path
.into(mThumbnail) // imageview to load the thumbnail
.type("mini") // mini or micro
.show(); // to show the thumbnail
To get this dependency use the following steps
Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency
dependencies {
compile 'com.github.sushinpv:SuziVideoThumbnailLoader:0.1.0'
}
ADD READ EXTERNAL STORAGE Permission in manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Try something similar to this code snippet:
img.setImageBitmap(ThumbnailUtils.createVideoThumbnail(
Environment.getExternalStorageDirectory().getPath() + "/WhatsApp/Media/WhatsApp Video/"+getItem(position),
MediaStore.Video.Thumbnails.FULL_SCREEN_KIND));
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.VideoColumns.DATA };
Cursor c = getContentResolver().query(uri, projection, null, null, null);
int vidsCount = 0;
if (c != null) {
vidsCount = c.getCount();
while (c.moveToNext()) {
String path = c.getString(0);
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
}
c.close();
}
You can use this method with any Uri:
public static Bitmap getVideoFrame(Uri uri, Context context) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(context, uri);
return retriever.getFrameAtTime();
}