I have a problem with my class who extend the AsyncTask. The logic is I take a screenshot of the camera preview each seconds with an interval, and each second in this interval, I create a new instance of my class extending AsyncTask and call execute on it without stock it in a variable. But when I set a Log.d in my doInBackground() method in my class, the Log.d is called only one time in the first second of the interval. I need to do that to send a new screenshot each second to a socket server.
This is the interval code :
private void startTakingPicturesInterval() {
new Timer().scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
camera.takePicture(null, null, pictureScreenTaked);
Log.d("debug_app", "Picture Taked");
new ClientServerStream().execute(image_to_send_captured_each_time);
}
},0,1000);
}
private Camera.PictureCallback pictureScreenTaked = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
image_to_send_captured_each_time = BitmapFactory.decodeByteArray(data, 0, data.length);
ImageView img_result_test = findViewById(R.id.img_result_test);
img_result_test.setImageBitmap(image_to_send_captured_each_time);
camera.cancelAutoFocus();
camera.startPreview();
}
};
My method doInBackground of the class extending the AsyncTask :
#Override
protected Object doInBackground(Object[] objects) {
initValues();
Log.d("debug_app", "Client executed correctly");
try {
bw.write("test");
bw.flush();
closeAll();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Solution Finded
The solution is because my server socket was disonnected so probably there was an error in my Client Socket so the code doesn't execute and the error is not shown because they executed Asychronously
Yesterday and today I tried to solve the problem from my service. I read lots of topics about this problem (when i want unstopable timer every 15s) but i don't find any solution.
First i try asynch task and service which are nevertheless implement WakeLock still pause when I disconnect the charger. In this topic i read that is no chance to do this in Service. (Here)
Now i try the AlertManager but i read that from some version of android don work repeting in small intervals.
My questions here is, How can i do this (15s interval which can be run always (sleep mode, no on charge etc..)) and android don't be stop this task. I need regular renewal every 15 seconds in all circumstances.
Someone help me how to do this?
Thank
My service on create
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakelock= pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getCanonicalName());
wakelock.acquire();
runnable = new Runnable() {
public void run() {
while(true) {
if (!running) return;
if (updateVillages()) {
result = true;
if (isNewVillage()) {
if (isNotificationEnable) doNotificate();
}
System.out.println("Prebehlo overovanie");
} else {
result=false;
System.out.println("Není internetové pripojenie");
}
updateUI();
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread= new Thread(runnable);
thread.start();
Hello There I am a newbie for Android Development, working to learn it to my own!
I just want to update my notification in a Java Thread in my application (I am just learning and curious about how can I do it).
I have an activity, a simple thread to increment an Integer value. Then, I just want to show it in my Notification whenever the Integer value increments!
My Code is as:
public class MainActivity extends Activity{
private final String LOG_KEY = this.getClass().getSimpleName();
private int c = 0;
private boolean flag = true;
private NotificationCompat.Builder builder;
private NotificationManager notificationManager;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
builder = new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(false);
builder.setOngoing(true);
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Thread t = new Thread(new MyThread());
t.start();
}//OnCreate ends
#Override
protected void onStop() {
super.onStop();
flag = false;
}//stop ends
#Override
protected void onDestroy() {
super.onDestroy();
flag = false;
}//destroy ends
private class MyThread implements Runnable {
#Override
public void run() {
while (flag) {
c+=1;
showNotification(Integer.toString(c) + " Counts");
}//while ends
}//run ends
private void showNotification(String msg) {
try {
//set the notification
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends
}//private class ends
}//MainActivity class ends here
As from my code, the notification appears and updates the value! But the problem is that it freezes the device and application at a sudden!
I just want help for what I am doing wrong as I am a newbie and learning it to my own. Any help and idea will be highly appreciated!
Thanks
You shouldn't be creating a notification and then continuously updating it as fast as you can from a thread. It's really not designed for that.
The closest thing I can think of that would meet your use case is using a notification to display progress. See this link:
Displaying Progress in a Notification
You might want to put some kind a rate limiter in your thread, unless you want your count to reach very high numbers very quickly. Perhaps make the thread sleep for a second between updates.
The problem is that you produce too much notifications more then a device can consume.
For your goal (just learn) you can add a some pause between notifications like that:
private void showNotification(String msg) {
try {
//set the notification
Thread.sleep(1000); //set the pause
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends
I'm running an AsyncTask on my TakePic class. In doInBackground function I'm using Camera.takePicture function. Now everything is fine at this point; I'm taking the picture and saving the file to /sdcard/%d.jpg that location.
public class TakePic extends AsyncTask<CameraPreview, String, Integer> {
#Override
protected Integer doInBackground(final CameraPreview... params) {
params[0].camera.takePicture(null,null,new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.e("picture_saved", "Picture has been saved succesfully: " + data.length);
camera.release();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("file_not_found: ","couldn't save the file "+e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.e("IOexception: ","couldn't save the file "+e.getMessage());
}
}
});
Log.e("doinback_compt:" ,"done");
return 0;
}
#Override
protected void onPostExecute(Integer integer) {
}
}
But after I execute this AsyncTask on my main class it doesn't finish. I need to execute another function and I have to wait until this AsyncTask finishes. So after I execute the AsyncTask I'm using a while loop to check the status of the task but the status never changes.
TakePic backCam=new TakePic();
backCam.execute(cameraPreview_front);
while (backCam.getStatus()!= AsyncTask.Status.FINISHED){
*waiting for async task to finish*
}
It stuck at the while loop and my logcat show that doInBackground running normal, and the file is saving to that location.
10-10 18:06:14.497 15975-15975/com.urun.camera_test E/clicked_capture:: ok
10-10 18:06:14.633 15975-16452/com.urun.camera_test E/doinback_compt:: done
So what am I need to do? Thanks in advance.
This is being handled in an odd way. First CameraPreview.camera.takePicture() will run in the background itself, that is why you pass it the Camera.PictureCallback in the constructor. You are simply stacking threads there. Try this in the main thread
[yourCameraPreview].camera.takePicture(null,null,new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
camera.release();
// Read below
}
}
Now we can just wait for the picture callback. Once we get data back, we can call an AsyncTask to store it in the file, and apply our own callback to wait for it's response. We can utilize a static inner class to make this all work.
private static class ImageSaver extends AsyncTask<Byte, Void, Exception>{
public interface ImageSavedListener{
void onImageSaved(Exception e);
}
private ImageSavedListener mCallback;
public ImageSaver(ImageSavedListener callback){
mCallback = callback;
}
#Override
protected void doInBackground(Byte... data){
if(data == null || data.length == 0)
return new Exception("Data returned from camera is invalid");
try {
FileOutputStream outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d("picture_saved", "Picture has been saved succesfully: " + data.length);
} catch (FileNotFoundException e) {
Log.e("file_not_found: ","couldn't save the file "+e.getMessage());
return e;
} catch (IOException e) {
Log.e("IOexception: ","couldn't save the file "+e.getMessage());
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception e){
if(mCallback != null)
mCallback.onImageSaved(e);
}
}
Then call it like this (in the section stated Read below above)
new ImageSaver(new ImageSavedListener(){
#Override
public void onImageSaved(Exception e){
if(e == null){
// do what you want
}
else
e.printStackTrace();
}
}).execute(data);
This will take the picture in the background, wait for the response, save the response to a file in the background, wait for the response, and then do what you want based on the exception returned after saving.
If you need to do some code after AsyncTask execution, I can suggest one solution.
Wrap your *waiting for async task to finish* code in Runnable and send it as a param to Async task ( but this is not the best solution, just fast one )
new AsyncTask<Object, Void, Runnable>() {
#Override
protected Runnable doInBackground(Object... runnables) {
CameraPreview cp = (CameraPreview) runnables[0];
Runnable callback = (Runnable) runnables[1];
/**your main logic*/
return callback;
}
#Override
protected void onPostExecute(Runnable aVoid) {
super.onPostExecute(aVoid);
if (aVoid != null)
aVoid.run();
}
}.execute( cameraPreview , new Runnable() {
#Override
public void run() {
/**code to run();**/
}
});
Possible problem with your current code is :
You are not executing super.onPostExecute(integer);
Try change code to
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
}
As pointed out before, does not make sense blocking your main thread waiting do certain event. However, if you still want to get a something from your AsyncTask, I would advise you to use FutureTask
As I can see in your code, the AsyncTask is finishing correctly.
The problem is that you are taking the picture inside the AsyncTask. So while the Camera.PictureCallback is waiting for the picture the task ends immediately after call the "takePicture" method.
What I should do is something like this (this is only an approach):
public class TakePic {
public interface MyTakePicListener{
void onPictureTaken();
void onPictureError();
}
private MyTakePicListener myListener;
public void takePicture(CameraPreview cameraPreview) {
cameraPreview.camera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, final Camera camera) {
new Thread(new Runnable() {
#Override
public void run() {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.e("picture_saved", "Picture has been saved succesfully: " + data.length);
camera.release();
HERE you should call a listener to continue with your success code
myListener.onPictureTaken();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("file_not_found: ", "couldn't save the file " + e.getMessage());
HERE you should call a listener to continue with your error code
myListener.onPictureError();
} catch (IOException e) {
e.printStackTrace();
Log.e("IOexception: ", "couldn't save the file " + e.getMessage());
HERE you should call a listener to continue with your error code
myListener.onPictureError();
}
Log.e("doinback_compt:", "done");
}
}).start();
}
});
}
}
Please, let me know if this could help you.
Or any other mechanism to delay code execution without hanging the main thread?
Use a Handler's postDelayed(). Documentation
Java example
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
//logic
}
}, 2000);
or
Thread({
try{
Thread.sleep(2000)
} catch (e: Exception) {
//
}
//logic
}).start()