We are working on NFC tag android app and it is working properly 50% of times, and rest of the times we get NFC service dead exception in below try blocks:
Scenario is we connect to nfc Tag first time and send data, it always works fine.
Then we don't move phone away and after 1-2 seconds we again tries to connect to nfc tag(if not connected) to send data and 30% of times we get NFC service dead exception and it doesn't start until we disable and enable mobile's NFC.
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY
+ Process.THREAD_PRIORITY_MORE_FAVORABLE); //first line of doInBackground()
if(((ArrayList<Byte>) params[0]).size()<=0){
return "No image selected!";
}
NfcA nfcaTag = (NfcA) params[2];
try{
nfcaTag = NfcA.get(tag);
if (!nfcaTag.isConnected()){
nfcaTag.connect(); //this is line 175 MainActivity
}
try {
nfcaTag.close();
}
Exception:
NFC service dead
android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:622)
at android.nfc.INfcTag$Stub$Proxy.connect(INfcTag.java:285)
at android.nfc.tech.BasicTagTechnology.connect(BasicTagTechnology.java:73)
at android.nfc.tech.NfcA.connect(NfcA.java)
at de.silab.nfc.vistagnfcappv1.MainActivity$2.onClick(MainActivity.java:175)
at android.view.View.performClick(View.java:5723)
at android.view.View$PerformClick.run(View.java:22689)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6361)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
Is there any way to solve this issue. We are stuck here since long time.
And any way to restart NFCAdapter/ nfc service by catching this exception?
Your nfcaTag's hosting process is dead. It has been close()'d. Your first step should be to debug by logging info to the console about your variables to see if something is unusual.
I find it strange that you close() your nfcaTag immediately after connect()'ing it. Maybe these two statements conflict?
Also, consider why you have initialized the nfcaTag only to change it immediately in the next try statement.
Is your NfcA.get(tag) occasionally returning a null NfcA object? Is tag occasionally null? You need to test every variable, especially the ones you haven't shared here completely in your question.
Related
I seem to be having a small problem with MulticastSocket on Android: writing an SSDP-related application. The socket works just fine when I set everything up the first time, but when I stop discovery, and try to restart things, I just get a SocketException: Socket Closed. I'm not closing the socket, I'm simply stopping the Kotlin Coroutine that is responsible for calling socket.receive() in a loop. Example:
fun listenForPackets(): Flow<DatagramPacket> {
return flow {
multicastSocket.use {
val incomingBuffer = ByteArray(MULTICAST_DATAGRAM_SIZE)
while (true) {
val incomingPacket = DatagramPacket(incomingBuffer, incomingBuffer.size)
it.receive(incomingPacket)
emit(incomingPacket)
incomingPacket.length = incomingBuffer.size
}
}
}
}
The problem
So the problem is that when I try to call that function again, I get a SocketException: Socket Closed. The socket initialization code is run once, meaning that toggling discovery on/off will use the same socket multiple times; the following code is run once throughout the whole application:
multicastSocket = MulticastSocket(MULTICAST_PORT)
multicastSocket.reuseAddress = true
multicastSocket.joinGroup(multicastGroup)
multicastLock.acquire()
What I have tried
My first thought was that I was not cancelling the Kotlin Coroutine correctly. As a result, I switched to using typical Java Threads, to no avail. Starting the thread the first time works, but, restarting discovery yields the same problem. I have also tried to not leave the group, and keep the multicastLock acquired - same problem.
What works
What works is having the initialization code (where I assign the socket, join the group, and acquire lock) run every time I need to start a scan. At the end of the scan, I reset all of the variables (leave group, release lock, close socket). So my question becomes - is this the correct approach? Or am I simply doing something else wrong?
Just to re-iterate, I'm discovering packets just fine, the issue is with restarting the discovery. Thank you in advance for any help!
I've been getting reports of the following crash
SecurityException: <<other_package>> from uid xxx not allowed to perform READ_CLIPBOARD
The crash occurred when a user clicks on a button that copies a text into clipboard as shown below.
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("label", shareUrl)
clipboard.setPrimaryClip(clip)
So my app doesn't try to read anything from clipboard. Really confusing why this error could happen.
Does anyone know how this crash happen and how can I fix this?
Additional Information
This crash only happens in Android 9 and Android 10 and not happens easily (only 6 users from 200k monthly active users)
I only saw two <<other_package>> in Crashlytics (one is a Bank app and another is a Music app).
I tried to read the source code of ClipboardService.java and AppOpsManager.java and found that the crash might came from noteOp in AppOpsManager.
Here is the stack trace of the crash:
Fatal Exception: java.lang.SecurityException: <<other_package>> from uid xxx not allowed to perform READ_CLIPBOARD
at android.os.Parcel.createException(Parcel.java:2087)
at android.os.Parcel.readException(Parcel.java:2055)
at android.os.Parcel.readException(Parcel.java:2003)
at android.content.IClipboard$Stub$Proxy.setPrimaryClip(IClipboard.java:293)
at android.content.ClipboardManager.setPrimaryClip(ClipboardManager.java:106)
at my.package.MyClass.copyToClipboard(MyClass.java:63)
at android.view.View.performClick(View.java:7375)
at android.view.View.performClickInternal(View.java:7336)
at android.view.View.access$3900(View.java:822)
at android.view.View$PerformClick.run(View.java:28214)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:238)
at android.app.ActivityThread.main(ActivityThread.java:7829)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:986)
Caused by android.os.RemoteException: Remote stack trace:
at android.app.AppOpsManager.noteOp(AppOpsManager.java:2568)
at com.android.server.clipboard.ClipboardService.clipboardAccessAllowed(ClipboardService.java:933)
at com.android.server.clipboard.ClipboardService.setPrimaryClipInternal(ClipboardService.java:775)
at com.android.server.clipboard.ClipboardService.setPrimaryClipInternal(ClipboardService.java:710)
at com.android.server.clipboard.ClipboardService$ClipboardImpl.setPrimaryClip(ClipboardService.java:358)
I can finally reproduce the crash in Android 9. This is what I found...
Root cause: When foreground app calls setPrimaryClipboard, the ClipboardService will broadcast the event to PrimaryClipChangedListener (if any) and will also make a call to AppOpsManager.noteOp to inform about READ_CLIPBOARD operation.
If the listener is not allowed to READ_CLIPBOARD (user can disallow by using adb shell command: cmd appops set <package> READ_CLIPBOARD deny), AppOpsManager.noteOp will throw a SecurityException and will crash the foreground app.
Now I'm sure that my code doesn't do anything wrong, but unfortunately I think I have to put try/catch around setPrimaryClip
Very rarely getting:
Fatal Exception: java.lang.IllegalArgumentException: Unknown URL content://com.example.provider/info
at android.content.ContentResolver.insert(ContentResolver.java:1252)
Fatal Exception: java.lang.IllegalArgumentException: Unknown authority com.example.provider
at android.content.ContentResolver.applyBatch(ContentResolver.java:1247)
Emphasis on rarely. Generally work fine without issue, so the authorities is set up fine, but this is showing up every once in a while for no reason. Are there reasons why the ContentResolver may not be able to find a ContentProvider (i.e. if not set up yet)?
I've had the rare IllegalArgumentException with Unknown URIs issue when I was doing ContentResolver operations in the custom Application object.
For example, I was trying to delete items in my content provider in the application onCreate method which would very occasionally crash:
public class CustomApplication extends Application {
#Override
public void onCreate() {
//..
context.getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
//..
}
}
Which would sometimes render the following crash:
Fatal Exception: java.lang.RuntimeException: Unable to create application com.myapp.CustomApplication: java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6431)
at android.app.ActivityThread.access$1800(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7331)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
at android.content.ContentResolver.delete(ContentResolver.java:1376)
at com.myapp.ReminderEntryDao.delete(Unknown Source)
at com.myapp.CustomApplication.onCreate(Unknown Source)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1037)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6428)
at android.app.ActivityThread.access$1800(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7331)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
I also saw similar behaviour with a BOOT_COMPLETE receiver. I had about 70 reported crashes with this exception (mostly Infinix devices ~43%, hardly any Samsung Devices) of about 200 000 monthly active users.
I moved this into a background scheduled job and haven't seen the crash since. I was only ever able to reproduce this issue once on a Nexus device that I used but never again.
I suspect perhaps sometimes on some versions of Android on some devices the Application/BOOT_COMPLETE Receiver initializes before the ContentProvider is fully initialized and therefore when it tries to access it, it is not properly set up yet.
There are a couple of stackoverflow posts that do state exactly what is created first and how the OS should behave:
Is the Application class guaranteed to be instantiated before a defined boot receiver is called
But like I said, I've seen otherwise and moving operations out of the classes into background schedulers seems to fix the problem (perhaps it is just because it takes a bit longer to get setup). Hopefully my experience will help you.
Edit: I used the evernote job dispatcher and deferred my ContentResolver operations to the job if required. (but I would assume that deferring the content provider operation to any kind of background processing might fix it as it had a bit more time to get setup - these are just my suspicions of course).
class DeleteRemindersJob extends Job {
#NonNull
#Override
protected Result onRunJob(final Params params) {
cursor = getContext().getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
//..
return Result.SUCCESS;
}
}
As we all know android doesn't unload *.so after close application. I had found the solve by adding "exit(0)" at the end, that is solved problem, but I wanna know exactly that all are OK.
The code is work fine as expected after solving the problem:
static int value = 0;
// In android_main
LOGI("value = %d", value); // always print 0, but not 1 after second run of
// application as it was without "exit(0)" at the end
value = 1;
I wanna to test that on class like:
class A {
A() {
LOGI("Constructor");
}
~A() {
LOGI("Destructor");
}
statis A a;
In such way prints only "Constructor".
Maybe because of destructor is calling after when LOGI isn't working more for application that will be closed ?
Question: why LOGI in destructor isn't working? According to first example on top destructor is calling really.
This is not only pointless, but quite possibly counterproductive. If android wants the memory utilized by your process, it will terminate the process to reclaim it; if it doesn't, it won't.
To specifically address your question, killing or exiting a process does not invoke destructors, it merely terminates execution and the kernel bulk-releases all memory and (conventional) resources.
Do not try to second guess the system, as that can frequently result in killing a process only to have android immediately restart it. Further, it can allegedly cause problems with a few Android IPC resources (like the camera) which may not be freed up when the process of a utilizing application unexpectedly dies.
I've been working on a widget for a while, and it usually works fine when I try to run it or update the code, even after a crash. However, every once in a while it seems to have a "major" crash and the widget becomes completely unresponsive afterwards. Even if I try to push new code to the phone it remains unresponsive after the update.
I've tried uninstalling the widget and reinstalling it, only to have the same thing occur. The only thing that seems to work is if I do a factory reset of the phone. After that, the widget works fine until I start changing the code and I run into another such crash. However, I'd like to not have to do a factory reset every few days.
Has this happened to anyone/does anyone know what might be the cause of this? Is there some data stored on the phone somewhere that prevents it from ever working again after the first crash?
Here's what the error log looked like:
java.lang.RuntimeException: Unable to start receiver com.alienweed.test.HelloWidget: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2058)
at android.app.ActivityThread.access$2400(ActivityThread.java:132)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1098)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
This should fix the crash.
Cursor curs = db.query(params...);
/* check the cursor now */
if(curs.moveToFirst()) { // `moveToFirst()` returns false if cursor is empty.
// access the cursor.
}