Android application not crashing when it should [ACRA] - android

Hi all,
I'm using (trying at the moment) ACRA for bug-reporting. Scenario is:
I open the app: ACRA outputs ACRA is enabled for mypackage, intializing...
I enter the Settings (where I prepared a NullpointerException)
The app freezes and Preparing crash dialog is output via a toast
The app does not close, but instead outputs the same toast again and again (all Views are gone)
When I close the app, after a few seconds (of gathering data I guess) the crash dialog opens
I have the following Annotation in front of my Application subclass:
#ReportsCrashes(formKey = "iwontshowyoumyformkey", customReportContent = {
REPORT_ID, APP_VERSION_CODE, ANDROID_VERSION, PHONE_MODEL, BRAND,
STACK_TRACE },
mode = ReportingInteractionMode.DIALOG,
resToastText = R.string.acra_toast_text,
resDialogText = R.string.acra_dialog_text,
resDialogTitle = R.string.acra_dialog_title,
resDialogCommentPrompt = R.string.acra_dialog_comment_prompt,
resDialogOkToast = R.string.acra_dialog_ok_toast,
forceCloseDialogAfterToast=true)
A notable detail is that the error occurs again and again, according to the Logcat.
This made me think that the activity is restarted all the time, and the error is in onCreate...
But the fact that the tag is ACRA made me unsure if it isnt ACRA, reoutputting the error.
Problem: The app should be crashed and closed so that the dialog can appear, but isn't.
Question: How would I go about debugging/solving this? A solution would be even better...
Thank you in advance,
Till

It's not solved, but I decided to not spend any more time on it, and abandon ACRA.
Crittercism has proven to be quite painless.

Related

Android Studio - showing new activity over other apps results in a blackscreen

