I'm tearing my hair out with this one! I'm a newbie to Android so I'm sure it's something super obvious.
I'm getting a ScheduledThreadPoolExecutor exception where cause: null
All I want is a seperate thread that runs whenever the activity is on screen!
// Instance Variables
private ScheduledExecutorService m_oScheduledExecutor = null;
#Override
protected void onResume()
{
super.onResume();
if (oScheduledExecutor == null)
{
oScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
}
try
{
oScheduledExecutor.scheduleAtFixedRate({Runnable Instance HERE}, 0, 10, TimeUnit.SECONDS);
}
catch (Exception e)
{
System.out.println("(MainActivity) Error: " + e.getMessage() + " Cause: " + e.getCause());
}
}
#Override
protected void onStop()
{
super.onStop();
m_oScheduledExecutor.shutdown();
}
EDIT: Entire Stack Trace....
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask#41976688 rejected from java.util.concurrent.ScheduledThreadPoolExecutor#4195c7f8[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1979)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:786)
at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:300)
at java.util.concurrent.ScheduledThreadPoolExecutor.scheduleAtFixedRate(ScheduledThreadPoolExecutor.java:545)
at java.util.concurrent.Executors$DelegatedScheduledExecutorService.scheduleAtFixedRate(Executors.java:619)
at com.example.wifitest.MainActivity.onResume(MainActivity.java:61)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
at android.app.Activity.performResume(Activity.java:5182)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1276)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
You cannot 'recycle' an ExecutorService. Once you have invoked shutdown(), attempting to schedule any task will cause a rejection, and in your case the rejection policy is to throw RejectedExecutionException.
If you follow your stacktrace, you can see in ScheduledThreadPoolExecutor:
/**
* Specialized variant of ThreadPoolExecutor.execute for delayed tasks.
*/
private void delayedExecute(Runnable command) {
if (isShutdown()) {
reject(command);
return;
}
// ...
}
Keeping your executor service as an instance variable is not going to work for you here: once it's been shutdown, it can't be used again.
Do not shutdown the ScheduledExecutorService inside onStop() method. Try to put it inside onDestroy() method. When your activity goes in background, onStop() method might be getting called, as your activity is not visible in the background. Because of this, if the ScheduledExecutorService is shutdown, you might be getting this error.
Related
Recently I sometimes got this exception when MainActivity called onResume().
java.lang.RuntimeException: Unable to resume activity {com.qau4d.c35s3.androidapp/com.xxx.XXX.XXX.MainActivity}: java.lang.IllegalArgumentException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3400)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3440)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1510)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.IllegalArgumentException
at android.os.Parcel.readException(Parcel.java:1687)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.ActivityManagerProxy.isTopOfTask(ActivityManagerNative.java:5475)
at android.app.Activity.isTopOfTask(Activity.java:5961)
at android.app.Activity.onResume(Activity.java:1252)
at com.qau4d.c35s3.androidapp.onResume(XActivity.java:29)
at com.qau4d.c35s3.androidapp.onResume(MainActivity.java:196)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
at android.app.Activity.performResume(Activity.java:6768)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3377)
Both in MainActivity and super class XActivity, only super.onResume(); is called. It's really strange to get this exception after a long time normal development.I checked some relative reference material but nothing got.
In the method Activity#isTopOfTask we can see:
private boolean isTopOfTask() {
if (mToken == null || mWindow == null) {
return false;
}
try {
return ActivityManager.getService().isTopOfTask(getActivityToken());
} catch (RemoteException e) {
return false;
}
}
And in ActivityManagerService#isTopOfTask we can found:
#Override
public boolean isTopOfTask(IBinder token) {
synchronized (this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
throw new IllegalArgumentException();
}
return r.task.getTopActivity() == r;
}
}
So, I think that ActivityRecord is null.But I don't know why it is null....
There is insufficient information in your question to determine the cause of the java.lang.IllegalArgumentException, Unfortunately the android ActivityThread doesn't log the stacktrace of that exception, and the exception message appears to be empty.
However, it looks like there is a way forward. The exception is handled by the following code in the ActivityThread::performResumeActivity method:
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to resume activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
If you register an Instrumentation class for your activity, it should be possible to use an onException method to log the stacktrace for the causal exception. Another possibility is to use Thread.setUncaughtExceptionHandler to set a handler for the thread in which the IllegalArgumentException is thrown.
These won't solve the problem (!) but it will get you a step closer to a solution.
I have successfully made outgoing call via PJSIP. Now facing a problem while try to handle incoming call.
Thread isanycall=new Thread(new Runnable() {
#Override
public void run() {
while(true)
{
if(Global.isanycall==1)
{
sipOperationIncoming(username, pwd, ip, number.getText().toString());
Global.isanycall=0;
}
}
}
});
isanycall.start();
This code is checking if there is any incoming call.
System.out.println("Incoming call handler");
//sip operation started
registration=SipRegistration.getSipRegistration(uname,pwd,ip);
registration.answerCall(da);
//sip operation ended
This code block is just responsible to call a function answerCall which is as follow
public void answerCall(DialerActivity activity){
call=new MyCall(myacc,1,this.ep,activity);
CallOpParam prm = new CallOpParam();
prm.setStatusCode(pjsip_status_code.PJSIP_SC_RINGING);
try {
call.answer(prm);
}catch(Exception e){
e.printStackTrace();
}
}
Now the exception I am getting is
java.lang.Exception: Title: pjsua_call_answer2(id, param.p_opt, prm.statusCode, param.p_reason, param.p_msg_data)
10-27 12:11:19.839 10090-10384/com.skyteloutsourcing.callnxt W/System.err: Code: 171140
10-27 12:11:19.839 10090-10384/com.skyteloutsourcing.callnxt W/System.err: Description: INVITE session already terminated (PJSIP_ESESSIONTERMINATED)
What can be the reason?
Solved it, I was responding with a different call id rather than which was the call id of incoming call. :)
I faced this error when I don't check this control
if(ci.state==pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED){
currentCall.delete()
currentCall=null
}
I want the user to be able to send an error report when my service crashes. I have an GUI app which gets updated using broadcasts from the service. The service runs in a different process and runs as foreground. I used the same code to attach the default exception handler to my GUI and there it works fine (opens the e-mail send app and the body of the e-mail contains the exception). But for my service threads, I cannot get them to call the UncaughtExceptionHandler.
The research I did so far is that the thread that crashes has a different threadid (12) than the thread I registered the cutom exceptionhandler on (229) The registration and the crash are in the same Timer_Tick runnable and should have the same threadid.
Logcat output:
> D/Registratie: General exception handler set for threadid=229
> D/Registratie: ThreadName in Timer_Tick: Timer-0 threadId=229
> D/Registratie: ThreadName in Timer_Tick: Timer-0 threadId=229
> D/Registratie: ThreadName in Timer_Tick: Timer-0 threadId=229
> D/Registratie: Throw ArrayIndexOutOfBounds exception W/dalvikvm:
> threadid=12: thread exiting with uncaught exception (group=0x4169fba8)
Service member and method:
// declared non-anonymous to prevent the garbage collector erroneously clearing
private Thread.UncaughtExceptionHandler mUEHandler;
public void attachGeneralExceptionHandler(){
mUEHandler = new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
Log.d(TAG, "Custom crash handler: build crashrapport and intent");
sendExceptionReport(t,e);
mUEHandler.uncaughtException(t, e);
}
};
Thread.setDefaultUncaughtExceptionHandler(mUEHandler);
Log.d(TAG, "General exception handler set for ThreadName: " + Thread.currentThread().getName() + " threadid=" + Thread.currentThread().getId());
}
TimerTick from the service:
private Runnable Timer_Tick = new Runnable() {
public void run() {
if(!uncaughtExceptionHandlerSet) {
// Make sure the exception handler is connected to this Timer_Tick thread
attachGeneralExceptionHandler();
uncaughtExceptionHandlerSet=true;
}
Log.d(TAG, "ThreadName in Timer_Tick: "+ Thread.currentThread().getName()+" threadId="+Thread.currentThread().getId());
if(testExceptionHandling){
Log.d("TAG", "Throw ArrayIndexOutOfBounds exception");
int[] exceptionTest = new int[3];
exceptionTest[3] = -1; // throws exception on thread with threadid 12, only one line in logcat
}
}
The documentation for Thread.setDefaultUncaughtExceptionHandler() indicates:
This handler is invoked in case any Thread dies due to an
unhandled exception
You don't need to call that method for each thread. Try setting the default handle in the onCreate() method of your service.
On my android project, I am getting an intermittent NullPointerException reported in both crashlytics and the play store for a null pointer exception when invoking one of my objects invokes a method on itself.
Here is the entirety of the method that has the NullPointerException:
#Override
public void notifyActivityStarted() {
startUpdatingLocation(); // <-- NullPointerException occurs here. This is line 83 of DefaultAndroidLocationProvider.java
}
private void startUpdatingLocation() {
final String bestProvider = getBestProviderName();
Log.d(LOGTAG, "Starting to update location for provider: " + bestProvider);
// If we don't have a location yet, then let's make sure we get one at
// least
// temporarily.
Location currentLoc = getLastLocationFromBestProvider();
if (currentLoc != null) {
Log.d(LOGTAG, "Hydrating with last location");
mLastLocation.hydrate(currentLoc);
}
mWorker = new WorkerThread("DefaultAndroidLocation");
// Get a location update every 10s from both network and GPS.
if (mManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
mManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
10000,
0,
DefaultAndroidLocationProvider.this,
mWorker.getLooper());
}
if (mManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
mManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
10000,
0,
DefaultAndroidLocationProvider.this,
mWorker.getLooper());
}
mIsUpdatingLocation = true;
shutdownInitiated = false;
}
Here is the stack trace:
java.lang.NullPointerException
at com.jingit.mobile.location.DefaultAndroidLocationProvider.notifyActivityStarted(DefaultAndroidLocationProvider.java:83)
at com.jingit.mobile.location.ActivityObserverSet.onStartObserved(ActivityObserverSet.java:48)
at com.jingit.mobile.location.LocationAwareFragment.onStart(LocationAwareFragment.java:41)
at android.support.v4.app.Fragment.performStart(Fragment.java:1484)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:941)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5633)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:896)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712)
at dalvik.system.NativeStart.main(NativeStart.java)
I wasn't able to find anything to give me hints on the documentation for NullPointerException, and haven't been able to find any other helpful hints. Any thoughts or ideas would be greatly appreciated.
I'm setting up a USB accessory connection between my Android phone and another device. Just sending bytes back and forth for now to test. I get some definite communication going at first, but it always ends up dying with Java.io.IOException: write failed: EBADF (Bad file number)" after a second or so. Sometimes the reading stays alive but the writing dies; others both die.
I'm not doing anything super fancy, reading and writing just like the Google documentation:
Initial connection (inside a broadcast receiver, I know this part works at least initially):
if (action.equals(ACTION_USB_PERMISSION))
{
ParcelFileDescriptor pfd = manager.openAccessory(accessory);
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
mIn = new FileInputStream(fd);
mOut = new FileOutputStream(fd);
}
}
Reading:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
byte[] buf = new byte[BUF_SIZE];
while (true)
{
try {
int recvd = mIn.read(buf);
if (recvd > 0) {
byte[] b = new byte[recvd];
System.arraycopy(buf, 0, b, 0, recvd);
//Parse message
}
}
catch (IOException e) {
Log.e("read error", "failed to read from stream");
e.printStackTrace();
}
}
}
});
thread.start();
Writing:
synchronized(mWriteLock) {
if (mOut !=null && byteArray.length>0) {
try {
//mOut.flush();
mOut.write(byteArray, 0, byteArray.length);
}
catch (IOException e) {
Log.e("error", "error writing");
e.printStackTrace();
return false;
}
}
else {
Log.e(TAG, "Can't send data, serial stream is null");
return false;
}
}
Error stacktrace:
java.io.IOException: write failed: EBADF (Bad file number)
W/System.err(14028): at libcore.io.IoBridge.write(IoBridge.java:452)
W/System.err(14028): at java.io.FileOutputStream.write(FileOutputStream.java:187)
W/System.err(14028): at com.my.android.transport.MyUSBService$5.send(MyUSBService.java:468)
W/System.err(14028): at com.my.android.transport.MyUSBService$3.onReceive(MyUSBService.java:164)
W/System.err(14028): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:781)
W/System.err(14028): at android.os.Handler.handleCallback(Handler.java:608)
W/System.err(14028): at android.os.Handler.dispatchMessage(Handler.java:92)
W/System.err(14028): at android.os.Looper.loop(Looper.java:156)
W/System.err(14028): at android.app.ActivityThread.main(ActivityThread.java:5045)
W/System.err(14028): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err(14028): at java.lang.reflect.Method.invoke(Method.java:511)
W/System.err(14028): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
W/System.err(14028): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
W/System.err(14028): at dalvik.system.NativeStart.main(Native Method)
W/System.err(14028): Caused by: libcore.io.ErrnoException: write failed: EBADF (Bad file number)
W/System.err(14028): at libcore.io.Posix.writeBytes(Native Method)
W/System.err(14028): at libcore.io.Posix.write(Posix.java:178)
W/System.err(14028): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191)
W/System.err(14028): at libcore.io.IoBridge.write(IoBridge.java:447)
W/System.err(14028): ... 13 more
I have logging all over the place and thus I know it's not anything too obvious, such as another permission request being received (and thus the file streams being reinitialized mid-read). The streams aren't closing either, because I never have that happen anywhere in my code (for now). I'm not getting any detached or attached events either (I log that if it happens). Nothing seems too out of the ordinary; it just dies.
I thought maybe it was a concurrency issue, so I played with locks and sleeps, nothing worked that I tried. I don't think it's a throughput issue either because it still happens when I sleep every read (on both ends), and read one single packet at a time (super slow bitrate). Is there a chance the buffer is being overrun on the other end somehow? How would I go about clearing this? I do have access to the other end's code, it is an Android device as well, using Host mode. In case that it matters, I can post that code too - standard bulk transfers.
Does the phone just have lackluster support for Android Accessory Mode? I've tried two phones and they both fail similarly, so I doubt it's that.
I'm wondering what causes this error in general when writing or reading from USB on Android?
I got same problem in my code, and I found that it happens because FileDescriptor object was GCed.
I fixed this issue by adding ParcelFileDescriptor field in Activity(or Service).
I checked your first code snippet and the code you based on, and latter has ParcelFileDescriptor field in Thread.
I think if you edit your code like below, it works well.
ParcelFileDescriptor mPfd;
...
if (action.equals(ACTION_USB_PERMISSION))
{
mPfd = manager.openAccessory(accessory);
if (mPfd != null) {
FileDescriptor fd = mPfd.getFileDescriptor();
mIn = new FileInputStream(fd);
mOut = new FileOutputStream(fd);
}
}
It ended up being a threading issue. I needed to more properly segregate even writing as well, instead of just reading.
I ended up using this code as a basis.
OK, a few things I noticed that just seemed different from what I do for Open Accessory Mode, which I followed the documentation for USB accessory mostly, so it should be very similar, is that your mIn.read(buf); should be mIn.read(buf, 0, 64); as far as I know.
Also, you should declare in your class declarations thread myThread;. Then within your BroadcastReceiver after creating the new FileInput/OutputStream, have myThread = new thread(myHandler, myInputStream); followed my myThread.start();.
Now I noticed that you are communicating directly with the UI from your thread. You should use a handler instead that the thread will communicate to and then that will communicate back to your UI, at least from what I had read.
Here is an example of my handler and thread:
final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg){
}
};
private class USB_Thread extends Thread {
Handler thisHandler;
FileInputStream thisInputStream;
USB_Thread(Handler handler, FileInputStream instream){
thisHandler = handler;
thisInputStream = instream;
}
#Override
public void run(){
while(true) {
try{
if((thisInputStream != null) && (dataReceived == false)) {
Message msg = thisHandler.obtainMessage();
int bytesRead = thisInputStream.read(USB_Data_In, 0, 63);
if (bytesRead > 0){
dataReceived = true;
thisHandler.sendMessage(msg);
}
}
}
catch(IOException e){
}
}
}
}
Also, there are some demo open accessory application here. They may help with your understanding of accessory mode.
And also there are known issues with an application not receiving the BroadcastReceiver for ACTION_USB_ACCESSORY/DEVICE_ATTACHED programmatically. It will only receive it via the manifest file. You can find more on this here and here.
I actually didn't test putting the dataReceived variable in the handler and only recently changed that part of my code. I tested it and it didn't work, so trying to remember what it was I had read, I think it was not about variables communicating within the threads, but trying to use something like .setText(). I have updated my code to include the dataReceived=true in the thread. The handler would then be used for updating items on the UI, such as TextViews, etc.
Thread
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
usbThread = new USB_Thread(mHandler, mInputStream);
usbThread.start();