1

In my app I have a child class that extends a support library class called SearchFragment in the leanback support library. I need to extend this class but unfortunately the onPause() of the parent (SearchFragment) class has a method I cannot use.

Every time I leave the activity the parent class runs the onPause() which calls the method I don't want.

Is there a way I can extend the SearchFragment class but not allow it to run its own onPause()?

Here is the onPause() method in the parent class that I cannot alter.

android.support.v17.leanback.app.SearchFragment

@Override
public void onPause() {
    releaseRecognizer(); //Need to stop this from calling
    super.onPause();
}

private void releaseRecognizer() {
    if (null != mSpeechRecognizer) {
        mSearchBar.setSpeechRecognizer(null);
        mSpeechRecognizer.destroy();
        mSpeechRecognizer = null;
    }
}

Also, the reason I am doing this is because this is an Android TV > Fire TV port. Fire TV does not have a speechRecognizer.

Elltz
  • 10,730
  • 4
  • 31
  • 59
Sealer_05
  • 5,346
  • 8
  • 35
  • 53
  • You can override the method `onPause()` in your `fragment` and not call `super.onPause()` in it. the method will not be propagated to parent class. – Shaishav Aug 17 '16 at 03:02

5 Answers5

0

onPause is a part of activity life cycle and cannot be ignored but you can do some hacks to do it. It requires you to modify the behavior of your releaseRecognizer() method.

The code can be changed as follows:

boolean isReleased;

public void releaseRecognizer() {
   if(isReleased) {
      return;
   }
   ...
   //your code go here
   ...
   isReleased = true;
}

//Somewhere else where you acquire the recognizer again you just set it to false:

public void acquireRecognizer(){

   ...
   isReleased = false
}

This way you make sure releaseRecognizer doesn't run the code twice.

Pooya
  • 6,083
  • 3
  • 23
  • 43
  • What if the releaseRecognizer class is private? – Sealer_05 Aug 17 '16 at 03:12
  • The SearchFragment class contains the onPause and releaseRecognizer method and cannot be modified. It is a locked google library. I can only extend it. – Sealer_05 Aug 17 '16 at 03:15
  • I suggest to modify the releaseRecognizer behavior. by the way, by looking at your updated code, what is the problem with multiple calling to releaseRecognizer()? – Pooya Aug 17 '16 at 03:18
  • FireTV doesnt have support for speech recognition in app like android tv so it fails – Sealer_05 Aug 17 '16 at 03:21
  • I'm not expert in FireTV but I think you can find this in the onCreate method of the activity and set a global parameter which can be used throughout the program to prevent the irrelevant code from running – Pooya Aug 17 '16 at 03:23
  • That would be nice. My app was based off an earlier version of the leanback sample. Worked great until I needed to get it running on FireOS... https://github.com/googlesamples/androidtv-Leanback – Sealer_05 Aug 17 '16 at 03:26
0

Since, onPause() in one of the methods of the parent SearchFragment class with public accessibility, you can simply override it in you sub-classes and not call super.onPause(). This will not propagate the method to the parent class and hence infamous releaseRecognizer() will not be called.

However, you need to take care that you implement your business logic that is properly tied up with other lifecycle methods of the SearchFragment so that system resources are not abused. So, you need modify overridden code as per your your use-case logic so that you eventually call onPause() after all.

Shaishav
  • 5,282
  • 2
  • 22
  • 41
  • Of course I am now getting.... SuperNotCalledException: Fragment SearchFragment{86aa5eb #0 id=0x7f10009c} did not call through to super.onPause() – Sealer_05 Aug 17 '16 at 03:45
  • I get why google has tied this up but it is also Very frustrating amazon does not allow this. They have a mic button but choose to not allow the dev to use it – Sealer_05 Aug 17 '16 at 03:47
  • This may be a dumb question but i cant extend and extended class to avoid this right? – Sealer_05 Aug 17 '16 at 04:09
  • @osiris355 Yeah, won't work that way. However, if the library is open source, we can try to modify the source as one of the more extreme measures. – Shaishav Aug 17 '16 at 04:14
0

Use Proguard assumenosideeffects option to annihilate the call to releaseRecognizer() method inside SearchFragment. This will require you to compile your code with Proguard enabled, but since the code in question is invoked in somewhat specific scenario, you may get away with using Proguard in release builds only.

Note, that you have to enable optimizations (the dontoptimize option must not be set), because stripping calls to methods via assumenosideeffects is technically an "optimization".

Make sure to use suggestions in this answer to limit Proguard actions to specific classes you want to "optimize" (in your case — to android.support.v17.leanback.app.SearchFragment).


This is the only way to cope with your problem without modifying the source code of SearchFragment. On second thought, you may be better off simply copying necessary classes to your project or in the worst case — plugging entire leanback support library as Gradle submodule and modyfying necessary methods directly (there is a good chance, that Fire TV has other issues with it besides this one).

user1643723
  • 4,109
  • 1
  • 24
  • 48
  • What a pain. Unfortunately as soon as a copy one class I have to copy another, and another.... – Sealer_05 Aug 17 '16 at 05:37
  • 1
    @osiris355 I understand your pain, but sometimes it is impossible to eat a cake and have it… On other hand you always have an options to follow the recommendation in [that answer](https://stackoverflow.com/a/30934640/1643723) and follow up with intercepting `NullPointerException`s all over the place. You have to decide whether you want short-term "ease" (catch exceptions, use reflective hacks), maintainability (fork the leanback library) or illusion of either (basically any other option, including the Proguard one, outlined in this answer). – user1643723 Aug 17 '16 at 05:59
-1

As mention in the android documents it's good practice to release system resources in onpause().
I think you should have aquire it again in onResume() .. As

@Override
public void onResume() {
super.onResume();
acquireRecognizer();
}

@Override
public void onPause() {
super.onPause();
releaseRecognizer();
}

Or perhaps you should release the recognizer in onStop() or in onDestroy(). In this way it will keep the recognizer untill the activity is alive.

@Override
protected void onStop() {
super.onStop();
releaseRecognizer();
}
isamirkhaan1
  • 749
  • 7
  • 19
  • As mentioned in my question I cannot touch the recognizer. If I do ANYTHING with the recognizer it fails. Amazon FireTVs do not have a speech recognizer. – Sealer_05 Aug 17 '16 at 03:44
  • oops ! you aren't able to modify `onPause()` and `releaseRecognizer()`. I guess you should then disable the recognizer, – isamirkhaan1 Aug 17 '16 at 04:10
  • Easier said than done. I dont see a global way of even doing this. – Sealer_05 Aug 17 '16 at 04:46
  • In app search http://stackoverflow.com/questions/30930871/making-androidtv-app-workable-on-firetv – isamirkhaan1 Aug 17 '16 at 05:03
  • Good find but I am getting nowhere attempting that. It says there is a field not found exception no matter where i use that block of code. – Sealer_05 Aug 17 '16 at 05:38
-1

In my view, you can override SearchFragment onPause as suggested here in other answers but by removing super.onPause() you will face some problems. So one safe solution can be to write your own SearchFragment class (copy all code from that class and crate your own class) Now in this class remove the method you do not want to call within onPause() method. By this way you are not removing super call, so this approach will be safe.

Ramit
  • 416
  • 3
  • 8
  • Unfortunately its not that simple since the SearchFragment class calls methods from the leanback support library and google throws that error wherever mRowsFragment.getVerticalGridView() in my copied fragment – Sealer_05 Aug 17 '16 at 04:44
  • Basically that method is final in the BaseRowFragment so I cannot call it from my project. – Sealer_05 Aug 17 '16 at 04:48