How to disable home button in Android like lock screen apps do?
Asked Answered
N

6

17

I know this question is asked many times but I found that none of the solution is working. I tried the code given below...

   protected void onPause() {
   super.onPause();
    Intent intent = new Intent(this,LockActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT |Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    }

What it does is that it bring the current activity again to front when android home screen is launched but it takes almost 3-4 seconds to bring activity againt to front when home screen is launched.

I have used some lock screen apps which don't even start the home screen when home button is clicked. I want to achieve something like that.

I have also used onUserLeavesHint method, onKeyDown method and onKeyDispatch method but none of them worked for me.

And please don't answer or comment like it is not possible to disable home button in Android. For such answers or comments I would suggest you to go through some Lock Screen apps on PlayStore. Also I found a working app on github along source code. It was working on my phone and the app used disableKeyguard but when I do the same in my app it doesn't work (disableKeyguard is deprecated but I use @supress warnings("deprecation")).

Nuristan answered 3/4, 2016 at 8:45 Comment(10)
Then the frank answer beside KIOSK mode is you can not disable home button.Aquamarine
I don't mind what you said but I have already mentioned in first line that I have read all the questions related to my question and every post says that you cant disable the home button in android and also in the end I stated that their are many screen locker apps on playstore which are able to disable home button you can try one of them if you have some time.Nuristan
@Nuristan I implore you to check out PiLocker, an open source lockscreen, in particular: github.com/Pi-Developers/Pi-Locker/blob/master/pilocker/src/… which will lead you to look at HomeKeyLocker and eventually github.com/shaobin0604/Android-HomeKey-LockerHitandmiss
Thanks @JasonSec. I have checked it once already(I have gone through every open source projects on github which deals with disabling home key ) and it was not working 100% , but I think I should look at this again as you suggested. Shaobin0604's Home key locker is not a perfect solution as it doesn't deal with virtual home keys.Nuristan
@Nuristan Ah I see, haven't tested a virtual home key with Pilocker but assuming it does work the relevant code is here: github.com/Pi-Developers/Pi-Locker/blob/…Hitandmiss
you do realize that any "work around" you may find it likely to be patched by google in a future update because this is a security issue right?Horseshoes
also specifically what apps are you talking about that lock the home button?Horseshoes
@Horseshoes they are particularly known by the name Lock Screen. You just search "pattern lock screen" on google play you will get many of them.Nuristan
@Nuristan have you found the answer yet ?Patch
I got it done for a dialog in activity: stackoverflow.com/a/52815684Rie
L
7

source - https://github.com/shaobin0604/Android-HomeKey-Locker

//Copy this class
public class HomeKeyLocker {
    private OverlayDialog mOverlayDialog;
    public void lock(Activity activity) {
        if (mOverlayDialog == null) {
            mOverlayDialog = new OverlayDialog(activity);
            mOverlayDialog.show();
        }
    }
    public void unlock() {
        if (mOverlayDialog != null) {
            mOverlayDialog.dismiss();
            mOverlayDialog = null;
        }
    }
    private static class OverlayDialog extends AlertDialog {

        public OverlayDialog(Activity activity) {
            super(activity, R.style.OverlayDialog);
            WindowManager.LayoutParams params = getWindow().getAttributes();
            params.type =  WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
            params.dimAmount = 0.0F; // transparent
            params.width = 0;
            params.height = 0;
            params.gravity = Gravity.BOTTOM;
            getWindow().setAttributes(params);
            getWindow().setFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |  WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 0xffffff);
            setOwnerActivity(activity);
            setCancelable(false);
        }

        public final boolean dispatchTouchEvent(MotionEvent motionevent) {
            return true;
        }

        protected final void onCreate(Bundle bundle) {
            super.onCreate(bundle);
            FrameLayout framelayout = new FrameLayout(getContext());
            framelayout.setBackgroundColor(0);
            setContentView(framelayout);
        }
    }
}

