简体   繁体   English

如何在锁定屏幕应用程序中禁用Android中的主页按钮呢?

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

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. 它的作用是当Android主屏幕启动时它将当前活动再次带到前面,但是当主屏幕启动时,将活动再次带到前面需要将近3-4秒。

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. 我还使用了onUserLeavesHint方法,onKeyDown方法和onKeyDispatch方法,但它们都没有为我工作。

And please don't answer or comment like it is not possible to disable home button in Android. 请不要回答或评论,因为无法在Android中禁用主页按钮。 For such answers or comments I would suggest you to go through some Lock Screen apps on PlayStore. 对于这样的答案或评论,我建议你在PlayStore上浏览一些锁屏应用程序。 Also I found a working app on github along source code. 我还在github上找到了一个有源代码的工作应用程序。 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")). 它正在我的手机上工作,应用程序使用disableKeyguard,但是当我在我的应用程序中执行相同操作时它不起作用(不支持disableKeyguard,但我使用@supress警告(“弃用”))。

source - https://github.com/shaobin0604/Android-HomeKey-Locker 来源 - 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);

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: 清单中的简单更改将允许您的应用注册为主屏幕/启动器,这将使您的.apk 完全控制主页按钮:

<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: 无论哪种方式,您的锁定屏幕活动应覆盖onPause ,检查用户是否“已通过身份验证”,如果不是,则假定用户打开了某些内容并应返回锁定屏幕:

@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) ). 为了获得更好的用户体验,您应该让用户选择允许一些应用程序绕过锁屏(例如Spotify),您可以在上面的if语句中包含它(例如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. 至于在主屏幕上加载应用,您可以参考Google上的教程来创建自己的启动器活动。

Combining launcher+lock-screen is the easiest way to avoid root access. 组合启动器+锁定屏幕是避免root访问的最简单方法。 You may find it easier to use root, but you'll limit your customer base. 您可能会发现使用root更容易,但您将限制您的客户群。

Hope this helps! 希望这可以帮助!

You can use the shaobin0604 library to do this. 您可以使用shaobin0604库来执行此操作。 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);
}

}

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. Android禁用该功能以覆盖除后退按钮以外的系统栏。 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. 1.首先,您的应用应该是设备所有者。

You can do it in several ways and the easiest is to execute the command: 您可以通过多种方式完成此操作,最简单的方法是执行命令:

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

Create a receiver(MyDeviceAdminReceiver) that extends DeviceAdminReceiver. 创建一个扩展DeviceAdminReceiver的接收器(MyDeviceAdminReceiver)。 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 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 : 以这种方式在AndroidManifest.xml文件中注册接收器:

<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: 2.你的onCreate方法应如下所示:

@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 : 3.取消固定屏幕并使导航栏功能

Call the function stopLockTask() at a place in your code where you want to unpin. 在代码中要取消固定的位置调用函数stopLockTask() 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 : 1.如果你的应用程序是启动后出现的第一件事

You need a service(StartAtBootService) and a receiver (BootCompletedReceiver) for this. 您需要一个服务(StartAtBootService)和一个接收器(BootCompletedReceiver)。

2. If you want your app to show up after screen lock and unlock (the power button is pressed to lock and unlock): 2.如果您希望在屏幕锁定和解锁后按下应用程序 (按下电源按钮以锁定和解锁):

Create AEScreenOnOffService that extends service and AEScreenOnOffReceiver that extends BroadcastReceiver to launch your activity when the screen is on. 创建扩展服务的 AEScreenOnOffService和扩展BroadcastReceiver的 AEScreenOnOffReceiver,以在屏幕打开时启动您的活动。

For a detailed info on everything I mentioned here, refer http://www.sureshjoshi.com/mobile/android-kiosk-mode-without-root/ 有关我在此提及的所有内容的详细信息,请参阅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. 我需要至少10个声望才能发布超过两个链接。 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. 由于我是stackoverflow的新手,因此我没有足够的声誉,所以我很抱歉无法分享我提到的所有链接。 Will surely update the post once I get access. 一旦我获得访问权限,肯定会更新帖子。

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] . 大约四年前,我提出了你提到的解决方案[Link]

onUserLeavesHint, onKeyDown and onKeyDispatch will never "disable" hardware keys. onUserLeavesHint,onKeyDown和onKeyDispatch永远不会“禁用”硬件密钥。

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. 如果您确实要在不创建主屏幕应用程序的情况下禁用硬件密钥,则应该根据设备进行root操作并从内核模块中删除相应的设备文件。 (Try at your own risk!) (请自担风险!)

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". 编辑:覆盖主页按钮的问题是谷歌认为它是一个安全漏洞,所以每当有人找到覆盖它的方法时谷歌会修补这个“漏洞”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM