There is an android application that uses AccessibilityService. After the user's permission, the application connects to the service and works with it. But it turned out that if the application crashes, it is automatically disconnected from the service. When you restart the application, the service does not work, but there is permission to connect to it. It is possible to reconnect to the service if in the settings of the spec. options to disable and re-enable the use of the service. Question: Is it possible to programmatically restore the connection to the service, if it is already allowed?
- interest Ask. find a solution, be sure to write. The service is local, i.e. on the phone? Does it fall with the app? - George Chebotaryov
- The application has a service (part of the application) that inherits the AccessibilityService. Accordingly, when the application crashes, the service closes and loses connection with the AccessibilityService. My task is to restore this connection, without going back into the device settings. - Maxim Povolotsky
1 answer
During the experiments, it turned out that when the program crashes, the system destroys all the classes created by the program, including MyAccessibilityService, which was associated with the system AccessibilityService. I didn’t find any tools allowing to forcefully reconnect with the system service, but it turned out that if you use UncaughtExceptionHandler (see the article for more details), the application remains “alive” and only the activation in which the error occurred falls. After restarting the activation, the connection with the system service is saved and the application is working normally.
ps Generation and trapping errors were carried out only in the activation, but I think a similar mechanism can be "sewn" in the service or the receiver. If anyone has other options, I listen carefully.
Update: The solution below works on 3 out of 4 tested devices !!! The service continues to fall off on Xiaomi Redmi4A (Android 7.1.2) To catch errors of any application components, the following was done: The MyApplication class was created, inheriting the application itself:
public class MyApplication extends Application { private static MyApplication instance; @Override public void onCreate() { super.onCreate(); instance = this; //This is crash catcher!; Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler(this)); } public static ContextWrapper getInstance() { return instance; } } Created class DefaultExceptionHandler:
public class DefaultExceptionHandler implements Thread.UncaughtExceptionHandler { private Context context; public static final String NAME_ERROR_MESSAGE = "error_message"; public DefaultExceptionHandler(Context context) { this.context = context; } @Override public void uncaughtException(Thread t, Throwable ex) { ex.printStackTrace(); Log.d("nocrash", "Localized Message: " + ex.getLocalizedMessage()); try { Intent intent = null; intent = new Intent(context, AfterCrashActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); // Информацию об ошибке можно будет увидеть в AfterCrashActivity intent.putExtra(NAME_ERROR_MESSAGE, ex.getMessage()); PendingIntent pendingIntent = PendingIntent.getActivity( MyApplication.getInstance().getBaseContext(), 0, intent, intent.getFlags());//getBaseContext() is null //Following code will restart your application after 2 seconds AlarmManager mgr = (AlarmManager) MyApplication.getInstance().getBaseContext() .getSystemService(Context.ALARM_SERVICE); if (mgr != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2000, pendingIntent); } else { mgr.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2000, pendingIntent); } } else { mgr.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2000, pendingIntent); } } //This will stop your application and take out from it. System.exit(2); } catch (Exception e) { e.printStackTrace(); } } } AfterCrashActivity make out to your taste. I have a button "Close application", "Try again" and "Submit error information".