Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind to AccessibilityService in Android?

I have created an android Service, which extends an AccessibilityService. From my Activity, I would like to bind to that Service. Because I need to send information from Service to Activity. I need example code please. I have searched google and have not found anything similar, someone could put a link to an example please.

like image 567
alvaro Avatar asked Sep 18 '12 11:09

alvaro


2 Answers

While binding with an AccessibilityService from an Activity is possible, you'll only be able to pass AccessibilityEvents into the service. This is because AccessibilityService.onBind() is declared final, which means you won't be able to add any new methods to the binder.

There are, however, several alternative solutions.

If your activity and service are running within the same process (this is typically true if they are in the same APK), then you can communicate with a static instance of your accessibility service. Here is an example of how that would work:

MyAccessibilityService.java:

private static MyAccessibilityService sSharedInstance;

protected void onServiceConnected() {
    . . .
    sSharedInstance = this;
}

public boolean onUnbind(Intent intent) {
    sSharedInstance = null;
    . . .
}

public static MyAccessibilityService getSharedInstance() {
    return sSharedInstance;
}

MyActivity.java

protected void onCreate() {
    . . .
    mAccessibilityService = MyAccessibilityService.getSharedInstance();
    if (mAccessibilityService != null) {
        // The service is running and connected.
        mAccessibilityService.doSomething();
    }
}

If your service and activity are in separate processes (e.g. separate APKs), then you still have a few options:

  • Communicate by broadcasting Intents from your activity to a BroadcastReceiver in your service
  • Bind your activity to a "proxy" service within the AccessibilityService's process that communicates with a static instance (as above)

If you need elaboration on either of those, leave a comment.

like image 158
alanv Avatar answered Sep 22 '22 06:09

alanv


Maybe there is another way to communicate whith each other:

  1. At AccessibilityService Child Class:

    Handle the target Activity's:
    PackageName AND
    ActivityName AND
    specific EventType(eg:AccessibilityEvent.TYPE_VIEW_CLICKED)

    @Override
    public void onAccessibilityEvent(final AccessibilityEvent event)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
            if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED)
                if (AccessibilityUtils.findNodeInfoByViewTypeAndText(event.getSource(), "android.widget.ToggleButton", TextUtils.getString(R.string.lable_disabled)) != null)
                    getAccessibilityService().disableSelf();
    }  
    
  2. At target Activity:just invoke the specific EventType

    invoke by user OR
    invoke by code

    btnEnableService.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(final View v)
                {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !btnEnableService.isChecked())
                    {
                        btnEnableService.setChecked(false);
                        txvEnabledState.setText(btnEnableService.isChecked() ? R.string.lable_service_status_enabled : R.string.lable_service_status_closed);
                        AppState.instance().setIsEnable(btnEnableService.isChecked());
                    }
                    else
                    {
                        openAccessibilitySettings();
    
                        btnEnableService.setChecked(!btnEnableService.isChecked());
                    }
                }
            });
    

Sample Code:

  • AppEventHandler_disableSelf.java — Bitbucket
  • SettingActivity.java — Bitbucket
like image 44
Asion Tang Avatar answered Sep 20 '22 06:09

Asion Tang