17

我知道这个问题被问了很多次,但我发现没有一个解决方案有效。我尝试了下面给出的代码...

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

它的作用是在启动 android 主屏幕时将当前活动再次置于最前面,但在启动主屏幕时将活动再次置于最前面需要将近 3-4 秒。

我使用了一些锁屏应用程序,当单击主页按钮时,它们甚至不启动主屏幕。我想实现这样的目标。

我还使用了 onUserLeavesHint 方法、onKeyDown 方法和 onKeyDispatch 方法,但它们都不适合我。

并且请不要回答或评论无法在 Android 中禁用主页按钮。对于此类答案或评论,我建议您浏览 PlayStore 上的一些锁屏应用程序。我还沿着源代码在 github 上找到了一个工作应用程序。它在我的手机上运行,​​并且应用程序使用了 disableKeyguard,但是当我在我的应用程序中执行相同操作时它不起作用(disableKeyguard 已弃用,但我使用@supress 警告(“弃用”))。

4

6 回答 6

7

来源 - 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);
于 2016-04-12T06:45:46.930 回答
3

您可以使用shaobin0604 库来执行此操作。它也会禁用后退按钮。您的活动将如下所示:


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

}

于 2016-04-11T19:20:34.227 回答
3

提供完美无瑕的非根锁屏功能的可靠方法是将您的“储物柜”应用创意与启动器应用相结合。

清单中的一个简单更改将允许您的应用注册为主屏幕/启动器,这将使您的 .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>

本教程中提取

然后,您将有两项活动,一项用于主屏幕,一项用于锁定屏幕。

您必须检测屏幕何时关闭/打开,以显示您的锁定屏幕活动:

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

这个答案中提取

仅供参考:由于此时您的“锁定屏幕”仍将被视为您的启动器的一部分,因此应用程序将能够在您的锁定屏幕上启动,这很糟糕:用户可以访问通知抽屉以单击消息/推文等,但也可以用于:无需解锁手机即可接听来电。

无论哪种方式,您的锁屏活动都应该覆盖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);
    }
}

为了获得更好的用户体验,您应该为您的用户提供允许一些应用程序绕过锁屏的选项(例如 Spotify),您可以将其包含在上面的if声明中(例如if(password!=storedPassword||isForegroundAppSpotify))。

至于在主屏幕上加载应用程序,您可以参考Google 上的教程来创建自己的启动器活动。

结合启动器+锁屏是避免root访问的最简单方法。您可能会发现使用 root 更容易,但您会限制您的客户群。

希望这可以帮助!

于 2016-04-12T01:30:57.433 回答
2

我做了很多研究来设计锁屏,终于找到了解决方案。Android 禁用了覆盖除后退按钮之外的系统栏的功能。但是有一些工作可以使这项工作:

耐心地理解和实施屏幕固定,你就会成功。

您可以创建一个应用程序来控制要实现屏幕固定的所有应用程序,或者您可以直接在要固定的同一应用程序中实现屏幕固定。

我将在本文中向您展示稍后的实现:

1.首先您的应用程序应该是设备所有者。

您可以通过多种方式执行此操作,最简单的是执行命令:

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

创建一个扩展 DeviceAdminReceiver 的接收器(MyDeviceAdminReceiver)。你不需要在这里有任何代码。有关设备所有者实施的更多信息,请参阅此链接
http://florent-dupont.blogspot.com/2015/02/10-things-to-know-about-device-owner.html

以这种方式在 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. 您的 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.取消固定屏幕并使导航栏功能

在代码中要取消固定的位置调用函数 stopLockTask() 。例如在我的应用程序中,一旦我验证用户输入了正确的密码,我就会调用这个函数:

 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
                    }

锁屏通常需要的额外信息:

1.如果您的应用程序是启动后出现的第一件事

为此,您需要一个服务(StartAtBootService)和一个接收器(BootCompletedReceiver)。

2.如果您希望您的应用在屏幕锁定和解锁后显示 (按电源按钮锁定和解锁):

创建扩展服务的 AEScreenOnOffService 和扩展BroadcastReceiver的 AEScreenOnOffReceiver以在屏幕打开时启动您的活动。

有关我在这里提到的所有内容的详细信息,请参阅http://www.sureshjoshi.com/mobile/android-kiosk-mode-without-root/
这是一篇出色的文章,对我帮助很大。特别感谢作者。

我需要至少 10 个声望才能发布两个以上的链接。由于我是 stackoverflow 的新手,我没有足够的声誉,所以很抱歉无法分享我提到的所有链接。一旦我获得访问权限,肯定会更新帖子。

于 2017-05-11T17:37:07.533 回答
1

对您的问题的简单回答是您不能那样做。

你提到的解决方案是我大约四年前提出的[Link]

onUserLeavesHint、onKeyDown 和 onKeyDispatch 永远不会“禁用”硬件键。

如果您真的想“处理”主页按钮,则必须将您的应用程序设置为主屏幕。看到这个这个

如果您真的想在不创建主屏幕应用程序的情况下禁用硬件密钥,您应该根您的设备并从内核模块中删除相应的设备文件。(尝试自担风险!)

于 2016-04-05T09:09:58.537 回答
-1

您可以做的是像这样覆盖主页键功能:

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

然后您应该能够阻止用户使用此按钮返回主屏幕。希望这对你有用。

编辑:覆盖主页按钮的问题是它被谷歌认为是一个安全漏洞,所以每次有人找到一种方法来覆盖它时,谷歌都会修补这个“漏洞”。  

于 2016-04-03T14:37:31.540 回答