I'm trying to develop an android app for the SDK version 30 that (when a button is clicked) starts listening to what apps are opened on the phone. If it detects the user opening Whatsapp, it is supposed to show a LockScreen activity over Whatsapp that makes you answer a math question before being able to use Whatsapp.
I know this can be done as their are apps like QualityTime or Forest that have similar features to restrict you from using certain apps, but I am a newbie when it comes to programming (probably obvious from my code) and feel totally stuck.
I have already figured out how to detect what app the user opened in the last second with code from stack overflow:
public String getCurrentApp() {
String topPackageName = "None";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService("usagestats");
long time = System.currentTimeMillis();
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 1, time);
// Sort the stats by the last time used
if (stats != null) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : stats) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (!mySortedMap.isEmpty())
{
topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
}
return topPackageName;
}
I have another function that is started when the user clicks the button in my app to "activate" the listening process. This function keeps checking if the user opens Whatsapp and is then supposed to display the Lockscreen activity on top:
public void startListening(View view)
{
System.out.println("Lock activated.");
while (activated) {
String currentlyRunningApp;
currentlyRunningApp = getCurrentApp();
if (currentlyRunningApp.equals("com.whatsapp"))
{
System.out.println("Whatsapp detected. Showing Lockscreen...");
Intent i = new Intent(this,LockScreen.class);
startActivity(i);
}
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
(All of the code I have shown is in my MainActivity btw.)
I have the following permissions granted to my app:
android.permission.PACKAGE_USAGE_STATS (for the getCurrentApp() function)
android.permission.SYSTEM_ALERT_WINDOW (as suggested here)
android.permission.ACTION_MANAGE_OVERLAY_PERMISSION (although I am not sure I even need this one)
My problem is, that instead of showing the Lockscreen activity I created, it only shows a blackscreen for the user. The Lockscreen activity itself works fine if I let the user open it through a button on the mainActivity, so the issue seems to really be that I can not properly show an activity if my app is running in the background and I want to display it on top of Whatsapp.
I have tried to look through similar questions, but all of the posts on here with similar use cases seem to be very old and outdated (i.e. this or this), as the newer versions seem to have way tighter security restrictions.
I also tried to do it with a screen overlay instead of an activity (using this source), but this doesn't even give me a blackscreen - just does nothing...
I am also aware that there are probably better ways to program the whole "listening and checking for whatsapp" part - i.e. with a service instead of a while-loop or something, but I only found out about services while researching this problem and I'd like to fix the blackscreen issue first.
After lots of trial and error I figured out that the issues was indeed caused by a missing permission, but one that I could not find on any stack overflow answer related to black screen problems. On top of that, I believe it's an issue that only occurred because I used a Xiaomi device for testing.
There are currently two separate permissions for displaying screens over other apps that you will need to grant:
Display over other apps, also called Display pop-up window. This is the android.permission.ACTION_MANAGE_OVERLAY_PERMISSION that I wasn't sure was even needed. So to emphasize, I definetly do need this permission.
Display pop-up windows while running in the background. This is the permission I was missing.
After I allowed them both (which you can do under Settings > Apps > Manage Apps > Your App > Other Permissions) everything worked fine.
To direct the user directly to the settings menu where they can allow these permissions, I used the code from this stack overflow answer. This is also where I got the info that it's a xiaomi-specific "issue".

displaying runtime errors in android/ios installed app

I've been trying to get errors to display in a text field within the app for ease of error reporting from users.
I've had some success using this code I found on stackoverflow. It's used at the top level of the app but it's not working on device:
//start code
this.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, errorHandler);
function globalErrorHandler(event:UncaughtErrorEvent):void
{
var message:String;
//check for runtime error
if (event.error is Error)
message = (event.error as Error).getStackTrace();
//handle other errors
else if (event.error is ErrorEvent)
message = (event.error as ErrorEvent).text;
else
message = event.error.toString();
//do something with message (eg display it in textfield)
myTextfield.text = message;
}
//end code
At first this wouldn't work on the device and I thought it was because upon the error, when developing on the pc, flashplayer would display the actionscript popup with the error. Which you would need to click "dismiss all" or close and then the globalErrorHandler was called after and then the error written to the textfield. I thought this is what was keeping it from showing up on the device. However, by adding event.preventDefault() I was able to suppress the actionscript popup when developing on the desktop and the error was written to the textfield successfully. This was not the case however on the andriod device. It still just hangs on the error. It's as if the default error event cannot be suppressed on android.
Thanks for your time. Any help appreciated!
EDIT 22/09/2017: I was able to see the error on device finally. It had to do with while on desktop publishing the error would be shown. However, on device the behavior was different and something was covering the textfield, by bring it to the front on error I was able to see it. However, I still see that some errors deeper in the class hierarchy are not being caught.
In our project we have it simpler (and it is working):
stage.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
private function onUncaughtError(e:UncaughtErrorEvent):void
{
// Console is basically a TextField for debug/diagnosis output.
if (e.error) Console.error(e.error.getStackTrace());
e.preventDefault();
}
The other thing you should probably check is whether your TextField actually displays any text at all for there might be text embedding issues, unrelated to the error handling routine.
UPD: Loading SWFs so it doesn't mix with the parent.
var request:URLRequest = new URLRequest(path);
var context:LoaderContext = new LoaderContext;
context.applicationDomain = ApplicationDomain.currentDomain;
var loader:Loader = new Loader;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
loader.load(request, context);

Fabric Crashlytics for android - how to include additional info in stackTrace area

I would like to get a object dump additionally sent during a crashlytics exception logging. So for example lets say there is a nullPointerException that occurs. i'd like to additionally add a large object which would be my model and include that in the stack trace area in crashlytics. this way when i see the stacktrace i can also view the model information from the dump. How would i send this info in additional to the usual crashlytics logging ? Here is what i have so far:
try{
//....
throw new NullPointerException("my cool msg");
}
catch(Exception e){
Crashlytics.setInt("priority", 4);
Crashlytics.setString("tag", "mytag");
Crashlytics.setString("message", Model.toString());
Crashlytics.logException(e);
}
What is occuring now is that nothing is appearing. but if i comment out the setString for "message" then i get a stacktrace with the message "my cool msg".
UPDATE: I even tried Crashlytics.log(Model.toString()); but that shows nothing on crashlytics. i am setting up crashlytics from Application subclass in onCreate like this: Fabric.with(this, new Crashlytics());
from the cashlytics docs i found this:
To make sure that sending crash reports has the smallest impact on your user’s devices, Crashlytics logs have a maximum size of 64 KB. When a log exceeds 64 KB, the earliest logged values will be dropped in order to maintain this threshold.
this could be my issue. checking my size now...
adjusting the size of the payload did not work. i made the payload 9 characters but still its not appearing.
UPDATE:
Lets start again but more simply. why does the following not work for me ?
try{
//....
throw new NullPointerException("my cool msg");
}
catch(Exception e){
Crashlytics.setInt("priority", 4);
Crashlytics.setString("tag", "mytag");
Crashlytics.setString("message", "");
Crashlytics.logException(e);
}
What happens here is indeed a stacktrace appears in crasylytics dashboard with the words "my cool message" but there is nothing about priority, tag or message. Only the stacktrace is appearing. should there
not be entries there with these headings or something ?
AFter clicking on the green "view all sessions" button i was able to see the custom information. they could have made it more obvious.
and also from the docs it seems the non-fatal exceptions are batched and sent the next time the app launches:
Crashlytics processes exceptions on a dedicated background thread, so the performance impact to your app is minimal. To reduce your users’ network traffic, Crashlytics batches logged exceptions together and sends them the next time the app launches.

ACRA send report without exiting app

Just started using ACRA. When the application crashes it sends a report to my server. All is well.
But there are exceptions which I can catch and let the user keep the problem without error - like using default values. But I'd like to get an error report without bothering the user. But when I do:
ErrorReporter errorReporter = ACRA.getErrorReporter();
errorReporter.putCustomData("test", "value");
errorReporter.handleSilentException(null);
the application shuts down. I first tried throwing some error (testing purposes), I hoped sending null would stop the app from stopping - I was wrong.
Is there a way to use ACRA to send an error report without exiting the app? Just thought I had it, but
ErrorReporter errorReporter = ACRA.getErrorReporter();
errorReporter.putCustomData("test", "value");
errorReporter.handleException(null, false); // false is endApplication param, `null` seems to result in a NullPointerException
This also closes the application (without an additional Exception from ACRA):
ErrorReporter errorReporter = ACRA.getErrorReporter();
errorReporter.putCustomData("test", "value");
errorReporter.handleException(new RuntimeException("message"), false); // tried `true` also, just in case
Also closes the app
Update:
(1) LogCat shows no stack trace.
(2) While reading the error report, my eye fell on
"DUMPSYS_MEMINFO":"Permission Denial: can't dump meminfo from from pid=1416, uid=10048 without permission android.permission.DUMP\n"
Tried to add android.permission.DUMP to androidmanifest.xml, but I get Permission is only granted to system apps. Reason for exiting app? Work around? It gets all information that I need (and more)...
As it turns out, the above code is correct. The problem was in that I have overwritten the ErrorReporter:
new HttpSender(org.acra.sender.HttpSender.Method.PUT, org.acra.sender.HttpSender.Type.JSON, null) {
#Override
public void send(final Context context, final CrashReportData report) throws ReportSenderException {
super.send(context, report);
respondAsIfCrashing(); // not the real method name
}
};
The application wasn't crashing, it just appeared to do that, because of the respondAsIfCrashing method.
The warning DUMPSYS_MEMINFO":"Permission Denial: can't dump meminfo from from pid=1416, uid=10048 without permission android.permission.DUMP is, apparently, not a reason to crash... (perhaps just not writing to device?)
So using
ErrorReporter errorReporter = ACRA.getErrorReporter();
errorReporter.handleException(new RuntimeException("message"), false);
Is sufficient

How to programatically change ACRA 'interaction mode' setting

I'm implementing ACRA in my Android App. I would like to be have it's interaction mode be silent by default, but if I see that a new version of my App is available, "Toast" the user upon crash with a message to update their copy of the App.
However it seems that ACRA interaction mode must be hard coded and loaded once upon init of application. Any way to set the mode at that point not via a hard coded setting? E.g. I'm looking to control the "mode = " setting which is copied below.
#ReportsCrashes(formKey = "xxxxxxxxxxxxxxxx",
mode = ReportingInteractionMode.TOAST,
resToastText = R.string.crash_toast_text)
public class MyApplication extends Application ...
I see that ACRA Issue 85 has added setters for resources for Toast parameters, but does it also have ability to configure interaction mode?
Maybe this? I didn't try but seems useful (at point of start)
http://www.java2s.com/Open-Source/Android/App/acra/org/acra/ErrorReporter.java.htm

Categories

Resources