Multiple imageView refreshing in Android using asynctasks? - android

what I have to do is to play videos on a single activity, the number of videos is undefined, could be from 1 to 8, a video in my case is an image sequence, where every image is downloaded from a cam on the internet using a fixed time interl.
Do a single video activity is not a problem, I can make it using ImageView and a AsyncTask, using many instances of this method when I try to make multiple videos activities does not work, only one of the video plays. I don't know exactly what it happens but I think it could be a cuncurrency related issue due to the UIThread.
Here the used AsyncTask code:
private class AsyncTask_LiveView extends AsyncTask<String, Integer, Void>
{
private String sImageMessage = "";
private final WeakReference<ImageView> imageViewReference;
private Bitmap bmImage = null;
private String url = "";
private String usr = "";
private String pwd = "";
private utils u = new utils();
public AsyncTask_LiveView(ImageView imageView, String Url, String Usr, String Pwd)
{
imageViewReference = new WeakReference<ImageView>(imageView);
url = Url;
usr = Usr;
pwd = Pwd;
}
// automatically done on worker thread (separate from UI thread)
#Override
protected Void doInBackground(final String... args)
{
while(!isCancelled())
{
if(isCancelled())
return null;
SystemClock.sleep(200);
Log.v("ImageDownload","test");
bmImage = u.DownloadBitmapFromUrl(url, usr, pwd);
publishProgress(0);
}
return null;
}
// can use UI thread here
#Override
public void onProgressUpdate(Integer... i)
{
Log.v("Image", "Setup Image");
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bmImage);
}
}
}
}
I start the AsyncTasks in this way:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layoutliveviewdouble);
this.imgV1 = (ImageView ) findViewById(R.id.imageView1);
aTaskImgV1 = new AsyncTask_LiveView(imgV1,
URL1,
"",
"");
this.imgV2 = (ImageView ) findViewById(R.id.imageView2);
aTaskImgV2 = new AsyncTask_LiveView(imgV2,
URL2,
"root",
"jenimex123");
aTaskImgV1.execute();
aTaskImgV2.execute();
}
The DownloadBitmapFromUrl method is:
public Bitmap DownloadBitmapFromUrl(String imageURL, final String usr, final String pwd) { //this is the downloader method
try {
URL url = new URL(imageURL);
/* Open a connection to that URL. */
HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
ucon.setRequestMethod("GET");
ucon.setDoOutput(true);
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication (usr, pwd.toCharArray());
}
});
ucon.connect();
/*
* Define InputStreams to read from the URLConnection.
*/
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
ByteArrayBuffer baf = new ByteArrayBuffer(100000);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
/* Convert the Bytes read to a String. */
Bitmap bmp = BitmapFactory.decodeByteArray(baf.toByteArray(), 0, baf.length());
return bmp;
} catch (Exception e) {
//Log.d("ImageManager", "Error: " + e);
return null;
}
}
Any Ideas?
Solution : (21/01/11)
The bounch of lines:
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication (usr, pwd.toCharArray());
}
});
were braking the mechanism. In fact only one credentials pair a could have been set globally, and the other download processes stucked in requesting using the wrong credentials.
The solution is:
String authString = usr + ":" + pwd;
byte[] authEncBytes = Base64.encode(authString.getBytes(), Base64.DEFAULT);
String authStringEnc = new String(authEncBytes);
ucon = (HttpURLConnection) url.openConnection();
if(_usr != "")
ucon.setRequestProperty("Authorization", "Basic " + authStringEnc);
Thanks to all.

I think yuo should use unique AsyncTask_LiveView for each ImageView.

Does this function support multiple threads?
bmImage = u.DownloadBitmapFromUrl(url, usr, pwd);