//Paste this in your activity
mHomeKeyLocker = new HomeKeyLocker();
mHomeKeyLocker.lock(this);
Legendary answered 12/4, 2016 at 6:45 Comment(7)
Source: This Github project Always cite your sources. Questions: Can this method be bypassed in a lockscreen situation, using hardware buttons (or opening a notification)? Which would only apply for the select Android phones/versions this hack works on (2.3 - some 4.x versions).Verdie
@Nitin I have already tried this but application is crashing when I use that two line of code(mHomeKeyLocker = new HomeKeyLocker(); mHomeKeyLocker.lock(this);) in my Activity.Nuristan
@Raug : Can you please paste crash log ?Legendary
Nice, the lib works fine!, but I have a question guys, on my case the keyboard also has been blocked... is it the behaviour of the lib?Antin
@freakAR Yes, this library blocks keyboard as well as back button.Pyrrha
getting error of permission Denied while dialog initializationReinsure
@Nitin : Add // getWindow().setType(TYPE_APPLICATION_OVERLAY); // this after initialize WindowManager.LayoutParams OverlayDialog methodFeces
G
3

You can use the shaobin0604 library to do this. It will disable the Back button too. You activity will look like this:


public class MainActivity extends Activity {

HomeKeyLocker homeKeyLocker;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    homeKeyLocker = new HomeKeyLocker();
    homeKeyLocker.lock(this);
}

}

Giesecke answered 11/4, 2016 at 19:20 Comment(3)
Good reference, I didn't know this workaround existed. It would be nice to get a full list of phones this works (and does not work) with, other than the ones shaobin listed. Also wondering if it can be bypassed (which is vital for a lockscreen).Verdie
@Jordan before asking the question here I explored all the question on this website and also all the open source projects on github which are related to my question. I have tried shaobin0604's library also, but application is crashing using that code.Nuristan
On UT880 device will not wark at all.Gallaway
V
3

The sure way of providing a flawless, non-root lockscreen functionality is by combining your "locker" app idea with a launcher app.

A simple change in the manifest will allow your app to register as a homescreen/launcher, which will give your .apk full control of the home button:

<application
    android:launchMode="singleTask"
    android:clearTaskOnLaunch="true"
    android:stateNotNeeded="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="ch.arnab.simplelauncher.HomeScreen"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:excludeFromRecents="true"
        android:screenOrientation="nosensor">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <!-- These 2 intent-filters identify a launcher: -->
            <category android:name="android.intent.category.HOME" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
</application>

Pulled from this tutorial

You will then have two activities, one for your home-screen, one for your lock screen.

You'll have to detect when the screen is turned off/turned on, to show your lock screen activity:

public class MainActivity extends Activity {

    //Create a receiver for screen-on/screen-off
    BroadcastReceiver mybroadcast = new BroadcastReceiver() {   
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                //Show lock-screen
            }
            else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                //Also show lock-screen, to remove flicker/delay when screen on?
            }

        }
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON));
        registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF));
    }
}

Pulled from this answer

FYI: since your "lock screen" will still be considered part of your launcher at this point, apps will be able to launch on top of your lock-screen, which is bad if: the user has access to the notification drawer to click on messages/Tweets etc, but can also be good for: being able to answer incoming calls without unlocking the phone.

Either way, your lock screen activity should override onPause, check whether the user is "authenticated", if he is not, assume that the user opened something and should go back to the lock screen:

@Override
public void onPause() {
    super.onPause();
    if(password!=storedPassword) {
      //Lockscreen activity shouldn't ever be escaped without the right password!
      //Return to launcher without root!
      Intent homeIntent = new Intent(Intent.ACTION_MAIN);
      homeIntent.addCategory(Intent.CATEGORY_HOME);
      homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      startActivity(homeIntent);
    }
}

For better user experience, you should give your user the option to allow a few apps to bypass the lockscreen (such as Spotify), you can include that in the if statement above (ex. if(password!=storedPassword||isForegroundAppSpotify)).

As far as loading apps on your homescreen, you can refer to tutorials on Google for creating your own launcher activity.

Combining launcher+lock-screen is the easiest way to avoid root access. You may find it easier to use root, but you'll limit your customer base.

Hope this helps!

Verdie answered 12/4, 2016 at 1:30 Comment(2)
Thanks @Aaron Gillion. I already tried this one also and it works but problem is that it asks for the launcher during home press which I don't want. Is there any way by which I can programatically set the home launcher for my app.Nuristan
The question is related to home button not home screen lockArvizu
I
2

I have done a lot of research to design a lock screen and finally found a solution. Android disabled the feature to override System bars except the back button. But there is a little work around to make this work:

Understand and implement screen pinning patiently and you will be successful.

You can create an app to control what all applications you want to implement screen pinning in or you can implement screen pinning directly in the same application you want to pin.

I'm going to show you the later implementation in this article:

1. Firstly your app should be the device owner.

You can do it in several ways and the easiest is to execute the command:

