My code,
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();
} catch (Exception e) {
e.printStackTrace();
throw new Throwable(
"Exception in retriveVideoFrameFromVideo(String videoPath)"
+ e.getMessage());
} finally {
if (mediaMetadataRetriever != null) {
mediaMetadataRetriever.release();
}
}
return bitmap;
}
This is Create thumbnail but take much time I used this with ListView then ListView being hangup.
You need run this task in Async Method Like this in onBindViewHolder() if you are using RecycleView or put on getView() if your are using ListView:
new AsyncTask<String, String, String>() {
Bitmap bitmapVideo;
#Override
protected String doInBackground(String... strings) {
try {
//Your method call here
bitmapVideo =retriveVideoFrameFromVideo(strings[0]);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String id) {
super.onPostExecute(id);
if (bitmapVideo != null) {
//Load your bitmap here
holder.imgVideoThumb.setImageBitmap(bitmapVideo);
}
}
}.execute(getYourVideolink());
For better efficiency you save the bitmap image in local and before calling AsyncTask() check weather this image is already save in local if its their than load from local and no new to run AsyncTask() again
Related
I am trying to change the wallpaper of Android every 15 minutes or something like this. A user can choose the time and I am running a periodic work using Workmanager.
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(SomeWorker.class, 15, TimeUnit.MINUTES).build();
WorkManager.getInstance().enqueue(periodicWorkRequest);
This way I am calling my Worker Class. The working class is this
public class SomeWorker extends Worker {
Context context = getApplicationContext();
private String URL;
#NonNull
#Override
public Result doWork() {
new FetchWallpaper().execute();
return Result.SUCCESS;
}
private class FetchWallpaper extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... voids) {
try
{
URL = "myurl.com";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL)
.build();
Response responses = null;
try {
responses = client
.newCall(request)
.execute();
String jsonData = responses.body().string();
JSONArray jsonArr = new JSONArray(jsonData);
JSONObject c = jsonArr.getJSONObject(new Random().nextInt(jsonArr.length()));
String imageUrl = c.getString("wallpaper");
Bitmap result= Picasso.with(getApplicationContext())
.load(imageUrl)
.get();
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
try {
wallpaperManager.setBitmap(result);
} catch (Exception ex) {
ex.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
Date currentTime = Calendar.getInstance().getTime();
}
catch (Exception e)
{
Date currentTime = Calendar.getInstance().getTime();
}
return null;
}
}}
On that Particular line,
new FetchWallpaper().execute();
I am getting the error saying it must call from the main thread. I am new to Android, I don't know if this is the good approach.
Please let me know if there is any better approach to perform such kind of task.
The Worker class already calls doWork on a background thread - you don't need to use AsyncTask at all.
Just move everything from your doInBackground method directly into the Worker's doWork.
You can not update UI from doInBackground method. If you want to do something on UI you must do that on Main UI thread. So write setBitmap code in onPostExecute method as onPostExecute on on Main UI Thread.
To do that set third parameter of AsyncTask as String
AsyncTask<Void, Void, String>
So that return type of doInBackground method will be String
protected String doInBackground(Void... voids)
...
...
return imageUrl;
}
And Your onPostExecute method will be like
#Override
protected void onPostExecute(String imageUrl) {
super.onPostExecute(imageUrl);
Bitmap result= Picasso.with(getApplicationContext())
.load(imageUrl)
.get();
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
try {
wallpaperManager.setBitmap(result);
} catch (Exception ex) {
ex.printStackTrace();
}
}
new AsyncTask<Void, Bitmap, Bitmap>() {
#Override
protected Bitmap doInBackground(Void... params) {
Bitmap bitmap = null;
try {
InputStream inputStream;
inputStream = new java.net.URL(url).openStream();
bitmap = BitmapFactory.decodeStream(inputStream);
}catch (Exception e) {
logAppE(TAG, "BITMAP ERROR -> " + e.getMessage());
}
return bitmap
}
#Override
protected void onPostExecute(Bitmap s) {
try {
Glide.with(context).asGif().load(s).into(imgViewGIF);
} catch (Exception e) {
logAppE(TAG, "BITMAP -> " + e.getMessage());
}
}
}.execute();
I have a ListView and I want to populate it with video form a URL. I can show Pictures in ListView adapter easily from URL, but how to load a video thumbnail?
You can use MediaMetadataRetriever to get your video thumbnail.
new AsyncTask<Void, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(Void... params) {
Bitmap bitmap = null;
String videoPath = "http://techslides.com/demos/sample-videos/small.mp4";
MediaMetadataRetriever mediaMetadataRetriever = null;
try {
mediaMetadataRetriever = new MediaMetadataRetriever();
if (Build.VERSION.SDK_INT >= 14)
// no headers included
mediaMetadataRetriever.setDataSource(videoPath, new HashMap<String, String>());
else
mediaMetadataRetriever.setDataSource(videoPath);
// mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mediaMetadataRetriever != null)
mediaMetadataRetriever.release();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (bitmap != null)
((ImageView) findViewById(R.id.your_image_id)).setImageBitmap(bitmap);
}
}.execute();
I was trying making OkHttp request in AsyncTask using call.execute() -- Synchronous call.
I have two buttons in my layout. Pressing button1 starts AsyncTask, that executes OkHttp request.call.execute().
And pressing button2, I just update a TextView.
Observation: While AsyncTask is running, I can not update TextView.
But, if I don't use AsyncTask and use OkHttpClient.newCall().enqueue() method,then I can update TextView by pressing button2.
Any answer for "Why using AsyncTask in this case not working"?
Source Code Sample:
bpost = (Button) findViewById(R.id.bpost);
bpost.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
i++;
tv.setText(""+i);
}
});
bstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
OkHttpHandler handler = new OkHttpHandler();
byte[] image = new byte[0];
try {
image = handler.execute(url).get();
if (image != null && image.length > 0) {
Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
imageView.setImageBitmap(bitmap);
tv.setText("Total btytes download: " + image.length);
}
} catch (Exception e) {
tv.setText("sorry, something went wrong!");
}
}
public class OkHttpHandler extends AsyncTask<String, Void, byte[]> {
OkHttpClient client = new OkHttpClient();
#Override
protected byte[] doInBackground(String... params) {
Request.Builder builder = new Request.Builder();
builder.url(params[0]);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
return response.body().bytes();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
This is because get() method of AsyncTask waits for the computation to finish in doInBackground method and then retrieves its result. See this link.
This will make your main UIThread in wait mode until doInBackground finish its execution or there is some exception occur(i.e. CancellationException,ExecutionException and InterruptedException).
You should use onPostExecute(Result) override method of AsyncTask.
private class OkHttpHandler extends AsyncTask<String, Void, byte[]> {
OkHttpClient client = new OkHttpClient();
#Override
protected byte[] doInBackground(String... params) {
Request.Builder builder = new Request.Builder();
builder.url(params[0]);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
return response.body().bytes();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(byte[] bytes) {
super.onPostExecute(bytes);
try {
if (bytes != null && bytes.length > 0) {
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
imageView.setImageBitmap(bitmap);
tv.setText("Total btytes download: " + bytes.length);
}
} catch (Exception e) {
tv.setText("sorry, something went wrong!");
}
}
}
I am writing an app with custom camera facility. In my custom camera after capturing i am drawing the captured image to canvas and providing free hand drawing over that captured imgae and then save option. At the time of saving i am save it as two images which means the one which contains free hand drawing and another one which contains no drawing. Saving is done by writing output stream and compressing bitmaps. The saving and compression of bitmaps done in two separate async tasks. The issue is that i can capture image up to 16 or 17 times but after that capturing and editing then pressing save button i am getting the exception "vm aborting Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1)" .
Async Task one
public class SaveOriginalImage extends AsyncTask<String, Void, String> {
OutputStream dataOutputStream;
Bitmap bitMapOriginalImage;
String fileName;
Activity activityContext;
ProgressDialog progressDialog;
String sbCaption;
String fileType;
public SaveOriginalImage(Bitmap bitMap, String filePath,
Activity currentActivity, String fileCaption) {
this.bitMapOriginalImage = bitMap;
this.fileName = filePath;
this.activityContext = currentActivity;
this.sbCaption = fileCaption;
}
#Override
protected String doInBackground(String... params) {
try {
dataOutputStream = new FileOutputStream(fileName);
bitMapOriginalImage
.compress(CompressFormat.PNG, 100, dataOutputStream);
Collection.lastImageFilePath = fileName;
dataOutputStream.flush();
dataOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
if (bitMapOriginalImage != null) {
bitMapOriginalImage.recycle();
bitMapOriginalImage = null;
}
}
}
Async Task 2
public class SaveFreeHandImage extends AsyncTask<String, Void, String> {
OutputStream dataOutputStream;
Bitmap bitMapToSave;
String fileName;
Activity activityContext;
ProgressDialog progressDialog;
String sbCaption;
String className;
String fileType;
public SaveFreeHandImage(Bitmap bitMap, String filePath,
Activity currentActivity, String fileCaption, String className) {
this.bitMapToSave = bitMap;
this.fileName = filePath;
this.activityContext = currentActivity;
this.sbCaption = fileCaption;
this.className = className;
}
#Override
protected String doInBackground(String... params) {
try {
dataOutputStream = new FileOutputStream(fileName);
bitMapToSave.compress(CompressFormat.PNG, 100, dataOutputStream);
Collection.lastImageFilePath = fileName;
try {
dataOutputStream.flush();
dataOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
// super.onPostExecute(result);
progressDialog.dismiss();
HomeFinal.showCustomToast("Drawing saved to SD card ", 0, 0,
activityContext);
Collection.isNewImageAdded = false;
DrawingView.colorD = Color.parseColor("#000000");
if (DrawingView.paths != null) {
if (DrawingView.paths.size() >= 1) {
DrawingView.paths.clear();
}
}
if (bitMapToSave != null) {
if (!bitMapToSave.isRecycled()) {
bitMapToSave.recycle();
bitMapToSave = null;
}
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(activityContext, "", "Saving..");
}
}
I am testing on lenovo a-300h 7 inch tablet . Please give me solution. Thanks in advance.
i solved myself. It is because of excess use of bitmaps, after handling bitmaps it worked perfectly.
I have an AsyncTask that gets favicon base on a URL.
I am creating a listView, that has a favicon and a URL. at the moment even though I have the AsyncTask my UI waits for the asyncTask to finish before it shows the next activity.
I would like my activity to start with a default image that is stored in drawable, and that the AsyncTask will replace the images after it got each favicon.
Any ideas how to do it?
my AsyncTask:
private class DownloadImageTask extends AsyncTask<URL, Void, Bitmap> {
final AccountListModel model = new AccountListModel(daoSession);
protected Bitmap doInBackground(URL... urls) {
URL urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
mIcon11 = model.getBitmapFromURL(urldisplay);
//try to get image
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
faviconBitmap=result;
}}
the way I am currently creating my list view
for (Site site : model.getSites()) {
try {
String url = site.getDomain()
faviconBitmap= new DownloadImageTask().execute(new URL("http", "www."+ url.trim(),"/favicon.ico")).get();
if (faviconBitmap != null) {
Bitmap scaled = Bitmap.createScaledBitmap(faviconBitmap,32, 32, true);
accountsAndUsersList.add(newAccountListScreen(scaled,site.getName());
}
}
else {
Bitmap icon = BitmapFactory.decodeResource(getResources(),R.drawable.favicon);
Bitmap scaled = Bitmap.createScaledBitmap(icon, 32, 32, true);
accountsAndUsersList.add(new AccountListScreen(scaled,site.getName());
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
sitesToSortArray = new AccountListScreen[accountsAndUsersList
.size()];
accountsAndUsersList.toArray(sitesToSortArray);
AccountListAdapter adapter = new AccountListAdapter(this,
R.layout.account_list_row, sitesToSortArray);
listViewAccountList = (ListView) findViewById(R.id.activityAccountList);
listViewAccountList.setAdapter(adapter);
please let me know if you would like to see my adapter as well.
Thank you!