How to get ACRA to stop app when exception is not in main activity? - android-activity

I want my app to stop when ACRA detects and reports an uncaught exception - normal ACRA behavior. This is not working when the exception happens in an activity that is not the main activity.
After fighting this in my actual app, I created a very simple app that uses ACRA, and allows me to force an exception in either the main activity, or a second one that can be started from the first. I am testing with a MinSDK of 26. The app is in Java and has only enough code to generate this test.
An exception in the first activity produces the desired result (as determined from logcat and the screen):
On button touch, main activity generates an exception
ACRA catches the exception:
ACRA starts another application process
the first process ends
the second process does ACRA processing
the second process ends
However, running again, but with the exception in the second activity (with the first still on the task stack), results in:
On button touch, main activity starts second activity
On button touch, second activity generates an exception
ACRA starts another application process
First process ends
ACRA processes in the second process (also using this code base)
meanwhile Android starts yet a third process - this is the problem
The second process finishes
The third process displays the main activity screen, and waits
What seems to be happening is that Android is detecting that there is an activity left on the stack, and is starting a new process to bring that one forward.
But, ACRA should be stopping this.
Is this an ACRA problem? In any case, ideas on how to prevent it?
*NOTE:
In my tests, I am using touch events on a bottom navigation bar to generate a divide by zero exception.
The order of when ACRA finishes and the third process starts is indeterminate, as far as I can tell. It is also probably irrelevant.
Test results are from watching the screen, and logcat. Important evens are logged using the Log class.
Below is a snippet from the main activity that shows the button processing, and the exception generation. The second activity is similar.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Context context = this.getApplicationContext();
setContentView(R.layout.activity_main);
Log.i(MyApp.TAG, "MainActivity.onCreate() - pid:"+android.os.Process.myPid());
mTextMessage = findViewById(R.id.message);
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener((item) -> {
switch (item.getItemId()) {
case R.id.navigation_home:
int i = 0;
Log.i(MyApp.TAG, "Throwing exception in main activity");
Log.i(MyApp.TAG, "This shouldn't show up" + 3 / i);
return true;
case R.id.navigation_dashboard:
Log.i(MyApp.TAG, "Starting Activity2");
startActivity(new Intent(context, Activity2.class));
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
}
return false;
});

This is a bug in ACRA, fixed by this PR, which will be included in the next release (5.3.0).

Related

How to keep the processing time within OnSleep()?

I am currently developing a Xamarin Forms UWP application. I am trying to save data when OnSleep () is called when the application ends, but it ends in the middle of the process. How can I continue processing to the end?
I tried how much processing time can be secured in OnSleep ().
in App.xaml.cs
protected override async void OnSleep()
{
// Handle when your app sleeps
Tracer.WriteLine("OnSleep In");
await Task.Delay(2000);
Tracer.WriteLine("OnSleep Out");
}
Expected result
14:25:21.414 OnSleep In
14:25:23.414 OnSleep Out
Actual result (never comes OnSleep Out)
14:25:21.414 OnSleep In
14:25:21.827 OnSleep In
program ended

Eclipse Jobs stay in the Progress View after returning an OK status

I have a an Eclipse Job class similar to the following:
public class MyCustomJob extends Job {
#Override
protected IStatus run(IProgressMonitor monitor) {
MyObject.blockingMethod();
return Status.OK_STATUS;
}
}
When I execute this job and it exits correctly, the bottom-right where the progress is listed while it is running still shows the name of the now completed job, but without any progress bar.
If I double click in the region where the name of the job still is, the Progress View opens as expected, but shows that the job has finished. If I click the "x" to clear the job, it disappears from the view, but if I close the view and reopen it, it comes right back.
How can I remove the name of the job from the bottom-right of the display and guarantee that if I clear the Finished job from the Progress View that is actually being dismissed?
Check the return path for any async UI execs that could affect status. Changing
from:
Platform.getDefault().asyncExec(runnable)
to
Platform.getDefault().syncExec(runnable)
fixed this issue

How to know any UI rendering is completed in automation code

