Cannot override the final method from AbstractInputMethodService - android

I have a service class that extends InputMethodService. When i want to bind this service to my ActivityMain, at code below i get the "Cannot override the final method from AbstractInputMethodService" error.
public class MyIME extends InputMethodService
implements KeyboardView.OnKeyboardActionListener, OnSharedPreferenceChangeListener {
//some code here...
#Override
public IBinder onBind( Intent intent ) {
return binder;
}
What is this error and how to fix it?

What is this error
onBind() is declared as final in AbstractInputMethodService. You cannot override it.
and how to fix it?
Delete your onBind() method.

Related

Instrumentation test cases for InputMethodService

I have extended the InputMethodService class to create my a custom IME. However, I am struggling to write valid Instrumentation test cases to verify the behavior. Previously the Service, could be tested using ServiceTestCase<YourServiceClass>. But it seems to have been deprecated, and the new format looks like this. Now in the given guidelines, I am struggling with this snippet:
CustomKeyboardService service =
((CustomKeyboardService.LocalBinder) binder).getService();
Since I am extending InputMethodService, it has already abstracted the IBinder, how can I obtain LocalBinder to get this snippet running? Currently, this snippet throws following exception:
java.lang.ClassCastException:
android.inputmethodservice.IInputMethodWrapper cannot be cast to
com.osrc.zdar.customkeyboard.CustomKeyboardService$LocalBinder
The extended class looks like:
public class CustomKeyboardService extends InputMethodService {
// Some keyboard related stuff
public class LocalBinder extends Binder {
public CustomKeyboardService getService() {
// Return this instance of LocalService so clients can call public methods.
return CustomKeyboardService.this;
}
}
// Some keyboard related stuff
}
How can I extend my custom class such that CustomKeyboardService service
= ((CustomKeyboardService.LocalBinder) binder).getService(); doesn't returns error?
Here is my test case code:
#RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest2 {
#Rule
public final ServiceTestRule mServiceRule = new ServiceTestRule();
#Test
public void testWithBoundService() throws TimeoutException {
// Create the service Intent.
Intent serviceIntent =
new Intent(InstrumentationRegistry.getTargetContext(), CustomKeyboardService.class);
// Bind the service and grab a reference to the binder.
IBinder binder = mServiceRule.bindService(serviceIntent);
// Get the reference to the service, or you can call public methods on the binder directly.
// This Line throws the error
CustomKeyboardService service =
((CustomKeyboardService.LocalBinder) binder).getService();
}
}
You can also check out OimeKeyboard on Github for full source code and submit a PR with a valid instrumentation test case.
Same issue happend to me, please check below link's solution.
Updated code snippets from link :
#Rule
public final ServiceTestRule mServiceRule = new ServiceTestRule();
private MyKeyboard retrieveMyKeyboardInstance(IBinder binder) {
try {
Class wrapperClass = Class.forName("android.inputmethodservice.IInputMethodWrapper");
Field mTargetField = wrapperClass.getDeclaredField("mTarget");
mTargetField.setAccessible(true);
WeakReference<MyKeyboard> weakReference = (WeakReference<MyKeyboard>) mTargetField.get(binder);
return weakReference.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void validateEditTextWithKeyboardInput() throws TimeoutException {
...
Intent serviceIntent = new Intent(InstrumentationRegistry.getTargetContext(), MyKeyboard.class);
IBinder binder = mServiceRule.bindService(serviceIntent);
MyKeyboard keyboard = retrieveMyKeyboardInstance(binder);
...
}
From : https://github.com/sealor/prototype-Android-Espresso-Keyboard-Testing

How to inject a bound service into an Activity via dagger?

I would like to inject a bound service into my activity via Dagger2.
My Service is declared as follow:
Public class MyService extends Service{
private final IBinder mBinder = new LocalBinder();
...
public class LocalBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void doBackgroundTask() {
...
}
}
My Activity:
public abstract class MainActivity extends AppCompatActivity {
#Inject
MyService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
service.doBackgroundTask();
...
}
How would you achieve that ? Where will you put the ServiceConnection (into a base class, inside the module) ?
Thanks a lot.
I don't think that injecting the service that way (via injected field) will work because you don't control the instantiation of the service's object.
If your service contains fields that need to be injected you will have to inject in onCreate() the same way you inject your activities, i.e. calling DaggerMyAppComponent.inject(this).
About the ServiceConnection: you will have to do it the usual way as described in http://developer.android.com/guide/components/bound-services.html
I was dealing with the same concept/problem and like #Ognyan says - you won't have control over creating service.
I think this: How to access service functions from fragment, which is bound to parent activity in Android? might help you.
You may instantiate service in Application/Activity and communicate with it as described in the attached link.
You may also think of putting the interface (which is communicating with service) in base abstract class (BaseActivity or BaseFragment) which Fragment/Activity inherits and then easily reach the interface in any fragment or activity you need.
Hope it solves your issue.

Passing a notification from my object to a service

I'm working in an app for android. I have a Service to manage the background process of streamming. Then I have an object AudioPlayer that manages the MediaPlayer instance and it get called from the service. But the problem I have is with the listener onPrepared, because it's within my AudioPlayer but I need that when it gets trigger send a message from my object AudioPlayer to my Service. Is it that possible?
I can try to put the logic of my MediaPlayer within Service, but I want to keep things decouple.
Yes It is possible.For communication between service and fragment you can use
1.BroadCast Receiver or 2.Messenger
Using messengers refer this link Communication between an Application class and Service in Android
Create a public interface that allows you to communicate between your service and object.
public interface MyListener {
public void receiveNotification();
}
After that, you have to make your object implements that interface.
public class MediaObject implements MyListener {
public void init () {
InitService.getService.addListener(this);
}
#Override
public void receiveNotification () {
//what you want to do
}
//rest of your class
To make it work you should have in your service class sth like:
public class YourService extends Service {
MyListener listener;
public YourService static getService () {
return YourService.this;
}
public void addListener (MyListener listener) {
this.listener = listener;
}
public void methodYouWantToCommunicateWithObject () {
//your code
if (listener!= null) {
listener.receiveNotification();
}
}

Is it possible to invoke a method from abstract class?

I have the Abstract class as following:
AbstractFilePickerFragment.java
public abstract class AbstractFilePickerFragment<T> extends ListFragment
implements LoaderManager.LoaderCallbacks<List<T>>
....
....
public void GoBackToPreviousDirectory() {
currentPath = getParent(currentPath);
refresh();
}
}
OtherActivity.java
private AbstractFilePickerFragment<T> mAbstractFilePickerFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
//THIS LINE SAYS "Cannot instantiate the type AbstractFilePickerFragment"
mAbstractFilePickerFragment = new AbstractFilePickerFragment();
}
public void GoBackToPreviousDir_onClick(MenuItem item) {
mAbstractFilePickerFragment.GoBackToPreviousDirectory();
}
}
Does anyone if it is possible to invoke the GoBackToPreviousDirectory from AbstractFilePickerFragment class???
I know a static method would work, but I can't make a static method for this situation.
Thank you so very much for the help
No. First, you do not invoke methods from classes. You invoke object methods as object is instance of class. Abstract class cannot be instantiated.
In order to call a non-static method, you have to instantiate the class.
Abstract classes cannot be instantiated, by definition. So Answer is NO
If you still need to access the method, You will have to create a class that extends the abstract class and implement all of the methods in the class. Then you can instantiate the extended class within your program and call the method.

How to call an Abstract Class extending Service or a Thread in the Main Activity?

I'm trying to create an abstract class that extends either a service or a thread. This is because i must run this class every second to find out the foreground activity. If its Service i'm using Runnable and make it run every second using Handler. But I'm unable to Start the service or thread from the main activity. I know that abstract classes cant be instantiated but is there any work around that i could use over here?? Please, help.
public abstract class A extends Service Implements Interface {
public void onCreate() {
super.onCreate();
mHandler.postDelayed(runnable, 1 * 1000);
}
protected abstract void getData();
public Runnable runnable = new Runnable() {
public void run() {
//Trying to find Foreground Activities
A start = new B();
start.getData();
mHandler.postDelayed(runnable, 1 * 1000);
}
};
//Inteface methods defined here.
}
Another class:
public class B extends A {
public void getData() {
//Do my stuff
}
}
Now I need to call this A class, so that this abstract method can be executed in which ever class I extend A.
To instantiate an abstract class('s anonymous subclass):
abstract class AbstractClass {}
public class MyActivity extends Activity {
public void onCreate(Bundle i) {
AbstractClass abstractInstance = new AbstractClass(){};
}
}
Though actually you are not supposed to need to do this. What I would suggest is a simple JavaSE concurrency based approach, using ScheduledExecutorService.

Categories

Resources