2

So I'm trying to do what many people have tried before: create an app that does not respond to the Home button. I've looked at many of the similar questions posted here on SO, but none of worked the way I wanted them to.

One thing I tried was making my app essentially another launcher. (Note: a little amount of user input is required to make it work.)

From my application's Manifest:

<category android:name="android.intent.category.DEFAULT" />       
<category android:name="android.intent.category.HOME" />

I also disabled the back button and made the launch mode "singleInstance."

I think Toddler Lock did something similar, but my implementation does not behave exactly the same way. Using my implementation, my app exists as the default home launcher indefinitely including after the application has been exited. Is there any way to declare the same behavior in a place other than the Application Manifest where it can be turned on temporarily or and turned off when the app is exited?

Car Home also does a similar thing and actually does it better than Toddler Lock. I'm not sure how it does it (maybe it has more permissions since it is a native app), but it manages to do the same thing without requiring the user to accept the alternate Launcher or choose the app as the default Launcher. Anyone have any idea on how it does it?

drewse
  • 115
  • 1
  • 8
  • To add, I realize there should be a way for me to add an Intent Filter within a class rather than within the AndroidManifest.xml. As described here: http://stackoverflow.com/questions/2162182/android-is-it-possible-to-disable-the-click-of-home-button/2650010#2650010 Could someone please describe how to set up the flag _synic_ mentioned in the comment above? Thanks! – drewse Jun 11 '11 at 23:22
  • synic's method requires that you set your app up as broadcast receiver and have your intent filter filter for the HOME category. See the doc on Broadcast Receivers http://developer.android.com/reference/android/content/BroadcastReceiver.html – Noel Jun 12 '11 at 00:13

2 Answers2

2

hackbod is essentially correct. I have gotten much of the desired behavior by

  1. Make a "capture home key" activity as described in the question. This is not the main activity of the program.
  2. In the manifest, disable it.
  3. In the app, enable the "capture home key" activity when you want the home capture to happen, and disable it when you want to exit.

The only question is what the capture home key activity should actually do. In my case, I needed it to just go to the start of the app... so it manufactures a CATEGORY_HOME intent, tests that it resolves correctly, and if so forwards on to the app. If it doesn't resolve correctly, it notifies the user, waits for the user to be ready, and then uses that intent. This way if the user chooses your app but doesn't make it default, he'll get prompted again.

Robert
  • 164
  • 1
  • 12
  • I've done steps 1, 2, 3 and they worked perfectly, so thanks for the help. But I'm unsure about how to implement the details of the Capture Home Key activity. I've given it a CATEGORY_HOME intent in the intent filter of the Manifest, but don't know how to test if it resolves correctly. Do I need to set up an Intent Filter to do that? And when I do set up an intent in the Capture Home Key activity that sends the user to the main activity, it only works the first time they press the Home button. The times after that they are brought to the Capture Home Key Activity display. – drewse Jun 13 '11 at 20:52
  • For the manifest: I made the filter have action MAIN, categories HOME and DEFAULT. It's possible DEFAULT is not necessary. – Robert Jun 16 '11 at 20:21
  • To make a home intent, I create it with ACTION_MAIN and add the category CATEGORY_HOME. Starting that activity behaves as if they had pushed the home key. To test it, I use `getPackageManager().resolveActivity(testIntent, PackageManager.MATCH_DEFAULT_ONLY)` Pull the activity info out of the resolution, and see if its name equals the class you're using to capture home. If it does, they've successfully set the default. If not, they haven't. – Robert Jun 16 '11 at 20:25
  • As for getting it to behave right each time, instead of just the first, make sure you test for default in onResume. Someone may correct me on this aspect, though, I haven't been doing this terribly long. – Robert Jun 16 '11 at 20:27
  • Thanks Robert for your continuous help! I really appreciate the time you have put into this. However, I am unsure of how to get the class name from the `ActivityInfo` object. When I simply call `.toString()` on it, I am given the info '_ActivityInfo{... com.android.internal.app.ResolverActivity}_' – drewse Jun 16 '11 at 23:37
  • Ok, ignore the previous comment (I got it to work with `.name` reference). My last issue is with regards to what happens when the user chooses Launcher and selects it as the Default after I bring up the chooser. Then, whenever the user opens my app again, the Intent launching `ACTION_MAIN` with `CATEGORY_HOME` is called and the app is immediately exited as Launcher is still the default. Did you find any way around that? – drewse Jun 17 '11 at 00:40
  • Sorry about the delay, it's been a while since I looked at the code. If you declare CAPTURE_PACKAGE to be the package which is capturing the home key, and CAPTURE_CLASS to be the class, you can `getPackageManager().setComponentEnabledSetting(new ComponentName(CAPTURE_PACKAGE, CAPTURE_CLASS), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);` to enable/disable capturing the home key. – Robert Nov 04 '11 at 21:00
  • Ah, I think I misunderstood. So, when you start the app, you use resolveActivity on a test intent to detect if it's default. If it is not default, tell the user. Then trigger the test intent and if you have changed the intents which can handle CATEGORY_HOME, they should get the choice again. At least, I think that's how it works. You may have to disable and enable the component which captures the home key so the OS picks up that there's a new option and asks. – Robert Nov 04 '11 at 21:11
1

To disable this after the user has enabled your app as the home app, disable that activity with PackageManager.setComponentEnabledSetting(). Note this implies that the activity that is overriding home should not be the main activity of your app, or else upon disabling it the user won't be able to return to your app.

CarHome is very different -- when Android is in a different UI mode (in a car for car mode or on a desk dock for desk mode), then a different Intent will be launched when the user presses home so that they can have a different "home" in that environment. If you are not writing a car mode home screen, you should not be using this.

hackbod
  • 90,665
  • 16
  • 140
  • 154