adb shell dpm set-device-owner [yourPackageName]/.[MyDeviceAdminReceiver]

Create a receiver(MyDeviceAdminReceiver) that extends DeviceAdminReceiver. You needn't have any code in here. For more info on Device owner implementation refer this link
http://florent-dupont.blogspot.com/2015/02/10-things-to-know-about-device-owner.html

Register the receiver in the AndroidManifest.xml file this way :

<receiver
       android:name=".MyDeviceAdminReceiver"
       android:label="@string/app_name"
       android:permission="android.permission.BIND_DEVICE_ADMIN">
     <meta-data
       android:name="android.app.device_admin"
       android:resource="@xml/device_admin" />

       <intent-filter>
         <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
       </intent-filter>
  </receiver>

2. Your onCreate method should look like this:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_lock_screen);

    ComponentName deviceAdmin = new ComponentName(this, MyDeviceAdminReceiver.class);
    DevicePolicyManager mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);


    if (mDpm.isDeviceOwnerApp(getPackageName())) {
        mDpm.setLockTaskPackages(deviceAdmin, new String[]{getPackageName()});
    }

    if (mDpm.isLockTaskPermitted(this.getPackageName()))
        startLockTask();

3.To unpin the screen and make Navigation Bar functional:

Call the function stopLockTask() at a place in your code where you want to unpin. For example in my application, as soon as I verify that the user has typed the correct passcode, I call this function:

 if (userInput.length() == 4) {

                    if (userInput.equals(passcode)) {
                        userInput = "";
                        etxtPasscodeDisplay.setText("");
                        stopLockTask(); // this is what you need
                        unlockHomeButton(); // A method to show home screen when 
                         passcode is correct
                        finishAffinity(); //kill other activities
                    }

Extra Info which usually is required for lockscreens:

1. If your app is the first thing that comes up after boot:

You need a service(StartAtBootService) and a receiver (BootCompletedReceiver) for this.

2. If you want your app to show up after screen lock and unlock (the power button is pressed to lock and unlock):

Create AEScreenOnOffService that extends service and AEScreenOnOffReceiver that extends BroadcastReceiver to launch your activity when the screen is on.

For a detailed info on everything I mentioned here, refer http://www.sureshjoshi.com/mobile/android-kiosk-mode-without-root/
This is an excellent write up which helped me a lot. Special thanks to the author.

I need at least 10 reputation to post more than two links. As I'm new to stackoverflow I don't have enough reputation so I'm sorry for not being able to share all the links I referred. Will surely update the post once I get access.

Idolum answered 11/5, 2017 at 17:37 Comment(2)
In android studio, this would be a broadcast reciever, right? Also, I get this error when I try to register the receiver in AndroidManifest.xml. Cannot resolve symbol '@xml/device_admin'. Any clue why?Lenora
Yes, myDeviceAdminReceiver extends broadcast receiver. wrt xml error, I think you either wouldn't have had xml folder or device_admin in xml. Create device_admin file in the xml folder and it will work fineIdolum
L
1

Simple answer to your question is you cannot do that.

The solution that you have mention was suggested by me about four years ago [Link].

onUserLeavesHint, onKeyDown and onKeyDispatch will never "disable" hardware keys.

If you really want to "handle" the Home button you will have to make your application as home screen. See this and this.

If you really want to disable your hardware key without making a home screen application, you should root your device and the delete the corresponding device file from the kernel module. (Try at your own risk!)

Ludwigshafen answered 5/4, 2016 at 9:9 Comment(1)
Thanks @Ludwigshafen But none of your points helps me.I think you haven't tried any Lock Screen apps from Google Play otherwise you would not have answered like that , please go through any of them ,it will really help you at some point of time in app development. By the way, I explored some open source projects of Lock Screen apps what they did was like they used an alert dialog with their lock activity making its dimensions 0, color transparent, and setting its gravity to bottom. But I didn't understand the implementation and also don't how will it work? Can you help me a little more?Nuristan
F
-1

What you could do is override the home key function like this:

@Override public boolean onKeyDown(int keyCode, KeyEvent event)
{
    if(keyCode == KeyEvent.KEYCODE_HOME)
    {
        //The Code Want to Perform.
    }
});

Then you should be able to prevent the user to go back to home screen using this button. Hope that works for you.

EDIT: The problem with overriding the home button is it is considered as a security hole by Google, so each time someone finds a way to override it Google patches this "hole".  

Foltz answered 3/4, 2016 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.