如何在Android 4.0 ICS中禁用StatusBar | SystemBar | 状态栏 【完美版】

这个世界上总是有很多牛人,我们不得不对此表示无限钦佩。

 

在我上次博文发出后,我始终对此耿耿于怀,因为之前提供的解决禁用Statusbar问题在ICS中依然存在问题,即不能自动隐现,需要重启。因此在搜索几个月之后发现,依然难有进展。 

就在前几天,我发现在Acer A510 这个平板上之前的方法已经完全行不通,于是重新搜索整个互联网。茫茫大海,亏我之前做的功课甚多,在Hide Bar (http://ppareit.github.com/HideBar/ 
)这个小工具上得到启发,很巧妙的解决了这个问题。

 

这个Hide Bar也是一国外小团队做的禁用statusbar工具,六月份之前,仍然没有给出适用ICS版本的更新。于是在这次重新搜索中,我欣然发现它偷偷支持了,等不及下载,看源码,一会功夫我就将这些代码抠到项目中。

 

说说原理吧,原理很简单,我之前也知道过一部分,他是将com.android.systemui名称的进程杀掉,不过这个杀不同,它是每隔一秒杀一回。之前我也试过kill这个进程,但因为每次kill后隔几秒就会重启,可能因为内核保护吧,当时就没再继续。而Hide Bar跑了个循环,隔一秒杀一下,这下内核想保护也没用了。

 

当然我手上平板众多,也发现一些小问题,比如一秒有点长,有的板子在这一秒间隔重启了com.android.systemui进程,界面显示出加载的画面,但是不一会又被杀了,界面抖了一下又没了那个进程,因为这样显得有点不稳定,我减小了kill的间隔;还有就是因为调用杀进程的命令是killall,在有的板子上却不支持这个命令,于是我又将其他板子上/system/xbin/下的killall和usleep拿了过来,增加了这个代码的适用性。

 

