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

后端 未结 6 1731
后悔当初
后悔当初 2020-12-24 14:43

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() {
            


        
相关标签:
6条回答
  • 2020-12-24 14:53

    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.

    0 讨论(0)
  • 2020-12-24 14:56

    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!)

    0 讨论(0)
  • 2020-12-24 14:58

    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);
    }
    

    }

    0 讨论(0)
  • 2020-12-24 15:00

    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);
    
    0 讨论(0)
  • 2020-12-24 15:03

    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!

    0 讨论(0)
  • 2020-12-24 15:12

    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".  

    0 讨论(0)
提交回复
热议问题