It looks like some of the methods you call in downloadBitmapFromUrl(..) method involve synchronization by some common object. Try adding some extra logging to each part of this method and see where each thread gets stuck. I would do it this way:
public Bitmap downloadBitmapFromUrl(String imageURL, final String usr, final String pwd) { //this is the downloader method
try {
...
Log.i(toString() + " in " + Thread.currentThread(), "is about to open connection...");
HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
Log.i(toString() + " in " + Thread.currentThread(), "has opened connection");
...
and so on.

Related

AsyncTask not actually async

I have a threading issue. When I try to write in TextView percentage of successful download, it doesn't update it at all, until the end (until all content received) and it just show 100 at the end.
Seems like it is not actually running in another thread...
I tried to use logging in console instead of using publishProgress, and it works. It seems like MainActivity is frozen until the download task is done.
public class DownloadTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... urls) {
String result = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection)url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int count = 0;
int size = 0;
while (reader.read() != -1) {
size++;
}
urlConnection = (HttpURLConnection)url.openConnection();
in = urlConnection.getInputStream();
reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
int progress = (int) (((float) count++ / (float) size) * 100);
publishProgress(progress);
data = reader.read();
}
return result;
}
catch(Exception e) {
e.printStackTrace();
return "Failed";
}
}
#Override
protected void onProgressUpdate(Integer... values) {
textView.setText((values[0]).toString());
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text);
DownloadTask task = new DownloadTask();
String result = null;
try {
result = task.execute("https://stackoverflow.com/").get();
}
catch (Exception e) {
e.printStackTrace();
}
Log.i("Contents Of URL", result);
}
Any help please?
You're using the get method in the ASyncTask, as per the docs.
Waits if necessary for the computation to complete, and then retrieves
its result.
That means you told the async task to run sincronously.
To have it running async, don't use the get method.
task.execute("https://stackoverflow.com/")
And use the onPostExecute to retrieve the result:
protected void onPostExecute(String result) {
}

Running multiple async tasks returns task to wrong handler

