Grab video thumbnail and show it in a Gridview in android - android

I am developing a module for which i want to show all the user's videos from sd card into a Gridview. I have grabbed video file paths in usual way (Checking if file or directory and save if its a file) in a arraylist and grabbed its bitmap thumbnail with following code:
Bitmap bmThumbnail = ThumbnailUtils.createVideoThumbnail(VideoValues.get(position).getAbsolutePath(),
Thumbnails.MINI_KIND);
Obviously this code runs in a background thread. But the only problem is that the gribview still freezes a lot while scrolling. According to me the main problem is extracting the bitmap from video, which takes a lot of time. Can anyone suggest me a different way to get bitmap from video and how it in a grid ? I have seen the smooth behavior in other apps like Facebook, etc. But I cannot figure out as to how that can be done.

please use below method for retrive video thumbnail from video
#SuppressLint("NewApi")
public static Bitmap retriveVideoFrameFromVideo(String videoPath)
throws Throwable
{
Bitmap bitmap = null;
MediaMetadataRetriever mediaMetadataRetriever = null;
try
{
mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime();
}
catch (Exception e)
{
throw new Throwable(
"Exception in retriveVideoFrameFromVideo(String videoPath)"
+ e.getMessage());
}
finally
{
if (mediaMetadataRetriever != null)
{
mediaMetadataRetriever.release();
}
}
return bitmap;
}

Related

Not getting full length of bytes from the Video

I'm trying to save the frame of the image from the live stream video. So, I'm able to show live stream video from my android application as well as saving it in my local storage. Now, I want to use some sort of delay in my saveImage function so that images get saved after some specific time. I have used both Handler and TimerTask. The image is getting saved in my local directory after some delay but the length of the image that I get is sometimes very small, the other time normal. I want my saved image to exactly the length of the video stream that I am getting in my application.
I hope the question I asked is easy to understand. I am a beginner in both android and stack overflow.
P.S - I used mjpeg library for showing the video. The video I am getting is from an IP Camera.
Code for saving the images
public void saveImage(){
try {
photo =
new File(Environment.getExternalStorageDirectory(),
"Download/photos/photo" + Instant.now().getEpochSecond() + ".jpg");
if (photo.exists()) {
photo.delete();
}
System.out.println("Photo " + photo);
FileOutputStream fos = new FileOutputStream(photo.getPath());
System.out.println("Image_length" +image.length);
fos.write(image);
fos.close();
} catch (IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
Code where saveImage is called
final Bitmap outputImg = BitmapFactory.decodeByteArray(image, 0, image.length);
if (outputImg != null) {
if (run) {
newFrame(outputImg);
// Saving frames in internal Storage
new Timer().schedule(
new TimerTask() {
#Override
public void run() {
saveImage();
}
},5000
);
}
} else {
Log.e(tag, "Read image error");
}

Set thumbnail to an Intent for VideoView

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.

The most efficient way to show the local image in android

I am currently work on a magazine like apps. Since there is an option to zoom in(150%, 200%, 250% of original source) , I would prefer not to scale down the image. However , the app will force restart when I try to decode the image because of the out of memory. Are there any suggestion to fix that?
The image are local (SD card) , can be retrieve in any approach, but eventually need to be a bitmap as I use something like cavans.drawbitmap to display it. I tried, input stream-> bytes , input stream->bitmap etc... but are there any most efficient way or at least
I can sure the app does not force restart / close? Thanks
try {
InputStream is = (InputStream) new URL(url).getContent();
try {
return BitmapFactory.decodeStream(is);
} finally {
is.close();
}
} catch (Exception e) {
return BitmapFactory.decodeResource(context.getResources(), defaultDrawable);
}
You should consider using nostra's image loader, it deals with memory quite efficiently, you can specify lots of config stuffs, im using it and its working pretty well for large images aswell
This is what smartImageView(by loopj - you can find him on http://loopj.com/) uses to retrieve files from the drive/sd.
private Bitmap getBitmapFromDisk(String imgID) {
Bitmap bitmap = null;
if(diskCacheEnabled){
String filePath = getFilePath(imgID);
File file = new File(filePath);
if(file.exists()) {
bitmap = BitmapFactory.decodeFile(filePath);
}
}
return bitmap;
}

how to capture listview data as Jpg image

i need to capture listview data and convert it into jpg or png image format , then saved into sd card. I captured only the data which is visible in the screen , but i am unable to capture the data which is avaialble in the scrollview.
So, please guide me guide me how to implement this.
i am using the following code to capture the visible data.
View v1=btnCapture.getRootView();
public void gettingRootView(View v1)
{
if( v1 != null)
{
v1.setDrawingCacheEnabled(true);
v1.buildDrawingCache();
Bitmap bm = v1.getDrawingCache();
try
{
if ( bm != null )
{
Log.e("file","filepath");
savePhoto(bm);
}
}
catch(Exception e){e.printStackTrace();}
}
}
public void savePhoto(Bitmap bmp)
{
Log.e("save photo","save photo");
File fileFolder=new File(Environment.getExternalStorageDirectory(),"SMSREADING");
fileFolder.mkdir();
Calendar c=Calendar.getInstance();
try
{
File fileName=new File(fileFolder,c.getTimeInMillis()+".jpg");
FileOutputStream output=new FileOutputStream(fileName);
bmp.compress(Bitmap.CompressFormat.PNG,100,output);
}
catch(Exception ex){
ex.printStackTrace();
}
}
You can create HTML from your data using one of the many templating libraries out there like, if you have a String list Apache's Velocity might work well. After you create your HTML you can use java-html2image to convert your html to an image.

creating a drawable from sd card to set as a background in android

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

Categories

Resources