【问题标题】:How to disable virtual home button in any activity?如何在任何活动中禁用虚拟主页按钮?
【发布时间】:2016-01-21 08:45:18
【问题描述】:

我需要在我的应用程序的任何活动中禁用 3 个虚拟按钮。我以某种方式禁用了后退按钮和多任务按钮,但我无法使用主页按钮。

我在 stackoverflow 上尝试了onAttachedToWindow() 风格的答案,但它们对我不起作用。

我不想为整个应用禁用主页按钮,我只想为单个活动窗口禁用它。感谢您的帮助!

【问题讨论】:

    标签: android virtual android-homebutton


    【解决方案1】:

    注意:如果你想部署它,我强烈建议你不要在你的应用程序中这样做。这只是为了展示我们如何做到这一点。

    由于 Android 4 没有有效的方法来禁用主页按钮。它几乎不需要 hack。我认为您需要的是应用程序中的 KIOSK 模式。一般来说,这个想法是检测新应用程序何时处于前台并立即重新启动您的Activity。流程如下..

    首先创建一个名为 KioskService 的类,扩展 Service 并添加以下 sn-p :

     public class KioskService extends Service {
    
      private static final long INTERVAL = TimeUnit.SECONDS.toMillis(2); // periodic interval to check in seconds -> 2 seconds
      private static final String TAG = KioskService.class.getSimpleName();
      private static final String PREF_KIOSK_MODE = "pref_kiosk_mode";
    
      private Thread t = null;
      private Context ctx = null;
      private boolean running = false;
    
      @Override
      public void onDestroy() {
        Log.i(TAG, "Stopping service 'KioskService'");
        running =false;
        super.onDestroy();
      }
    
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Starting service 'KioskService'");
        running = true;
        ctx = this;
    
        // start a thread that periodically checks if your app is in the foreground
        t = new Thread(new Runnable() {
          @Override
          public void run() {
            do {
              handleKioskMode();
              try {
                Thread.sleep(INTERVAL);
              } catch (InterruptedException e) {
                Log.i(TAG, "Thread interrupted: 'KioskService'");
              }
            }while(running);
            stopSelf();
          }
        });
    
        t.start();
        return Service.START_NOT_STICKY;
      }
    
      private void handleKioskMode() {
        // is Kiosk Mode active? 
          if(isKioskModeActive()) {
            // is App in background?
          if(isInBackground()) {
            restoreApp(); // restore!
          }
        }
      }
    
      private boolean isInBackground() {
        ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
    
        List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
        ComponentName componentInfo = taskInfo.get(0).topActivity;
        return (!ctx.getApplicationContext().getPackageName().equals(componentInfo.getPackageName()));
      }
    
      private void restoreApp() {
        // Restart activity
        Intent i = new Intent(ctx, MyActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        ctx.startActivity(i);
      }
    
      public boolean isKioskModeActive(final Context context) {
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        return sp.getBoolean(PREF_KIOSK_MODE, false);
      }
    
      @Override
      public IBinder onBind(Intent intent) {
        return null;
      }
    }
    

    在您的 AppContext 类中添加以下方法以通过应用程序上下文创建来启动 service

    @Override
    public void onCreate() {
      super.onCreate();
      instance = this;
      registerKioskModeScreenOffReceiver();
      startKioskService();  // add this
    }
    
    private void startKioskService() { // ... and this method
      startService(new Intent(this, KioskService.class));
    }
    

    AppContext类看起来像这样

      public class AppContext extends Application {
    
      private AppContext instance;
      private PowerManager.WakeLock wakeLock;
      private OnScreenOffReceiver onScreenOffReceiver;
    
    
      @Override
      public void onCreate() {
        super.onCreate();
        instance = this;
        registerKioskModeScreenOffReceiver();
      }
    
      private void registerKioskModeScreenOffReceiver() {
        // register screen off receiver
        final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        onScreenOffReceiver = new OnScreenOffReceiver();
        registerReceiver(onScreenOffReceiver, filter);
      }
    
      public PowerManager.WakeLock getWakeLock() {
        if(wakeLock == null) {
          // lazy loading: first call, create wakeLock via PowerManager.
          PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
          wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "wakeup");
        }
        return wakeLock;
      }
    }
    

    将服务声明和检索前台进程的权限添加到清单中:

    <service android:name=".KioskService" android:exported="false"/>
    <uses-permission android:name="android.permission.GET_TASKS"/>
    //Added permission Edit 1
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

    我在一个站点上看到了这一切,但忘记了链接,我所拥有的只是内容和代码,所以我将所有内容都发布为答案。得到链接后,我将与您分享。

    【讨论】:

    • 你在哪里定义 registerKioskModeScreenOffReceiver() ?
    • @kagkar 我找到了你正在搜索的链接。你需要那个链接还是你离开了?
    • @ShreeKrishna 能给个链接吗?
    • @ArsenSench 可能是it is
    【解决方案2】:

    如果我没记错的话,您想禁用主页按钮,或者您可以说将您的活动保持在每个活动屏幕的前面。

    为此,我建议您使用窗口管理器屏幕启动您的活动窗口。当您使用窗口管理器开始您的活动时,您的主页按钮活动将进入后台。这意味着您的活动无法通过按主页按钮关闭。

    如此简单,将您的活动用作窗口管理器活动。许多锁屏应用也采用这种方式

    抱歉代码。我无法发布代码,因为我离开了 android 编程,现在我正在处理动画,所以你可能需要为此付出努力。

    但是您可以使用窗口管理器活动来击败主页按钮和所有其他系统按钮。

    我的锁屏应用项目不完整。您必须进行一些更改,并应删除不需要的 java 类文件和适配器文件。

    我还开发了新的锁,屏幕上有 81 个图像。两个解锁手机你必须设置你选择的图像。

    您可以从here下载我未完成的项目。

    我更新链接并知道它的工作原理。

    【讨论】:

    • 我更新了我的链接,现在可以从那里下载文件了。 @RamyAly
    • 我更新了我的链接,现在可以从那里下载文件了。 @kord
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多