android4.0屏蔽状态栏按钮的方法

最近做个ANDROID项目,需要屏蔽平板底层的导航按钮,难点是APP里不仅有自己写的activity,还有调用别的APP(GSF)里的activity里,不是很好实现,先将已有的不完善的解决方法写出来。

所有的实现都在NEXSU 7上测试的,别的机子没测过,不保证有用。

下面介绍的第五种方法是现在最好的解决方法。通过反射机制获取隐藏服务StatusBarService,调用它的disable()方法来屏蔽导航按钮。


一. 自己写的activity屏蔽导航按钮


1. 获取到界面上的一个view

2. 调用API


view.setSystemUiVisibility (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)  

3. 不过Google认为导航按钮太重要了,当你点击屏幕的时候,导航按钮会再次显示出来。

我尝试的监听导航按钮显示事件,当收到显示事件后,再次调用上面的API来隐藏,不过这样显示有问题,屏幕有抖动。

    view.setOnSystemUiVisibilityChangeListener(mSystemUiVisibilityChangeListener);  
    iew.OnSystemUiVisibilityChangeListener mSystemUiVisibilityChangeListener   
             = new View.OnSystemUiVisibilityChangeListener() {  
    @Override  
                  public void onSystemUiVisibilityChange(int vis) {  
                     if ((vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) { //当前状态是显示,隐藏它  
                         view.setSystemUiVisibility (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)  
                      }  
                  }  

4. 由于目前还没有好的解决上面的问题,我就不去掉导航按钮整个一栏,而是仅仅去掉导航按钮

    int INVISBLE = 0x00400000|0x00200000|0x01000000|0x00010000;//这几个整数参数API是不开放的  
    //INVISBLE = View.STATUS_BAR_DISABLE_EXPAND | View.STATUS_BAR_DISABLE_RECENT|View.STATUS_BAR_DISABLE_BACK|View.STATUS_BAR_DISABLE_HOME  
    view.setSystemUiVisibility(INVISBLE);  

运行效果图如下,最下面的导航栏已经没有导航按钮了,只有一个圈圈,无法触控。




二. 调用第三方APK里的activity


由于需要GOOGLE的登录界面,我就调用了GSF提供的登录activity,方法如下:

    Intent localIntent = new Intent(com.google.android.accounts.AccountIntro);  
    localIntent.putExtra("firstRun", true);  
    localIntent.putExtra("allowSkip", true);  
    startActivityForResult(localIntent, requestCode);  

但是当登录界面弹出对话框时,导航按钮都显示出来了,这个是客户接受不了的,要我必须改掉,目前还没有解决掉(已经解决)。问题界面如下


目前想出来的方法是将下面导航栏都去掉,有三种方法,当必须都已经ROOT了。

两种方法屏蔽掉导航按钮,不需要ROOT。


第一种:

修改system/build.prop 添加系统属性 qemu.hw.mainkeys=1,重启。

缺点: 需要重启,所以就没有采用。

第二种:

删除system/app/SystemUI.apk ,这个就是用来显示系统导航栏的APK,但在需要的时候,将APK在放到app目录下,启动服务就行了。

在APK开始运行的时候,将SystemUI.apk移动另一个地方,当APK运行结束的时候,在将SystemUI.apk移回原位,启动SystemUIService服务。

源码如下:

protected static void moveSystemUIapkFile(boolean move) {    
    try {    
        File systemUIapkFile = new File("/system/app/SystemUI.apk");  
        Process p;    
        p = Runtime.getRuntime().exec("su");    
          
        // Attempt to write a file to a root-only    
        DataOutputStream os = new DataOutputStream(p.getOutputStream());    
        os.writeBytes("mount -o remount,rw /dev/block/stl6 /system\n");    
        if (move && systemUIapkFile.exists()) {    
            os.writeBytes("mv /system/app/SystemUI.apk /system/SystemUI.apk\n");    
        }   
        if (!move && !systemUIapkFile.exists()){    
            os.writeBytes("mv /system/SystemUI.apk /system/app/SystemUI.apk\n");  
            os.writeBytes("LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService");  
        }    
        os.writeBytes("mount -o remount,ro /dev/block/stl6 /system\n");    
  
        // Close the terminal    
        os.writeBytes("exit\n");    
        os.flush();    
        p.waitFor();    
    } catch (Exception e) {    
         Log.e(TAG,"moveSystemUIapkFile",e);  
    }    
}

先在开始的时候调用
    moveSystemUIapkFile(true);  
再在结束的时候调用
    moveSystemUIapkFile(false);  


缺点: 当将SystemUI.apk移走时,平板会重启,重启后也就没有了导航栏。需要重启,也没有采用。


第三钟:

将系统进程com.android.systemui杀掉,不过系统会自动将它重启,那就循环的KILL。

实验下来循环时间在300MS左右是最好的,时间长了,屏幕就会由抖动现象。

首先将 killall 和 usleep 这两个命令程序拷贝到asserts目录下,源码和命令程序在这里下载

一部分源码如下:

    package com.dstvmobile.walkatouch.setupwizard;  
      
    import java.io.BufferedInputStream;  
    import java.io.BufferedReader;  
    import java.io.DataOutputStream;  
    import java.io.File;  
    import java.io.FileNotFoundException;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.InputStream;  
    import java.io.InputStreamReader;  
    import java.util.ArrayList;  
    import java.util.Map;  
      
    import android.content.Context;  
    import android.content.Intent;  
    import android.content.res.AssetManager;  
    import android.util.Log;  
      
      
    public enum Device {  
      
        INSTANCE;  
      
        private static String TAG = Device.class.getSimpleName();  
      
        private boolean mHasRootBeenChecked = false;  
        private boolean mIsDeviceRooted = false;  
      
        private boolean mHasBeenInitialized = false;  
        private Context mAppContext = null;  
      
        private boolean mSystembarVisible = true;  
      
        static public void initialize(Context appContext) {  
            if (INSTANCE.mHasBeenInitialized == true) {  
                Log.e(TAG, "Initializing already initialized class " + TAG);  
            }  
            INSTANCE.mHasBeenInitialized = true;  
            INSTANCE.mAppContext = appContext;  
            AddKillAll(appContext, "killall");  
            AddKillAll(appContext, "usleep");  
           // moveSystemUIapkFile(true);        
        }  
      
        public static void AddKillAll(Context appContext, String commandFileName) {  
            File killAllFile = new File("/system/xbin/"+commandFileName);  
            if (!killAllFile.exists()) {  
                AssetManager assetManager = appContext.getAssets();  
                InputStream inputStream = null;  
                String commandFilePath = null;  
                try {  
                    inputStream = assetManager.open(commandFileName);  
                    commandFilePath = appContext.getApplicationContext().getFilesDir()  
                            .getAbsolutePath() + File.separator + commandFileName;  
                    saveToFile(commandFilePath, inputStream);  
                } catch (IOException e) {  
                    Log.e("tag", e.toString());  
                }  
                try {  
                    Process p;  
                    p = Runtime.getRuntime().exec("su");  
                    DataOutputStream os = new DataOutputStream(p.getOutputStream());  
                    os.writeBytes("mount -o remount,rw /dev/block/stl6 /system\n");  
                    os.writeBytes("cd system/xbin\n");  
                    os.writeBytes("cat " + commandFilePath + " > " + commandFileName + "\n");  
                    os.writeBytes("chmod 755 " + commandFileName + "\n");  
                    os.writeBytes("mount -o remount,ro /dev/block/stl6 /system\n");  
                    os.writeBytes("exit\n");  
                    os.flush();  
                    p.waitFor();  
                } catch (Exception e) {  
                    Log.e(TAG, e.toString());  
                }  
            }  
        }  
      
        static public Device getInstance() {  
            INSTANCE.checkInitialized();  
            return INSTANCE;  
        }  
      
        private void checkInitialized() {  
            if (mHasBeenInitialized == false)  
                throw new IllegalStateException("Singleton class " + TAG  
                        + " is not yet initialized");  
        }  
      
        public boolean isRooted() {  
      
            checkInitialized();  
      
      
            if (mHasRootBeenChecked) {  
                return mIsDeviceRooted;  
            }  
      
            try {  
                File file = new File("/system/app/Superuser.apk");  
                if (file.exists()) {  
                    mHasRootBeenChecked = true;  
                    mIsDeviceRooted = true;  
                    return true;  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
      
            try {  
                ArrayList<String> envlist = new ArrayList<String>();  
                Map<String, String> env = System.getenv();  
                for (String envName : env.keySet()) {  
                    envlist.add(envName + "=" + env.get(envName));  
                }  
                String[] envp = (String[]) envlist.toArray(new String[0]);  
                Process proc = Runtime.getRuntime()  
                        .exec(new String[] { "which", "su" }, envp);  
                BufferedReader in = new BufferedReader(new InputStreamReader(  
                        proc.getInputStream()));  
                if (in.readLine() != null) {  
                    mHasRootBeenChecked = true;  
                    mIsDeviceRooted = true;  
                    return true;  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
      
            mHasRootBeenChecked = true;  
            mIsDeviceRooted = false;  
            return false;  
      
        }  
      
        public enum AndroidVersion {  
            HC, ICS, JB, UNKNOWN  
        };  
      
        public AndroidVersion getAndroidVersion() {  
            checkInitialized();  
            int sdk = android.os.Build.VERSION.SDK_INT;  
            if (11 <= sdk && sdk <= 13) {  
                return AndroidVersion.HC;  
            } else if (14 <= sdk && sdk <= 15) {  
                return AndroidVersion.ICS;  
            } else if (16 == sdk) {  
                return AndroidVersion.JB;  
            } else {  
                return AndroidVersion.UNKNOWN;  
            }  
        }  
          
        protected static void moveSystemUIapkFile(boolean move) {    
            try {    
                File systemUIapkFile = new File("/system/app/SystemUI.apk");  
                Process p;    
                p = Runtime.getRuntime().exec("su");    
                  
                // Attempt to write a file to a root-only    
                DataOutputStream os = new DataOutputStream(p.getOutputStream());    
                os.writeBytes("mount -o remount,rw /dev/block/stl6 /system\n");    
                if (move && systemUIapkFile.exists()) {    
                    os.writeBytes("cp /system/app/SystemUI.apk /system/SystemUI.apk\n");    
                }   
                if (!move && !systemUIapkFile.exists()){    
                    os.writeBytes("cp /system/SystemUI.apk /system/app/SystemUI.apk\n");    
                }    
                os.writeBytes("mount -o remount,ro /dev/block/stl6 /system\n");    
                  
                // Close the terminal    
                os.writeBytes("exit\n");    
                os.flush();    
                p.waitFor();   
                if(!move){  
                      
                }  
            } catch (Exception e) {    
                 Log.e(TAG,"moveSystemUIapkFile",e);  
            }    
        }  
        public void showSystembar(boolean makeVisible) {  
            checkInitialized();  
            try {  
                ArrayList<String> envlist = new ArrayList<String>();  
                Map<String, String> env = System.getenv();  
                for (String envName : env.keySet()) {  
                    envlist.add(envName + "=" + env.get(envName));  
                }  
                String[] envp = (String[]) envlist.toArray(new String[0]);  
                if (makeVisible) {  
                    String command;  
                    Device dev = Device.getInstance();  
                    if (dev.getAndroidVersion() == AndroidVersion.HC) {  
                        command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";  
                    } else {  
                        command = ""  
                                +"rm /sdcard/hidebar-lock\n"  
                                + "sleep 5\n"  
                                + "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";  
                    }  
                    Runtime.getRuntime().exec(new String[] { "su", "-c", command }, envp);  
                    mSystembarVisible = true;  
                } else {  
                    String command;  
                    Device dev = Device.getInstance();  
                    if (dev.getAndroidVersion() == AndroidVersion.HC) {  
                        command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib service call activity 79 s16 com.android.systemui";  
                    } else {  
                        command = "touch /sdcard/hidebar-lock\n"  
                                + "while [ -f /sdcard/hidebar-lock ]\n"  
                                + "do\n"  
                                + "killall com.android.systemui\n"                                                     
                                + "usleep 300000\n"  
                                + "done\n"  
                                + "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";  
                    }  
                    Runtime.getRuntime().exec(new String[] { "su", "-c", command }, envp);  
                    mSystembarVisible = false;  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
      
        public boolean isSystembarVisible() {  
            checkInitialized();  
            return mSystembarVisible;  
        }  
      
        public void sendBackEvent() {  
            try {  
                ArrayList<String> envlist = new ArrayList<String>();  
                Map<String, String> env = System.getenv();  
                for (String envName : env.keySet()) {  
                    envlist.add(envName + "=" + env.get(envName));  
                }  
                String[] envp = (String[]) envlist.toArray(new String[0]);  
                Runtime.getRuntime().exec(  
                        new String[] { "su", "-c",  
                                "LD_LIBRARY_PATH=/vendor/lib:/system/lib input keyevent 4" },  
                        envp);  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void saveToFile(String filePath, InputStream in){  
            FileOutputStream fos = null;  
            BufferedInputStream bis = null;  
            int BUFFER_SIZE = 1024;  
            byte[] buf = new byte[BUFFER_SIZE];  
            int size = 0;  
            bis = new BufferedInputStream(in);  
            try {  
                fos = new FileOutputStream(filePath);  
                while ((size = bis.read(buf)) != -1)  
                    fos.write(buf, 0, size);  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            } finally {  
                try {  
                    if (fos != null) {  
                        fos.close();  
                    }  
                    if (bis != null) {  
                        bis.close();  
                    }  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
      
    }  

在需要隐藏时候调度

Device.initialize(this);  
Device.getInstance().showSystembar(false);
在需要去消隐藏的时候调用

Device.getInstance().showSystembar(true); 

效果界面:



目前在研究如何屏蔽第三方APK界面的三个导航按钮,而不是去掉整个导航栏。

刚发现了屏蔽三个导航按钮的方案。

第四种:

使用StatusBarManager类,不过这个类是隐藏的,必须在源码下编译,使用SDK编译的肯定是找不到类。

    import android.app.StatusBarManager;  
    mStatusBarManager = (StatusBarManager)this.getSystemService(Context.STATUS_BAR_SERVICE);  

在需要隐藏的时候调用:


mStatusBarManager.disable(StatusBarManager.DISABLE_HOME  
                    |StatusBarManager.DISABLE_BACK|StatusBarManager.DISABLE_RECENT);
在需要显示的时候调度:



mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);  

第五种:

对于第四种方法,SDK编译下也可以实现,使用JAVA的反射机制,获取隐藏接口。

这个方法在我的另一篇文章里已经介绍过了,来实现关机功能 http://blog.csdn.net/kobeyxyx/article/details/9112641

    private void statusBarDisable(boolean disable) {    
          
         try {  
           int DISABLE_NAVIGATION  = 0x00200000 | 0x00400000 | 0x01000000;  
             //int DISABLE_NAVIGATION =  View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_BACK | View.STATUS_BAR_DISABLE_RECENT;  
           int DISABLE_NONE = 0x00000000;  
           //获得ServiceManager类  
           Class<?> ServiceManager = Class  
              .forName("android.os.ServiceManager");  
             
           //获得ServiceManager的getService方法  
           Method getService = ServiceManager.getMethod("getService", java.lang.String.class);  
             
           //调用getService获取RemoteService  
           Object oRemoteService = getService.invoke(null,"statusbar");  
             
           //获得IStatusBarService.Stub类  
           Class<?> cStub = Class  
              .forName("com.android.internal.statusbar.IStatusBarService$Stub");  
           //获得asInterface方法  
           Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);  
           //调用asInterface方法获取IStatusBarService对象  
           Object oIStatusBarService = asInterface.invoke(null, oRemoteService);  
           //获得disable()方法  
           Method disableMethod = oIStatusBarService.getClass().getMethod("disable",int.class,IBinder.class,String.class);  
           //调用disable()方法  
           if(disable){  
              disableMethod.invoke(oIStatusBarService,DISABLE_NAVIGATION,new Binder(),this.getPackageName());     
           }else{  
              disableMethod.invoke(oIStatusBarService,DISABLE_NONE,new Binder(),this.getPackageName());     
           }             
         }catch (Exception e) {            
           Log.e(TAG, e.toString(), e);           
         }  
      }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值