话不多说了,上代码。

  1 package transight.tablet.android.util;
  2 
  3 import java.io.BufferedInputStream;
  4 import java.io.BufferedReader;
  5 import java.io.DataOutputStream;
  6 import java.io.File;
  7 import java.io.FileNotFoundException;
  8 import java.io.FileOutputStream;
  9 import java.io.IOException;
 10 import java.io.InputStream;
 11 import java.io.InputStreamReader;
 12 import java.util.ArrayList;
 13 import java.util.Map;
 14 
 15 import android.content.Context;
 16 import android.content.res.AssetManager;
 17 import android.util.Log;
 18 
 19 /**
 20  * Class with global information about the specific device.
 21  */
 22 public enum Device {
 23 
 24     INSTANCE;
 25 
 26     private static String TAG = Device.class.getSimpleName();
 27 
 28     private boolean mHasRootBeenChecked = false;
 29     private boolean mIsDeviceRooted = false;
 30 
 31     private boolean mHasBeenInitialized = false;
 32     private Context mAppContext = null;
 33 
 34     // flag if the systembar is currently visible, assume at start this is true
 35     private boolean mSystembarVisible = true;
 36 
 37     static public void initialize(Context appContext) {
 38         if (INSTANCE.mHasBeenInitialized == true) {
 39             Log.e(TAG, "Initializing already initialized class " + TAG);
 40             // throw new IllegalStateException(
 41             // "Trying to initialize already initialized class " + TAG);
 42         }
 43         INSTANCE.mHasBeenInitialized = true;
 44         INSTANCE.mAppContext = appContext;
 45         AddKillAll(appContext, "killall");
 46         AddKillAll(appContext, "usleep");
 47     }
 48 
 49     private static void AddKillAll(Context appContext, String commandFileName) {
 50         File killAllFile = new File("/system/xbin/"+commandFileName);
 51         if (!killAllFile.exists()) {
 52             AssetManager assetManager = appContext.getAssets();
 53             InputStream inputStream = null;
 54             String commandFilePath = null;
 55             try {
 56                 inputStream = assetManager.open(commandFileName);
 57                 commandFilePath = appContext.getApplicationContext().getFilesDir()
 58                         .getAbsolutePath() + File.separator + commandFileName;
 59                 saveToFile(commandFilePath, inputStream);
 60             } catch (IOException e) {
 61                 Log.e("tag", e.toString());
 62             }
 63             try {
 64                 Process p;
 65                 p = Runtime.getRuntime().exec("su");
 66 
 67                 // Attempt to write a file to a root-only
 68                 DataOutputStream os = new DataOutputStream(p.getOutputStream());
 69                 os.writeBytes("cd system/xbin\n");
 70                 os.writeBytes("cat " + commandFilePath + " > " + commandFileName + "\n");
 71                 os.writeBytes("chmod 755 " + commandFileName + "\n");
 72 
 73                 // Close the terminal
 74                 os.writeBytes("exit\n");
 75                 os.flush();
 76                 p.waitFor();
 77             } catch (Exception e) {
 78                 Log.e(TAG, e.toString());
 79             }
 80         }
 81     }
 82 
 83     static public Device getInstance() {
 84         INSTANCE.checkInitialized();
 85         return INSTANCE;
 86     }
 87 
 88     private void checkInitialized() {
 89         if (mHasBeenInitialized == false)
 90             throw new IllegalStateException("Singleton class " + TAG
 91                     + " is not yet initialized");
 92     }
 93 
 94     public boolean isRooted() {
 95 
 96         checkInitialized();
 97 
 98         Log.v(TAG, "isRooted called");
 99 
100         if (mHasRootBeenChecked) {
101             Log.v(TAG, "Result for isRooted is cached: " + mIsDeviceRooted);
102             return mIsDeviceRooted;
103         }
104 
105         // first try
106         Log.v(TAG, "Checking if device is rooted by checking if Superuser is available");
107         try {
108             File file = new File("/system/app/Superuser.apk");
109             if (file.exists()) {
110                 Log.v(TAG, "Device seems rooted");
111                 mHasRootBeenChecked = true;
112                 mIsDeviceRooted = true;
113                 return true;
114             }
115         } catch (Exception e) {
116             e.printStackTrace();
117         }
118 
119         // second try
120         Log.v(TAG, "Checking if device is rooted by checking if su is available");
121         try {
122             // get the existing environment
123             ArrayList<String> envlist = new ArrayList<String>();
124             Map<String, String> env = System.getenv();
125             for (String envName : env.keySet()) {
126                 envlist.add(envName + "=" + env.get(envName));
127             }
128             String[] envp = (String[]) envlist.toArray(new String[0]);
129             // execute which su
130             Process proc = Runtime.getRuntime()
131                     .exec(new String[] { "which", "su" }, envp);
132             BufferedReader in = new BufferedReader(new InputStreamReader(
133                     proc.getInputStream()));
134             // if we receive location, we are on a rooted device
135             // TODO: can break if the executable is on the device, but non working
136             if (in.readLine() != null) {
137                 Log.v(TAG, "Device seems rooted");
138                 mHasRootBeenChecked = true;
139                 mIsDeviceRooted = true;
140                 return true;
141             }
142         } catch (Exception e) {
143             e.printStackTrace();
144         }
145 
146         mHasRootBeenChecked = true;
147         mIsDeviceRooted = false;
148         return false;
149 
150     }
151 
152     public enum AndroidVersion {
153         HC, ICS, JB, UNKNOWN
154     };
155 
156     public AndroidVersion getAndroidVersion() {
157         checkInitialized();
158         Log.v(TAG, "getAndroidVersion called");
159         int sdk = android.os.Build.VERSION.SDK_INT;
160         if (11 <= sdk && sdk <= 13) {
161             Log.v(TAG, "We are running on HoneyComb");
162             return AndroidVersion.HC;
163         } else if (14 <= sdk && sdk <= 15) {
164             Log.v(TAG, "We are running on IceCreamSandwich");
165             return AndroidVersion.ICS;
166         } else if (16 == sdk) {
167             Log.v(TAG, "We are running on JellyBean");
168             return AndroidVersion.JB;
169         } else {
170             Log.v(TAG, "We don't know what we are running on");
171             return AndroidVersion.UNKNOWN;
172         }
173     }
174 
175     public void showSystembar(boolean makeVisible) {
176         checkInitialized();
177         try {
178             // get the existing environment
179             ArrayList<String> envlist = new ArrayList<String>();
180             Map<String, String> env = System.getenv();
181             for (String envName : env.keySet()) {
182                 envlist.add(envName + "=" + env.get(envName));
183             }
184             String[] envp = (String[]) envlist.toArray(new String[0]);
185             // depending on makeVisible, show or hide the bar
186             if (makeVisible) {
187                 Log.v(TAG, "showBar will show systembar");
188                 // execute in correct environment
189                 String command;
190                 Device dev = Device.getInstance();
191                 if (dev.getAndroidVersion() == AndroidVersion.HC) {
192                     command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";
193                 } else {
194                     command = "rm /sdcard/hidebar-lock\n"
195                             + "sleep 5\n"
196                             + "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";
197                 }
198                 Runtime.getRuntime().exec(new String[] { "su", "-c", command }, envp);
199                 // no proc.waitFor();
200                 // we just shown the bar, set flag to visible
201                 mSystembarVisible = true;
202             } else {
203                 Log.v(TAG, "showBar will hide the systembar");
204                 // execute in correct environment
205                 String command;
206                 Device dev = Device.getInstance();
207                 if (dev.getAndroidVersion() == AndroidVersion.HC) {
208                     command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib service call activity 79 s16 com.android.systemui";
209                 } else {
210                     command = "touch /sdcard/hidebar-lock\n"
211                             + "while [ -f /sdcard/hidebar-lock ]\n"
212                             + "do\n"
213                             + "killall com.android.systemui\n"
214 //                            + "sleep 1\n"
215                             + "usleep 600000\n"
216                             + "done\n"
217                             + "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";
218                 }
219                 Runtime.getRuntime().exec(new String[] { "su", "-c", command }, envp);
220                 // no proc.waitFor();
221                 // we just hide the bar, set flag to not visible
222                 mSystembarVisible = false;
223             }
224         } catch (Exception e) {
225             e.printStackTrace();
226         }
227     }
228 
229     /**
230      * @return true is the systembar is visible or false when it is not visible
231      */
232     public boolean isSystembarVisible() {
233         checkInitialized();
234         // TODO: this might be improved by using 'ps ...' to see if the systemui process
235         // is running and by checking the /sdcard/hidebar-lock file
236         return mSystembarVisible;
237     }
238 
239     public void sendBackEvent() {
240         Log.v(TAG, "sendBackEvent");
241         try {
242             // get the existing environment
243             ArrayList<String> envlist = new ArrayList<String>();
244             Map<String, String> env = System.getenv();
245             for (String envName : env.keySet()) {
246                 envlist.add(envName + "=" + env.get(envName));
247             }
248             String[] envp = (String[]) envlist.toArray(new String[0]);
249             Runtime.getRuntime().exec(
250                     new String[] { "su", "-c",
251                             "LD_LIBRARY_PATH=/vendor/lib:/system/lib input keyevent 4" },
252                     envp);
253         } catch (Exception e) {
254             e.printStackTrace();
255         }
256     }
257     
258     public static void saveToFile(String filePath, InputStream in){
259         FileOutputStream fos = null;
260         BufferedInputStream bis = null;
261         int BUFFER_SIZE = 1024;
262         byte[] buf = new byte[BUFFER_SIZE];
263         int size = 0;
264         bis = new BufferedInputStream(in);
265         try {
266             fos = new FileOutputStream(filePath);
267             while ((size = bis.read(buf)) != -1)
268                 fos.write(buf, 0, size);
269         } catch (FileNotFoundException e) {
270             e.printStackTrace();
271         } catch (IOException e) {
272             e.printStackTrace();
273         } finally {
274             try {
275                 if (fos != null) {
276                     fos.close();
277                 }
278                 if (bis != null) {
279                     bis.close();
280                 }
281             } catch (IOException e) {
282                 e.printStackTrace();
283             }
284         }
285     }
286 

287 } 

 

将killall和usleep放到assets文件夹下,执行以下代码即可。

1 Device.initialize(getApplicationContext());
2 Device device = Device.getInstance();
3 device.showSystembar(false);

 

posted @ 2012-08-29 15:18  席步川  阅读(3847)  评论(4编辑  收藏  举报