I create several picture objects that each download their own image. But frequently, the same image shows up for several (or all) of the objects.
public class Picture {
private String userID;
private String fileName;
private String baseURI;
private Bitmap img;
public Picture () {
this.userID = "";
this.fileName = "";
this.baseURI = "";
}
/**
* Retrieves the UUID of the User
*
* #return - String
*/
public String getUserID() {return userID;}
public void setUserID(String _userID) {userID = _userID;}
/**
* Retrieves the Filename of the Picture
*
* #return - String
*/
public String getFileName() {return fileName;}
public void setFileName(String fileName) {
this.fileName = fileName;
//Don't retrieve a file from the server if the filename is empty or it is a placeholder
if (fileName != "" && fileName != "NoNewPicure" && fileName != "NewPicture") {
new RetrieveImageTask(getFileNameURI(), img) {
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
setPreview(result);
}
}.execute();
}
}
private URI getFileNameURI() {
return URI.create(baseURI.concat(fileName));
}
private void setBaseURI(String baseURI) {
this.baseURI = baseURI;
}
/**
* Accesors for preview image
* #return - Image
*/
#Bindable
public Bitmap getPreview() {return img;}
public void setPreview(Bitmap img) {
this.img = img;
notifyPropertyChanged(BR.preview);
}
private static class RetrieveImageTask extends AsyncTask<URI, Void, Bitmap> {
static URI uriString;
static Bitmap myBitmap;
private Exception exception;
RetrieveImageTask(URI uri, Bitmap bitmap) {
uriString = uri;
this.myBitmap = bitmap;
}
protected Bitmap doInBackground(URI... src) {
try {
Log.e("src",uriString.toString());
URL url = new URL(uriString.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
Log.e("Bitmap","returned");
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
Log.e("Exception",e.getMessage());
return null;
}
}
protected void onPostExecute(Bitmap result) {
//Do nothing
}
}
}
In code the images are called from a for loop:
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
Picture pic = new Picture();
pic.fromJSON(json_data);
result.add(pic);
}
It appears as though when the Async task returns, several (or all) of the handlers fire. Any ideas on how to fix this? I've tried adding in this:
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
URI thisURI = getFileNameURI();
if (uriString.equals(thisURI)) {
setPreview(result);
}
}
But then only one Picture object actually gets an image.
The answer was quite simple after hearing Another brick in the wall. You can't have any pudding if you don't eat your meat! I can't have my bitmap if the file hasn't downloaded. But I CAN put my bowl where the pudding is going to be so that after I eat my meat, I can eat my pudding. I changed my AsynTask like such:
private class RetrieveImageTask extends AsyncTask<URI, Void, Boolean> {
public URI uriString;
public Picture pic;
RetrieveImageTask(URI uri) {
uriString = uri;
}
protected Boolean doInBackground(URI... src) {
try {
Log.e("src",uriString.toString());
URL url = new URL(uriString.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
Log.e("Bitmap","returned");
pic.setPreview(bitmap);
return true;
} catch (IOException e) {
e.printStackTrace();
Log.e("Exception",e.getMessage());
return null;
}
}
protected void onPostExecute() {
//Do nothing
}
}
Note the public variables in the class wrapper. Now when I call my task (code changed from above):
RetrieveImageTask task = new RetrieveImageTask(getFileNameURI());
task.pic = this;
task.execute();
my bowl will be where the pudding is going to be. IE. I put the calling object as a variable in the private AsyncTask class which populates what I need when it is finished running. :D My bowl of pudding is full after I eat my meat!!!!

SSL certificate with imageView on Android Studio

I want to show picture that obtain from URLlink but I stuck in problem that's not trust in this URLlink. Then, it don't show anythings on screen. So, this is my Oncreate's code.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
Bitmap bmp = null;
ImageView imgView =(ImageView)findViewById(R.id.imageView);
String imageUrl = "10.34.250.12/api/config/v1/maps/imagesource/domain_0_1500368087062.jpg";
imgView.setImageBitmap(GetBitmapfromUrl("https://httpbin.org/image/png"));
imgView.setTag("10.34.250.12/api/config/v1/maps/imagesource/domain_0_1500368087062.jpg");
new DownloadImagesTask().execute(imgView);
}
and this is DownloadImageTask's code.
class DownloadImagesTask extends AsyncTask<ImageView, Void, Bitmap> {
ImageView imageView = null;
#Override
protected Bitmap doInBackground(ImageView... imageViews){
this.imageView = imageViews[0];
return download_Image((String)imageView.getTag());
}
#Override
protected void onPostExecute(Bitmap result){
imageView.setImageBitmap(result);
}
private Bitmap download_Image(String url){
Bitmap bmp = null;
try{
URL urln = new URL(url);
HttpURLConnection con = (HttpURLConnection)urln.openConnection();
String UserCredentials = "dev : dev12345";
String basicAuth = Base64.encodeToString(UserCredentials.getBytes(), Base64.NO_WRAP);
// String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes);
con.setRequestProperty ("Authorization", basicAuth);
con.setRequestMethod("GET");
// con.setUseCaches(false);
// con.setDoInput(true);
// con.setDoOutput(true);
InputStream is = con.getInputStream();
bmp = BitmapFactory.decodeStream(is);
return bmp;
}
catch (Exception e){}
return bmp;
}
}
thanks for every helps .
For https your may cast the result of openConnection to HttpsURLConnection
If you using untrust ssls you may create a X509Certificate with your keystore to use in the application, or create a X509 that ignores all certificates

android.os.NetworkOnMainThreadException in AsyncTask's doInBackground