I am wanting to know a button is rendered on main window UI or not. This button rendering is depending on server response result (written in Objective C). If server response comes perfectly it becomes render perfectly (VISIBLE) otherwise it is not present there (INVISIBLE). And whenever it becomes visible I always tap on it for further next process.
I wrote code
UIATarget.localTarget().pushTimeout(200);
//My code
UIATarget.localTarget().popTimeout();
By the above code I have to wait till 200 sec but my concern is I want to wait but whenever object is on screen I don't want keep me busy in WAITING MODE.
How will I write code in automation?
Thanks
Ok, this might give you idea how to follow-up:
For your view implement an accessibilityValue method which returns a JSON formatted value:
- (NSString *)accessibilityValue
{
return [NSString stringWithFormat:
#"{'MyButtonisVisible':%#}",
self.MyButton.isHidden ? #"false" : #"true"];
}
Then somehow you can access it from your test javascript:
var thisproperty = eval("(" + element.value() + ")");
if (thisproperty.MyButtonisVisible) {
UIATarget.localTarget().tap({"x":100, "y":100});
}
Hope that helps.
If you make the name different when you enable the button you can do this:
var awesomeButton = target.frontMostApp().mainWindow().buttons()[0];
UIATarget.localTarget().pushTimeout(200);
awesomeButton.withName("My Awesome Button");
if (awesomeButton.isVisible()) {
UIALogger.logError("Error no awesome button!");
}
UIATarget.localTarget().popTimeout();
withName will repeatedly test the name and control will return to your script once the name matches or when the time out is reached.
Per Apple's Doc
withName:
Tests if the name attribute of the element has the given string value. If the match fails, the test is retried until the current timeout expires.
Timeout Periods:
If the action completes during the timeout period, that line of code returns, and your script can proceed. If the action doesn’t complete during the timeout period, an exception is thrown.
https://developer.apple.com/library/etc/redirect/xcode/ios/e808aa/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UsingtheAutomationInstrument/UsingtheAutomationInstrument.html#//apple_ref/doc/uid/TP40004652-CH20

how to update/refresh Progress View from a long-running non-UI Job in eclipse rcp

i have a long-running non-UI Job with a number of sub-tasks. each sub-task updates caption for the Job's progress entry in the Progress View via IProgressMonitor.subTask(some-caption). the Job goes through three sub-tasks before it contributes to the UI in its fourth sub-task (via Display.syncExec() of course) by creating a new IEditorPart instance. the problem is that those initial three sub-tasks are never reflected in the Job's progress entry in the Progress View. in fact, the Job progress entry never actually appears in the Progress View until fourth sub-task. this, of course, creates a problem for a user who is left to wonder if anything is even happening. my guess is that once the Job starts, the vm thread "broker" (sorry, not well versed in this matter) never gets a chance to switch from a non-UI Job thread to the UI thread until the former actually makes a call to the latter via Display.syncExec(). my only solution at this point is to put Job thread to sleep for about half a second right after each sub-task kicks in, thereby allowing UI thread to take over long enough to update Progress View. and while this has worked most of the time, i still get instances here and there where the Porgress View still remains empty until fourth sub-task, leading me to believe that my solution is not of a robust kind. hence, i am looking for a robust one. thank you for your time!
EDIT: example code
Job job = new Job("multipleTasks") {
public IStatus run(IProgressMonitor monitor) {
monitor.beginTask("multiple tasks", IProgressMonitor.UNKNOWN);
monitor.subTask("task1");
monitor.worked(1);
try { Thread.sleep(1000); } catch (Exception e) { }
monitor.subTask("task2");
monitor.worked(1);
try { Thread.sleep(1000); } catch (Exception e) { }
monitor.subTask("task3");
monitor.worked(1);
try { Thread.sleep(1000); } catch (Exception e) { }
monitor.done();
return Status.OK_STATUS;
}
};
job.schedule();

Stop httputils service in basic4android

I am using basic4android and I made an application that uses httputils services. Sometimes a remote error occurs (possible server overload or limited internet connection) and the application exits with the error message box. The activity closes but httputils service is still running. While I reopen the activity new error occurs, because of the unfinished job of httputils. Everything is OK only if I choose to stop the activity in the second error.
Is there any way to determine if the httputils service is running by a previous instance of my app? Or better, a way to try to stop this service either its running or not.
HttpUtils errors should not cause your program to exit. You should check IsSuccess to make sure that the call succeeded or not.
You can stop the service from running by calling StopService(HttpUtilsService).
Public Sub StationTransfer_Click
Dim job As HttpJob
job.Initialize("MyJob", Me)
Dim URL As String="https://www.yourserver.com/myjob.asmx/GetData?parameter1=abc"
job.Download(URL)
ProgressDialogShow2("Getting data From Server...", True)
End Sub
Sub JobDone(Job As HttpJob)
Select Job.JobName
Case "MyJob"
HandleMyJob(Job)
End Select
Job.Release
End Sub
Sub HandleMyJob(Job As HttpJob)
If Job.Success = False Then
ToastMessageShow("Error downloading Data", True)
ProgressDialogHide
Return
End If
....
end Sub
if there is an httpjob error you catch it in the handler function by looking at the status. if the status is not success than you catch it and display a message.