All threads get suspended - android

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();
}

Related

Receiving image in Asynctask and display it in ImageView

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;
}

Experiencing choppyness when loading Bitmaps into ImageViews from AsyncTask. Looking for improvement pointers

I'm experiencing some choppyness when loading bitmaps into ImageViews from an AsyncTask.
I have a fragment in which I display information loaded from SQLite, and said information often times have photos attached. When my fragment is launched, it takes up to a second before it is displayed (the app appears to hang for a bit),
probably because of the heavy data loading, which tells me I might be doing something wrong.
Here is a stripped down version of my implementation:
public class InformationFragment extends Fragment {
private ArrayList<MyPhoto> mPhotos;
private LinearLayout mPhotoContainer;
private View mView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ....
mView = inflater.inflate(R.layout.fragment_information, container, false);
mPhotoContainer = (LinearLayout) mView.findViewById(R.id.fragment_information_photos_container);
return mView;
}
#Override
public void onResume() {
super.onResume();
loadInformation();
}
private void loadInformation() {
// Loads information from database and puts it into TextViews and such.
// Relatively performance heavy operations, should perhaps run off main, but it's not the cause
// of my problems as it was pretty smooth before I implemented photo attachments
}
private ArrayList<MyPhoto> getPhotos() {
// Loads photos from database. Not sure but could be pretty performance heavy, you tell me :)
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(mPhotoContainer.getChildCount() == 0) {
mPhotos = getPhotos();
for (MyPhoto p : mPhotos) {
addImageViewForPhoto(p);
}
}
}
private void addImageViewForPhoto(MyPhoto p) {
final ImageView iv = new ImageView(getActivity());
mPhotoContainer.addView(iv);
new MyPhotoLoaderTask(iv).execute(p.getBytes());
}
}
The following is the MyPhotoLoaderTask class
public class MyPhotoLoaderTask extends AsyncTask<byte[], Void, Bitmap> {
private final WeakReference<ImageView> mWeakImageView;
public MyPhotoLoaderTask(ImageView iv) {
mWeakImageView = new WeakReference<ImageView>(iv);
}
#Override
protected Bitmap doInBackground(byte[]... params) {
return MyPhotoUtils.createBitmap(params[0], 100, 100);
}
#Override
protected void onPostExecute(final Bitmap result) {
if(mWeakImageView != null && result != null) {
final ImageView iv = mWeakImageView.get();
iv.setImageBitmap(result);
}
}
}
And lastly, the MyPhotoUtils.createBitmap() method
public static Bitmap createBitmap(byte[] bytes, int reqWidth, int reqHeight) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
opts.inSampleSize = getInSampleSize(opts, reqWidth, reqHeight);
opts.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
}
I don't mind the fact that loading the images takes a while, but I would love for the fragment to load with all of the text information already present,
and then have the images appear one by one after the user has begun interaction with the fragment. The current situation is pretty bad in my opinion, and I fear it will become even worse if the user will attach even more photos to the information.

Android save data from nested AsyncTask onPostExecute after screen rotation

I have spent many hours looking for a solution to this and need help.
I have a nested AsyncTask in my Android app Activity and I would like to allow the user to rotate his phone during it's processing without starting a new AsyncTask. I tried to use onRetainNonConfigurationInstance() and getLastNonConfigurationInstance().
I am able to retain the task; however after rotation it does not save the result from onPostExecute() to the outer class variable. Of course, I tried getters and setters. When I dump the variable in onPostExecute, that it is OK. But when I try to access to the variable from onClick listener then it is null.
Maybe the code will make the problem clear for you.
public class MainActivity extends BaseActivity {
private String possibleResults = null;
private Object task = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.task = getLastNonConfigurationInstance();
setContentView(R.layout.menu);
if ((savedInstanceState != null)
&& (savedInstanceState.containsKey("possibleResults"))) {
this.possibleResults = savedInstanceState
.getString("possibleResults");
}
if (this.possibleResults == null) {
if (this.task != null) {
if (this.task instanceof PossibleResultWebService) {
((PossibleResultWebService) this.task).attach();
}
} else {
this.task = new PossibleResultWebService();
((PossibleResultWebService) this.task).execute(this.matchToken);
}
}
Button button;
button = (Button) findViewById(R.id.menu_resultButton);
button.setOnClickListener(resultListener);
}
#Override
protected void onResume() {
super.onResume();
}
OnClickListener resultListener = new OnClickListener() {
#Override
public void onClick(View v) {
Spinner s = (Spinner) findViewById(R.id.menu_heatSpinner);
int heatNo = s.getSelectedItemPosition() + 1;
Intent myIntent = new Intent(MainActivity.this,
ResultActivity.class);
myIntent.putExtra("matchToken", MainActivity.this.matchToken);
myIntent.putExtra("heatNo", String.valueOf(heatNo));
myIntent.putExtra("possibleResults",
MainActivity.this.possibleResults);
MainActivity.this.startActivityForResult(myIntent, ADD_RESULT);
}
};
private class PossibleResultWebService extends AsyncTask<String, Integer, Integer> {
private ProgressDialog pd;
private InputStream is;
private boolean finished = false;
private String possibleResults = null;
public boolean isFinished() {
return finished;
}
public String getPossibleResults() {
return possibleResults;
}
#Override
protected Integer doInBackground(String... params) {
// quite long code
}
public void attach() {
if (this.finished == false) {
pd = ProgressDialog.show(MainActivity.this, "Please wait...",
"Loading data...", true, false);
}
}
public void detach() {
pd.dismiss();
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(MainActivity.this, "Please wait...",
"Loading data...", true, false);
}
#Override
protected void onPostExecute(Integer result) {
possibleResults = convertStreamToString(is);
MainActivity.this.possibleResults = possibleResults;
pd.dismiss();
this.finished = true;
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (this.possibleResults != null) {
outState.putString("possibleResults", this.possibleResults);
}
}
#Override
public Object onRetainNonConfigurationInstance() {
if (this.task instanceof PossibleResultWebService) {
((PossibleResultWebService) this.task).detach();
}
return (this.task);
}
}
It is because you are creating the OnClickListener each time you instantiate the Activity (so each time you are getting a fresh, new, OuterClass.this reference), however you are saving the AsyncTask between Activity instantiations and keeping a reference to the first instantiated Activity in it by referencing OuterClass.this.
For an example of how to do this right, please see https://github.com/commonsguy/cw-android/tree/master/Rotation/RotationAsync/
You will see he has an attach() and detach() method in his RotationAwareTask to solve this problem.
To confirm that the OuterClass.this reference inside the AsyncTask will always point to the first instantiated Activity if you keep it between screen orientation changes (using onRetainNonConfigurationInstance) then you can use a static counter that gets incremented each time by the default constructor and keep an instance level variable that gets set to the count on each creation, then print that.