Why do I get in an AsyncTask which should a android.os.NetworkOnMainThreadException? I thought that an AsyncTask is the solution to that problem. The exxeption is on line 7.
private class ImageDownloadTask extends AsyncTask<String, Integer, byte[]> {
#Override
protected byte[] doInBackground(String... params) {
try {
URL url = new URL(params[0]);
URLConnection connection = url.openConnection();
InputStream inputStream = connection.getInputStream();
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
} catch (IOException ex) {
return new byte[0];
}
}
}
I want to use it for downloading a picture.
public byte[] getProfilePicture(Context context, String id) {
String url = context.getString(R.string.facebook_picture_url_large, id);
ImageDownloadTask task = new ImageDownloadTask();
return task.doInBackground(url);
}
By calling doInBackground() directly, you are not actually using the AsyncTask functionality. Instead, you should call execute() and then use the results by overriding the AsyncTask's onPostExecute() method as explained in the Usage section of that same page.
Best way to download an image and attach it to a ImageView is passing the ImageView as the parameter in your async task and set the URL as a tag of the image view then after downloading the task in the OnPostExecute() set the image to the ImageView look at this example :
public class DownloadImagesTask extends AsyncTask<ImageView, Void, Bitmap> {
ImageView imageView = null;
#Override
protected Bitmap doInBackground(ImageView... imageViews) {
this.imageView = imageViews[0];
return download_Image((String)imageView.getTag());
}
#Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
private Bitmap download_Image(String url) {
...
}
And the Usage will be like this
ImageView mChart = (ImageView) findViewById(R.id.imageview);
String URL = "http://www...someImageUrl ...";
mChart.setTag(URL);
new DownloadImageTask.execute(mChart);
The image will be attached automatically when done, for more memory optimization you could use WeakReference.
Good Luck.

Android Thumbnail Loading Problem

I'm using a thumbnail loader in my project the one mentioned below. The problem is that the it loads all the thumbnails properly except the ones who's size is of about 40K. When our back end is giving that sort of thumbnails are not generated and sometimes this eventually leads to a Crash too.
What m I supposed to do with this ?
public class ThumbnailManager
{
private final Map<String, Bitmap> drawableMap;
public static Context context;
private Resources res;
private int thumbnail_size;
public ThumbnailManager()
{
drawableMap = new HashMap<String, Bitmap >();
res = new Resources(context.getAssets(), null, null);
thumbnail_size = res.getInteger(R.ThumbnailManager.THUMBNAIL_SIZE);
}
public Bitmap fetchBitmap(String urlString)
{
if(drawableMap.containsKey(urlString))
{
return (drawableMap.get(urlString));
}
//Log.d(getClass().getSimpleName(), " Image URL :: "+ urlString);
try
{
InputStream is = fetch(urlString);
android.util.Log.v("ThumbnailManager", "ThumbnailManager " + urlString);
drawableMap.put(urlString, BitmapFactory.decodeStream(is));//Bitmap.createScaledBitmap(BitmapFactory.decodeStream(is), thumbnail_size, thumbnail_size, false));
return drawableMap.get(urlString);
}
catch(Exception e)
{
android.util.Log.v("EXCEPTION", "EXCEPTION" + urlString);
return null;
}
}
public void fetchBitmapOnThread(final String urlString, final ImageView imageView)
{
if(drawableMap.containsKey(urlString))
{
imageView.setImageBitmap(drawableMap.get(urlString));
return;
}
if(urlString.compareTo("AUDIO") == 0)
{
Bitmap audioThumb = BitmapFactory.decodeResource(context.getResources(), R.drawable.timeline_audio_thumb);
drawableMap.put(urlString, Bitmap.createScaledBitmap(audioThumb, thumbnail_size, thumbnail_size, false));
imageView.setImageBitmap(drawableMap.get(urlString));
return;
}
final Handler handler = new Handler()
{
public void handleMessage(Message message)
{
imageView.setImageBitmap((Bitmap) message.obj);
}
};
Thread thread = new Thread()
{
public void run()
{
Bitmap urlBitmap = fetchBitmap(urlString);
Message message = handler.obtainMessage(1, urlBitmap);
handler.sendMessage(message);
}
};
thread.start();
}
public InputStream fetch(String urlString) throws IOException, MalformedURLException
{
final URL url = new URL(urlString);
final URLConnection conn = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(true);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
return(conn.getInputStream());
}
}
It would be great if you added a stacktrace here. But I suspect its an memory issue too. If you are loading lots of bitmaps into memory, they require much more memory than the original filesize. Ex. your thumbnail that is 40k could be 400k as a bitmap, It depends on the resolution. Use ddms and watch how much free memory your app is steeling. If it get less then 2MB of working memory, the BitmapFactory is likly to make a RuntimeException when decoding your large thumb.

Categories

Resources