I am a beginner in Android app dev. Recently I am trying to make a face detection app using FaceDetector.
In the code below is my main activity class. I have a Runnable to loop through a set of images, convert to bitmaps and send them to FaceOverlayView to find and draw faces. The loop can go through all 4 items.
However, as I tried to make it loop all over again by setting index to 0 after the last item, the app crashes. I observed the behavior that the app will crash trying to reload an image loaded before. Would you please give me any insight on this? Many thanks in advance.
public class MainActivity extends AppCompatActivity {
private FaceOverlayView mFaceOverlayView;
Handler handler;
Thread thread;
ArrayList<Integer> imgID = new ArrayList<Integer>(Arrays.asList(R.raw.face1, R.raw.face2, R.raw.face3, R.raw.face4));
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFaceOverlayView = (FaceOverlayView) findViewById(R.id.face_overlay);
thread = new Thread(new myThread());
thread.start();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.arg1 == -1) {
//thread.interrupt();
}
Bitmap bitmap = (Bitmap) msg.obj;
mFaceOverlayView.setBitmap(bitmap);
}
};
}
class myThread implements Runnable {
#Override
public void run() {
int index = 0;
while (index < imgID.size()) {
InputStream stream = getResources().openRawResource(imgID.get(index));
Bitmap bitmap = BitmapFactory.decodeStream(stream);
Message msg = Message.obtain();
msg.obj = bitmap;
handler.sendMessage(msg);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
if (index >= imgID.size()) {
index = 0;
}
bitmap.recycle();
bitmap = null;
}
}
}
}
Related
i have imageView
<ImageView
android:id="#+id/loading"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerCrop"
android:layout_gravity="center_horizontal"
android:src="#drawable/spinner"/>
and image is
i want create an animation which change position of image inside imageView
i tried this
android:scrollX="-80dp"
this in xml and static i want animation
You can do it by creating a thread and a handler where the thread sleeps for a certain amount of time and informs handler by sending message when it wakes up and handler will update the image in image view.
Create 4 Fields like below :
private ImageView mImageView;
private Handler mImageChangingHandler;
private int mCurrentImageIndex = 0;
private BackgroundThread mImageUpdateThread;
In onCreate() get the ImageView, spilt your bitmaps and add it to a list and create a handler which updates imageview. Here you should know the number of individual bitmaps which is in main Bitmap. Like :
mImageView = (ImageView) findViewById(R.id.img);
Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.anim);
//number of individual bitmaps, which you should know.
final int numberOfImages = 21;
//individual bitmap width
int bitmapWidth = mainBitmap.getWidth() / numberOfImages;
//individual bitmap height
int bitmapHeight = mainBitmap.getHeight();
//list which holds individual bitmaps.
final List<Bitmap> animBitmaps = new ArrayList<>(numberOfImages);
//split your bitmap in to individual bitmaps
for (int index = 0; index < numberOfImages; index++) {
animBitmaps.add(Bitmap.createBitmap(mainBitmap, index * bitmapWidth, 0, bitmapWidth, bitmapHeight));
}
//set 1st bitmap to imageView.
mImageView.setImageBitmap(animBitmaps.get(mCurrentImageIndex));
mImageChangingHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
//increament current bitmap index
mCurrentImageIndex++;
//if current index is greater than the number of images, reset it to 0
if (mCurrentImageIndex > numberOfImages - 1) {
mCurrentImageIndex = 0;
}
mImageView.setImageBitmap(animBitmaps.get(mCurrentImageIndex));
return true;
}
});
//Create the background thread by passing the handler and start.
mImageUpdateThread = new BackgroundThread(mImageChangingHandler);
mImageUpdateThread.setRunning(true);
mImageUpdateThread.start();
And This will be your BackgroundThread.class :
public static class BackgroundThread extends Thread {
private Handler mHandler;
private boolean mRunning;
public BackgroundThread(Handler handler) {
mHandler = handler;
}
public void setRunning(boolean running) {
mRunning = running;
}
#Override
public void run() {
super.run();
while (mRunning) {
try {
//this sleeps for 100 milliseconds
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//send message to handler after sleep
mHandler.sendEmptyMessage(0);
}
}
}
}
Finally in onDestroy() stop the thread. Like :
mImageUpdateThread.setRunning(false);
boolean stopThread = true;
while (stopThread) {
try {
mImageUpdateThread.join();
//thread already stopped
stopThread = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mImageUpdateThread = null;
Note : If you want to increase the update speed, reduce the sleep time in thread.
I'm trying to get HTML source but it's freezing the app.
I don't know what the problem is and I added Internet Permission
I took this code from a site but it's not working with me. It works until I press the button and then it just freezes.
I hope some one can help me with this, here is the code I'm using:
public class MainActivity extends Activity {
private String HTML = "";
EditText tv;
private ProgressDialog m_ProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button)findViewById(R.id.button1);
tv = (EditText)findViewById(R.id.editText1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
getHTML("http://m.Facebook.com/");
}
});
}
public void getHTML(String paramString)
{
try
{
BufferedInputStream localBufferedInputStream = new BufferedInputStream(new URL(paramString).openConnection().getInputStream());
ByteArrayBuffer localByteArrayBuffer = new ByteArrayBuffer(50);
while (true)
{
int i = localBufferedInputStream.read();
if (i == -1)
{
HTML = new String(localByteArrayBuffer.toByteArray());
handler.sendEmptyMessage(0);
return;
}
i = (byte)i;
localByteArrayBuffer.append(i);
}
}
catch (Exception localException)
{
while (true)
this.HTML = "Error!";
}
}
private Handler handler = new Handler()
{
public void handleMessage(Message paramMessage)
{
EditText localEditText = (EditText)MainActivity.this.findViewById(R.id.editText1);
MainActivity.this.m_ProgressDialog.dismiss();
localEditText.setText(MainActivity.this.HTML);
}
};
}
What does this have to to with a WebView? You have a NetworkOnMainThreadExeption. You have to put your code in an AsyncTask or Thread to prevent this.
In addition to doing network work on your main thread (a big no-no in Android - use an AsyncTask), your error is probably happening here:
public void getHTML(String paramString) {
try {
BufferedInputStream localBufferedInputStream = new BufferedInputStream(new URL(paramString).openConnection().getInputStream());
ByteArrayBuffer localByteArrayBuffer = new ByteArrayBuffer(50);
while (true) {
int i = localBufferedInputStream.read();
if (i == -1) {
HTML = new String(localByteArrayBuffer.toByteArray());
handler.sendEmptyMessage(0);
return;
}
i = (byte) i;
localByteArrayBuffer.append(i);
}
} catch (Exception localException) {
while (true) // <<< this will create an infinite loop when an error occurs
this.HTML = "Error!";
}
}
Try removing while (true) from your catch statement.
im building an android application that recive images from arduino uno in order to show them continously as a video , i write an asyncTask that reads image and show it in image view , how can i invoke this method every seconed automatically .
here is my asyncTask
I made a button that invoke the async task , but how to make it invoked continously
class myAsyncTask extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
mmInStream = tmpIn;
int byteNo;
try {
byteNo = mmInStream.read(buffer);
if (byteNo != -1) {
//ensure DATAMAXSIZE Byte is read.
int byteNo2 = byteNo;
int bufferSize = 7340;
int i = 0;
while(byteNo2 != bufferSize){
i++;
bufferSize = bufferSize - byteNo2;
byteNo2 = mmInStream.read(buffer,byteNo,bufferSize);
if(byteNo2 == -1){
break;
}
byteNo = byteNo+byteNo2;
}
}
}
catch (Exception e) {
// TODO: handle exception
}
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
bm1 = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
image.setImageBitmap(bm1);
}
}
If it's from a background thread, one possibility is to use an unbounded for loop. For example, suppose the AsyncTask currently does:
private class MyTask extends AsyncTask<T1, Void, T3>
{
protected T3 doInBackground(T1... value)
{
return longThing(value);
}
protected void onPostExecute(T3 result)
{
updateUI(result);
}
}
then rewrite it as something like:
private class MyTask extends AsyncTask<T1, T3, T3>
{
protected T3 doInBackground(T1... value)
{
for (;;)
{
T3 result = longThing(value);
publishProgress(result);
Thread.sleep(1000);
}
return null;
}
protected void onProgressUpdate(T3... progress)
{
updateUI(progress[0]);
}
}
Of course, you should have a check to break the loop (for example when the Activity is paused or destroyed).
Another option is to create a Handler instance and call postDelayed() repeatedly.
Handler h = new Handler();
h.postDelayed(r, DELAY_IN_MS);
Runnable r = new new Runnable() {
public void run() {
// Do your stuff here
h.postDelayed(this, DELAY_IN_MS);
}
}
I am trying to show two consecutive images in an Android app, which are received through a socket (from a C program using sendfile). The sender code seems to work ok, and I am having issues with the Android code side.
Part of the code in the Android app is the following:
public class DisplayNewActivity extends Activity {
...
#Override
public void onCreate(Bundle savedInstanceState) {
....
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Drawable d2;
d2 = (Drawable)msg.obj;
imageSock.setImageDrawable(d2); // to set the arrived image in the imageshow object
}
};
...
cThread = new Thread(new ClientThread());
rThread = new Thread(new RcvThread());
cThread.start();
}
public class ClientThread implements Runnable {
public void run() {
// thread used for socket connection.
...
rThread.start(); // once the connection has been established
...
}
}
#SuppressLint("HandlerLeak")
public class RcvThread implements Runnable {
public void run() {
while (connected) {
try {
InputStream inputStream = socket.getInputStream();
Drawable d = Drawable.createFromStream(inputStream, null);
Message msg = new Message();
msg.obj = d;
mHandler.sendMessage(msg);
} catch (Exception e) {
Log.e("SocketConnectionv02Activity", "C: ErrorRCVD", e);
}
}
}
}
}
The problem I am facing is that after the first image received by the Android app is shown correctly, then the next one received (which is correctly received) is not shown and leaves the imageview object showing a white space.
Any suggestion/idea to solve this issue?.
Thanks in advance for any help you could provide.
EDIT:
public class DisplayNewActivity extends Activity {
...
#Override
public void onCreate(Bundle savedInstanceState) {
....
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bitmap d2;
d2 = (Bitmap)msg.obj;
imageSock.setImageBitmap(d2); // to set the arrived image in the imageshow object
}
};
...
cThread = new Thread(new ClientThread());
rThread = new Thread(new RcvThread());
cThread.start();
}
public class ClientThread implements Runnable {
public void run() {
// thread used for socket connection.
...
rThread.start(); // once the connection has been established
...
}
}
#SuppressLint("HandlerLeak")
public class RcvThread implements Runnable {
public void run() {
while (connected) {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
Bitmap d = BitmapFactory.decodeStream(in);
Message msg = new Message();
msg.obj = d;
mHandler.sendMessage(msg);
} catch (Exception e) {
Log.e("SocketConnectionv02Activity", "C: ErrorRCVD", e);
}
}
}
}
}
It sounds like the issue you are having is in decoding the data into a proper image after receiving it.
I might recommend not using Drawable.createFromStream() and instead using BitmapFactory.decodeStream() or manually downloading the data into a byte[] first and using BitmapFactory.decodeByteArray(). Sometimes the latter is useful if the former can't sufficiently keep up with the decoder as the data is received.
The method you are currently using actually ends up calling BitmapFactory.descodeResourceStream(), which is used to read image data out of the local res/ package and not so much from a remote socket.
I am trying to display the images in galleryViews which are in ListView. I am downloading images from server to SDCard and then displaying it, first I am checking images in cache if image is not there then I am loading it from sdcard.
when the user starts the app for the first time I am downloading the images from server and saving them to sdcard in the mean time iam showing the activity with text only
I want if the image is not there in sdcard the after downloading the image it should display the image as soon as the image is download here is what I am doing.
public class AsyncImageLoader {
private boolean isImageView;
private final LinkedHashMap<String, Bitmap> cache =
new LinkedHashMap<String, Bitmap>(60, (float) 1.0, true);
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
LoadImageFromSdCard loadImage = (LoadImageFromSdCard) msg.obj;
if (isImageView) {
loadImage.imageView.setImage(loadImage.bmp);
} else {
Thread thread = new Thread(new LoadImageFromSdCard(loadImage.uri, loadImage.imageView));
try {
Log.i("AsyncImageLoader", "SECOND THREAD STARTED");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.start();
}
}
};
public Bitmap loadImage(String uri,
ImageTextComboControl imageView) {
if (cache.containsKey(uri)) {
return cache.get(uri);
} else {
handler.post(new LoadImageFromSdCard(uri, imageView));
}
return null;
}
private class LoadImageFromSdCard implements Runnable {
String uri;
ImageTextComboControl imageView;
ImageView image;
Bitmap bmp = null;
public LoadImageFromSdCard(String uri, ImageTextComboControl imageView) {
this.uri = uri;
this.imageView = imageView;
}
public void run() {
FileInputStream fis;
try {
fis = new FileInputStream(new File(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
bmp = BitmapFactory.decodeStream(fis);
if (imageView != null) {
isImageView = true;
cache.put(uri, bmp);
Message message = new Message();
message.obj = this;
handler.sendMessage(message);
}
}
}
}
Thanx
Is much better use Async Task class http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html (using AsyncTask section) and, important, take care about large bitmap
http://developer.android.com/training/displaying-bitmaps/index.html
I solved my problem using onContentChanged() method in adapter. I am saving images to sdCard and getting the sdCard path saving it into sqlite database so when ever the data is changing in sqlite database onContentChanged method is called because I am using Cursor Adapter.