How to add at a main layout an imageView controlled from another thread?

I'm making an app for Android. I have reached my goal with the single main thread pushing a button!!! (show an image saved on the SD in an ImageView) But I need to do it with threading to save some time and because I will make other threads.
The problem when I do this on a new thread a warning appears that tells me:
"Only the original thread that created a view hierachy can touch its
views."
And the Image is not opened.
Here is this code:
public class intsocketclient extends Activity implements OnClickListener{
public ImageView imagen;
private Button connectPhones;
private Handler conectarhandler = null;
private Runnable conectarunner = null;
public boolean condicion = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imagen = (ImageView) findViewById(R.id.imagen);
connectPhones = (Button) findViewById(R.id.connect_phones);
connectPhones.setOnClickListener(this);
conectarhandler = new Handler();
conectarunner = new Runnable() {
public void run() {
conectayenvia();
conectarhandler.post(this);
}
};
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub.
if(v==connectPhones) {
new Thread (conectarunner).start();
}
}
public void conectayenvia () {
if (condicion){
condicion = false;
Bitmap bMap = BitmapFactory.decodeFile("/sdcard/recibido.jpg");
imagen.setImageBitmap(bMap);
}
}
}
But I really need it to be this way.
Is it possible to take the main layout (the original "main.xml") and some kind of "add" over it another main file (a "threadmain.xml" which only contains the imageView)but also with the capability of pushing buttons and other kind of things of the first original "main.xml" layout????????
use AsyncTask, as it will handle threads automatically, the preExecute and postExecute methods of AsyncTask run on UI thread.
private class DF extends AsyncTask<Void, Void, Void>{
private Bitmap bMap;
#Override
protected Void doInBackground(Void... params) {
if (condicion){
condicion = false;
bMap = BitmapFactory.decodeFile("/sdcard/recibido.jpg");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
imagen.setImageBitmap(bMap);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
}
call the asyncTask in onClick.
#Override
public void onClick(View v) {
// TODO Auto-generated method stub.
if(v==connectPhones) {
new DF().execute();
}
}
Your problem is that you're trying to run UI methods not on the UI thread. The solution is to call runOnUiThread from the other thread.

Create slideshow without mouselistener

I am new in android and I want to create slideshow without any listener, I mean I would like open my app and see just animation with effect. I can't find examples or tutorials, anyone could help me? Thanks
If you want to do anything automatically without user interaction, than you have to use a backgroud thread. In Android you cannot call methods modifying the UI fron a background thread. As you plan on periodically updating the UI, you will be best off with AsynchTash.
private class SwitchImagesTask extends AsyncTask<Integer, Integer, Intehger> {
protected Long doInBackground(Integer... itemCount) {
for (int i = 0; i < itemCount[0]; i++) {
try{Thread.wait(1000);}catch(Exception e) {return -1;}
publishProgress(i);
}
return 1;
}
protected void onProgressUpdate(Integer... progress) {
// Display your image here
}
protected void onPostExecute(Integer result) {
// Say goodby to the user
}
}
If slide show means one image after another, than the easiest way to do this will be to add an ImageView to the layout, and change it's content.
if you call a activity, you can use layout inflator in inner class which extends thread.
public class SlideshowActivity extends Activity {
private static final int[] mSlides = new int[]{R.layout.layout_a , R.layout.layout_b , R.layout.layout_c};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new StartSlideShow().start();
}
class StartSlideShow extends Thread
{
#Override
public void run() {
LayoutInflater inflator = SlideshowActivity.this.getLayoutInflater();
for(int inx = 0 ; inx < mSlides.length ; inx++)
{
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
inflator.inflate(mSlides[inx], null);
}
}
}
}

Categories

Resources