I have the code below (app live, and I got a crash reported at the line with mService.consumePurchase):
Thread trd = new Thread(new Runnable()
{
#Override
public void run()
{
try
{
int response = mService.consumePurchase(3, getPackageName(), sku.mToken);
if (response == 0)
{
System.out.println("onActivityResult consume ok");
purchasesOK.add(sku.mSku);
}
else
{
System.out.println("onActivityResult consume failed");
purchasesFail.add(sku.mSku);
runOnUiThread(new Runnable()
{
public void run()
{
alert("Store Problems!", "There were problems consuming the product, please use RESTORE button.");
}
});
}
} catch (RemoteException e) {
purchasesFail.add(sku.mSku);
System.out.println("onActivityResult consume crashed");
runOnUiThread(new Runnable()
{
public void run()
{
alert("Store Problems!", "There were problems consuming the product, please use RESTORE button.");
}
});
}
}
});
trd.start();
here is the crash report:
java.lang.NullPointerException at
com.XXXXX.GGActivity.j_ItemPurchase(GGActivity.java:1309) at
com.XXXXX.GGLib.step(Native Method) at
com.XXXXX.GGView$Renderer.onDrawFrame(GGView.java:436) at
android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1523)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
I thought that try/catch will show the popup error in any case of exception. Any ideas what might caused it ? Or how can I avoid it?
Thanks,
/C.
Add this:
catch(NullPointerException e){
purchasesFail.add(sku.mSku);
System.out.println("onActivityResult consume crashed");
runOnUiThread(new Runnable(){
public void run(){
alert("Store Problems!", "There were problems consuming the product, please use RESTORE button.");
}
});
}
in order to show the popup message
Related
In my application i should used socket.io and i want when receive my event update UI elements!
I write below codes and i receive my events show me logs, but not update any UI!
I want when receive event, check this winner is user or not and then update my UI.
In logCat show me my logs but not update any UI elements!
My codes:
public void onsocketFinishRecieve(final JSONObject ob) {
try {
((BaseActivity) context).runOnUiThread(() -> {
try {
cancelTimer();
final FinishResponse finishResponse = new Gson().fromJson(ob.toString(), FinishResponse.class);
if (finishResponse.getRes().getWinnerName().equals("not user") || finishResponse.getRes().getWinnerName().equals("not winner")) {
winnerNameWhenFinished = "Not winner";
} else {
winnerNameWhenFinished = finishResponse.getRes().getWinnerName();
}
if (detail.getId() != null) {
if (detail.getId() == finishResponse.getRes().getId()) {
//Set new winner layouts
//Register in auction
if (Constants.profileResponse != null) {
if (Constants.profileResponse.getRes() != null) {
if (Constants.profileResponse.getRes().getUser() != null) {
//Winner
if (Constants.profileResponse.getRes().getUser().getId().equals(finishResponse.getRes().getUserId())) {
Log.e("FinishedSocket", "1");
detailPage_bottomWinnerRateTxt.setVisibility(View.GONE);
detailPage_bottomWinnerBuyTxt.setText("Show basket");
detailPage_bottomWinnerBuyTxt.setOnClickListener(v -> {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("OPEN_CART_IN_MAIN", "true");
startActivity(intent);
});
} else {
Log.e("FinishedSocket", "2");
//Loser
detailPage_bottomWinnerBuyTxt.setText("Awesome offers");
}
}
}
}
}
}
} catch (Exception e) {
Log.e("DetailResErr", e.getMessage());
}
});
} catch (Exception e) {
Log.e("DetailResErr", e.getMessage());
}
}
Logcat message :
2020-03-08 13:37:37.399 E/FinishedSocket: 2
In logcat show me above message , why not run this line : detailPage_bottomWinnerBuyTxt.setText("Awesome offers"); ??
How can i fix it?
try to run this on Mainthread like this.
someActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
//Your code to run in GUI thread here
detailPage_bottomWinnerBuyTxt.setText("Awesome offers");
}
});
Sockets work on IOThread while other side UI Work on separate Thread called UI thread. So, update the UI element on UI Thread.
Use Annotation :
#UiThread
public abstract void setText(#NonNull String text) { ... }
For know about more annotation, Check the following blog:
https://medium.com/#gurwindersingh_37022/android-annotations-30b4a2850d0
I want to send value from string (distance to obstacle) to my TextView in main activity.
I tried to use Handler, but still not working (crash) or receive nothing.
A part code which receive data from HC-05 (screen where you see in debug value assignet to variable)
enter image description here
#Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while(true){
try {
bytes = inputStream.read(buffer);
final String comingMsg = new String(buffer,0,bytes);
Log.d(TAG,"InputStream: " + comingMsg);
/*mHandler2.post(new Runnable() {
#Override
public void run() {
Message message = new Message();
message.obj = comingMsg;
mHandler2.sendMessage(message);
}
});*/
}catch (IOException e){
Log.e(TAG,"Write: Error reading input." + e.getMessage());
active=false;
break;
}
}
}
Here It's parts of code from MainActivity where I tried put something to get values from service.
[I add, that for this moment i want to see something values from bluetooth in textView. Later I want to create parse string and send custom text to custom TextView - example: FL: (Front Left)- to one textView, FR: (Front Right) - to second textView]
There is method implementThreads(), because I wanted to do 6 Threads to 6 TextView which every time is refreshing value from string in Services (there I tried get value from Bluetooth Service)
Log.d(TAG,"Check intent - result");
if(getIntent().getIntExtra("result",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded device");
myBluetoothService = new MyBluetoothService(getApplicationContext());
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service");
checkIfActive();
}
Log.d(TAG,"Check intent - connect_to_paired");
if(getIntent().getIntExtra("connect_to_paired",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded_paired_device");
myBluetoothService = new MyBluetoothService(getApplicationContext());
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service");
checkIfActive();
}
}
#Override
public void onStart(){
super.onStart();
myBluetoothService = new MyBluetoothService(getApplicationContext());
}
public void checkIfActive(){
Log.d(TAG,"CheckIfActive: Started");
if(myBluetoothService.active){
Log.d(TAG,"CheckIfActive: Running method implementThreads()");
implementThreads();
}
}
public void implementThreads(){
Log.d(TAG,"ImplementThreads: Started");
Thread thread = new Thread(){
#Override
public void run() {
try{
sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
};
thread.start();
}
public void startConnection(BluetoothDevice device,UUID uuid){
Log.d(TAG,"StartConnection: Initializing connection");
myBluetoothService.startClient(device,uuid);
}
Thanks all for help, because It's very important for me !
Use this to interect with UI Thread for operations like updating textviews etc.
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
//YOUR CODE HERE
Message message = new Message();
message.obj = comingMsg;
mHandler2.sendMessage(message);
}
});
I clearly misunderstand how they work. My code:
private final Runnable processAccel = new Runnable() {
#Override
public void run() {
Log.d(TAG, "run: AccelStart");
registerAccel();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler.postDelayed(this, interval);
unregisterAccel();
}
};
During this Runnable i was hoping to record sensor events, in the same class. However I get no data.
If I remove the
unregisterAccel();
it records data all the time, both during the runnable and when it is not running, and during when it is sleeping during the runnable, but as soon as I deregister the sensor listener at the end of the runnable, I stop getting results, even when I extend the Thread.sleep out to 10 seconds, which makes no sense to me?
Extra info:
public void registerAccel(){
Log.d(TAG, "registerAccel: on");
sensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
public void unregisterAccel(){
Log.d(TAG, "unregisterAccel: off");
sensorManager.unregisterListener(this, mAccelerometer);
}
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()