I'm trying receive the image over TCP (in Asynctask) and display it in ImageView but I have an error in onPostExecute. Anyone know why?
And also whether idea of receiving is correct, if the next step will be recurring receiving image over TCP and displaying it?
Code:
public class TcpClient extends Activity {
ImageView imageView;
public static String aHost;
public String aSocketIn;
public static int aSocketInInt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bundle_result);
imageView = (ImageView) findViewById(R.id.imageView);
Intent intent = getIntent();
aHost = intent.getStringExtra("addressIp");
aSocketIn = intent.getStringExtra("socketIn");
aSocketInInt = Integer.parseInt(aSocketIn);
new DownloadImageTask(aHost,aSocketInInt).execute();
} }
public class DownloadImageTask extends AsyncTask <Void,Void,Bitmap > {
public Bitmap bitmap = null;
String Host;
int SocketIn;
public DownloadImageTask(String Host,int SocketIn) {
this.Host = Host;
this.SocketIn = SocketIn;
}
#Override
protected Bitmap doInBackground(Void... params) {
ClientIn clientIn;
try {
InetAddress serwerAddress = InetAddress.getByName(Host);
Socket socket = new Socket(serwerAddress, SocketIn);
clientIn = new ClientIn(socket);
bitmap = clientIn.Receive();
return bitmap;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result); // ERROR: Cannot resolve symbol 'imageView'
} }
Looks like DownloadImageTask class is not inner-class of TcpClient class which is extending Activity,so to access imageView object of ImageView in other class, need to send it on DownloadImageTask using class constructor in same way as doing currently for getting Host and SocketIn in DownloadImageTask class.
Change DownloadImageTask as for to using imageView "
public DownloadImageTask(String Host,int SocketIn,ImageView imageView) {
this.Host = Host;
this.SocketIn = SocketIn;
this.imageView=imageView;
}
Related
i am tring to download a few urls with Jsoup and then set them as source urls for image view with Picasso. but i had a lot of difficulty doing so.
then i decided to just send one single hardcoded url to picasso from jSoup class which resulted to an exception
here is the code for my MainActivity
package com.vsoft.tsubdl;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
public ImageView imageView;
public static ImageView imageView2;
ImageView imageView3;
ImageView imageView4;
String[] tinyurl = {"http://2tinysub.net/"};
JsonParser jsonParser;
ArrayList<ImageView> imageViewsArray;
public static Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView);
imageView2 = (ImageView) findViewById(R.id.imageView2);
imageView3 = (ImageView) findViewById(R.id.imageView3);
imageView4 = (ImageView) findViewById(R.id.imageView4);
mContext = this;
imageViewsArray = new ArrayList<>();
imageViewsArray.add(imageView);
imageViewsArray.add(imageView2);
imageViewsArray.add(imageView3);
imageViewsArray.add(imageView4);
jsonParser = new JsonParser();
try {
jsonParser.execute(tinyurl);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setImages(){
Picasso.with(MainActivity.mContext)
.load(jsonParser.theUrl)
.into(imageView);
}
this is my JsoupParser Activity
public class JsonParser extends AsyncTask<String,Void,String> {
public String[] URLS = {"","","",""};
public static String theUrl = "";
MainActivity mainActivity = new MainActivity();
#Override
protected String doInBackground(String... urls) {
try {
Document doc = Jsoup.connect("http://2tinysub.net/").get();
Elements links = doc.select(".box .details ul li");
Elements picURLS = doc.select(".details .poster img");
Element firsimage = picURLS.first();
theUrl = "https://i.jeded.com/i/now-you-see-me-2.135-52356.jpg";
} catch (Exception e) {
e.printStackTrace();
}
return theUrl;
}
#Override
protected void onPostExecute(String s) {
mainActivity.setImages();
}
}
i think it has something to do with the fact that i'm setting image in the setImage method.
i say this because it works fine if i do the picasso part after the Jsoup execute statement in the try block in Main Activity.
Now Please does any one has an answer for whats is wrong.
You're problem is that you're creating a new instance of MainActivity in your Asynctask: MainActivity mainActivity = new MainActivity();
There are a number of problems with this approach if you consider the activity lifecycle with your async task.. but to your question - For this particular case your async task just needs a reference to the Activity that starts it. You need to pass that into the async task, most likely in the constructor. If yo go that route please wrap your activity in a WeakReference so you don't cause memory pressure.
Here's what would fix it: (note that I didn't compile this so there might be typos)
public class JsonParser extends AsyncTask<String,Void,String> {
private WeakReference<MainActivity> mainActivityReference;
public JsonParser(MainActivity activity) {
mainActivityReference = new WeakReference(activity);
}
... <your other code>
#Override
protected void onPostExecute(String s) {
//Because the activity could be destroyed, don't store a hard reference to the activity
//Also you should probably check to make sure the activity is in a good state
MainActivity activity = mainActivityReference.get();
if(activity != null) {
activity.setImages();
}
}
I am building an app which will continuously get screenshots of my laptop screen and transfer it to my android app but there is some problem within the while loop, when I put a for loop to a limit then my program runs but as it goes till infinity or I replace it with infinite while loop my code suspends all the threads and app crash dueto memory allocation problem, please suggest me to execute my code infinite times so that there are continuous screenshots displayed.
Thank You.
Here is my code
public class ScreenActivity extends AppCompatActivity {
ImageView img;
int width,height;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen);
img=(ImageView)findViewById(R.id.imageView);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
// while (true)
for (int i=0;i<100;i++)
new GetImg().execute();
}
Bitmap imgscr;
public class GetImg extends AsyncTask<Object,Void,Bitmap> {
#Override
protected Bitmap doInBackground(Object[] params) {
Socket client= null;
try {
client = new Socket("192.168.1.5",6767);
InputStream in=client.getInputStream();
imgscr=Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), width, height, false);
} catch (Exception e) {
e.printStackTrace();
}
return imgscr;
}
#Override
protected void onPostExecute(Bitmap bm)
{
img.setImageBitmap(bm);
}
}
}
#m0skit0 commented the actual reason of getting the ANR. You're out of your run-time memory when you're creating threads in an infinite loop. I'm pretty confused about your purpose though. I think you need to get the screenshots one after one and if this is the case, you can simply add a listener to the AsyncTask and get the callback when the screenshot is downloaded fully.
So if I've understood correctly, you need to declare an interface like this.
public interface DownloadCompletedListener {
public void onDownloadComplete(String result);
}
Now you need to implement the interface in your Activity like this
public class ScreenActivity extends AppCompatActivity implements DownloadCompletedListener {
private GetImg getImageTask;
private Bitmap imageBitmap;
#Override
public void onDownloadComplete(String result) {
if(result.equals("SUCCESS")) {
// Set the image now
img.setImageBitmap(imageBitmap);
// Start next download here
getImageTask = new GetImg();
getImageTask.mListener = this;
getImageTask.execute();
} else {
// Do something
}
}
}
You need to modify your AsyncTask a bit. You need to declare the DownloadCompletedListener.
public class GetImg extends AsyncTask<Object,Void,Bitmap> {
private DownloadCompletedListener mListener;
#Override
protected Bitmap doInBackground(Object[] params) {
Socket client= null;
try {
client = new Socket("192.168.1.5",6767);
InputStream in=client.getInputStream();
imgscr=Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), width, height, false);
} catch (Exception e) {
e.printStackTrace();
}
return imgscr;
}
#Override
protected String onPostExecute(Bitmap bm)
{
imageBitmap = bm;
mListener.onDownloadComplete("SUCCESS");
}
}
So your onCreate function will look like this now
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen);
img=(ImageView)findViewById(R.id.imageView);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
// Start downloading image here. Remove the loop
getImageTask = new GetImg();
getImageTask.mListener = this;
getImageTask.execute();
}
I have this little piece of code and I want to achieve this: program should set a wallpaper from linked image.
ImgDownload:
public class ImgDownload extends AsyncTask {
private String requestUrl;
private ImageView view;
private Bitmap pic;
private ImgDownload(String requestUrl, ImageView view) {
this.requestUrl = requestUrl;
this.view = view;
}
#Override
protected Object doInBackground(Object... objects) {
try {
URL url = new URL(requestUrl);
URLConnection conn = url.openConnection();
pic = BitmapFactory.decodeStream(conn.getInputStream());
} catch (Exception ex) {
}
return null;
}
#Override
protected void onPostExecute(Object o) {
view.setImageBitmap(pic);
}
}
main
public class MainActivity extends Activity {
private ImageView img;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img= (ImageView)findViewById(R.id.img);
//!!!! This is where I am stuck :)
Object s = new ImgDownload("http://images1.wikia.nocookie.net/__cb20120402213849/masseffect/images/4/42/Uncharted_Worlds_Codex_Image.jpg",img );
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
How to instantiate/create this class in my mainActivity, so it could download img from link? Any help suggestions, thoughts, will be appreciated :)
You execute this AsyncTask like this:
ImgDownload downloader = new ImgDownload("http://images1.wikia.nocookie.net/__cb20120402213849/masseffect/images/4/42/Uncharted_Worlds_Codex_Image.jpg",img);
downloader.execute();
But I would not recommend using your code as it will produce memory leaks. For example try to rotate your device while it is downloading an image. I guarantee you your application will crash. Plus AsyncTask is a generic class. You could use that to make your code a little simpler. Here is my improved image download task:
public class ImgDownload extends AsyncTask<Void, Void, Bitmap> { // Use Generics
private final String requestUrl;
private final WeakReference<ImageView> imageViewReference; // Use WeakReference to prevent memory leaks
public ImgDownload(String requestUrl, ImageView view) {
this.requestUrl = requestUrl;
this.imageViewReference = new WeakReference<ImageView>(view);
}
#Override
protected Bitmap doInBackground(Void... objects) {
try {
URL url = new URL(requestUrl);
URLConnection conn = url.openConnection();
return BitmapFactory.decodeStream(conn.getInputStream()); // Return bitmap instead of using global variable
} catch (Exception ex) {
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
ImageView imageView = imageViewReference.get();
if(imageView != null && bitmap != null) { // Check if image or ImageView are null
imageView.setImageBitmap(bitmap);
}
}
}
new ImgDownload("http://images1.wikia.nocookie.net/__cb20120402213849/masseffect/images/4/42/Uncharted_Worlds_Codex_Image.jpg", MainActivity.img).execute();
I've been having problems with this for quite some time now. I'm getting there little by little but I don't have much time to spend programming :(
So I'm having to load image from URLs for showing on a list view, and i'm almost there. They are lazy loading and the cache system i'm using works good.
The problem is that the downloaded images are in the wrong place when I start scrolling and I can't figure out where i'm going wrong.
The code is inspired from these two links:
This one for the layout idea.
http://blog.blundell-apps.com/imageview-with-loading-spinner/
and this one for the cache system.
http://android-developers.blogspot.fr/2010/07/multithreading-for-performance.html
So here's my code:
public class LoaderImageView extends LinearLayout
{
private static final String TAG = "LoderImageView";
private Context mContext;
private ImageView mImage;
private ProgressBar mSpinner;
/* The HashMap that contains the references to the different
* downloads currently running.
*/
public static HashMap<LoaderImageView, BitmapDownloaderTask> tasks =
new LinkedHashMap<LoaderImageView, BitmapDownloaderTask>();
public LoaderImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = context;
mImage = new ImageView(mContext);
mImage.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mSpinner = new ProgressBar(mContext);
mSpinner.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mSpinner.setIndeterminate(true);
addView(mSpinner);
addView(mImage);
Log.w(TAG, "Loading an imageView");
}
public void downloadImage(String url)
{
resetPurgeTimer();
//Log.w(TAG, "Loading: " + url);
if(url.equals(""))
{
mImage.setImageDrawable(mContext.getResources().getDrawable(R.drawable.male));
}
else
{
Bitmap bitmap = getBitmapFromCache(url);
if(bitmap == null)
{
/* The bitmap is not in the cache. */
cancelPotentialDownload(this);
/* Start the new download. */
BitmapDownloaderTask bdt = new BitmapDownloaderTask(this, url);
bdt.execute();
}
else
{
/*The bitmap is in the cache. */
mImage.setImageBitmap(bitmap);
mSpinner.setVisibility(View.GONE);
}
}
}
class BitmapDownloaderTask extends AsyncTask<Void, Void, Bitmap>
{
private String mUrl;
private LoaderImageView mLiv;
public BitmapDownloaderTask(LoaderImageView liv, String url)
{
mLiv = liv;
mUrl = url;
}
#Override
protected void onPreExecute()
{
LoaderImageView.tasks.put(mLiv, this);
mSpinner.setVisibility(View.VISIBLE);
mImage.setVisibility(View.GONE);
Log.w(TAG, "Starting an AsyncTask");
}
#Override
protected Bitmap doInBackground(Void... voids)
{
URL url = null;
try
{
url = new URL(mUrl);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
return BitmapTools.fetchBitmap(url);
}
#Override
protected void onPostExecute(Bitmap bitmap)
{
BitmapDownloaderTask b = tasks.get(mLiv);
if(b == this)
{
LoaderImageView.tasks.remove(this);
mImage.setImageBitmap(bitmap);
}
if (isCancelled())
{
bitmap = null;
}
addBitmapToCache(mUrl, bitmap);
tasks.remove(mLiv);
mSpinner.setVisibility(View.GONE);
mImage.setVisibility(View.VISIBLE);
}
}
/* More methods related too the cache... */
Here the xml layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/list_item_selector" >
<com.myproject.liste.LoaderImageView
android:id="#+id/visites_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
</RelativeLayout>
I'm creating the list with a BaseAdapter and ListActivity.
Also i'm loading the list by pages of data: I load 10 items, when the user scrolls down I load 10 more, and call notifyDataSetChange();
i have this class:
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageFromWeb ifw;
private String url;
private final WeakReference<ImageView> imageViewReference;
public DownloadImageTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
#Override
protected Bitmap doInBackground(String... params) {
url = params[0];
try {
return BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(Bitmap result) {
if (isCancelled()) {
result = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(result);
}
}
}
#Override
protected void onPreExecute() {
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
---------> imageView.setImageResource(R.drawable.pw);
}
}
}
}
and the main activity:
public class ImageFromWeb extends Activity {
private String path = "http://....";
private ImageView imageView;
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main);
ImageView mChart = (ImageView) findViewById(R.id.imview);
mChart.setTag(path);
new DownloadImageTask(mChart).execute(path);
}
}
I want to put in the point of arrow(in DownloadImageTask class) an alert dialog! How can i do this? Because this class isn't an activity.
thanks :)
change the constructor and pass a Context object
Context mContext;
public DownloadImageTask(ImageView imageView,Context mContext) {
imageViewReference = new WeakReference<ImageView>(imageView);
this.mContext = mContext;
}
Now you can use this Context to create dialogs
You can even cast mContext to your Activity class and call functions within your Activity
Move the Async Task to your activity and use that to call your DownloadImageTask class & methods. This will make your life a lot easier.
pass a Activity instance to the class where you want to display dialog, and check
if(!actvity.isFinishing){
//show dialog
}
You can have a static Context in your Application like this:
public static Context CurrentContext;
and a custom abstract Activity that sets currentContext upon creation like this:
public abstract class CustomActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication.CurrentContext = this;
}
}
Then you would get context like this:
AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(MyApplication.CurrentContext);
dlgBuilder.setTitle("Context Example");
dlgBuilder.setMessage("I am being shown from the application Static context!");
dlgBuilder.setNeutralButton("Ok", null);
dlgBuilder.show();
This way you never have to worry about context wether you are in a background task or directly in an Activity it will work for most cases.
hope this helps!