본인은 문서를 읽는 타입이 아니므로 무조건 부딪히면서 감으로 해결하는 방식으로 코딩을 하기 때문에
어디 사이트에선 이렇답디다. 이게 더 좋답디다. 시시비비 가리는걸 별로 좋아하진 않습니다.
Process를 이용한 안드로이드 내부 adb shell command를 사용하는데 있어 system내 파일을 쓰기가 불가능한 점을 가능케 하는 코드입니다.
6시간 넘게 삽질하여 화가나서 쓰는 글이니. 양해부탁드립니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public static void writeHost(List<WebsiteItem> hosts, Context activity) { File sdcard = Environment.getRootDirectory(); final File hostFile = new File(sdcard, "/etc/hosts"); final File file = new File(Environment.getExternalStorageDirectory(), "hosts"); FileOutputStream fos = null; try { fos = new FileOutputStream(file); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos)); for (WebsiteItem h : hosts) { bw.write("127.0.0.1 " + h.url.trim()); bw.newLine(); } bw.close(); } catch (IOException e) { e.printStackTrace(); } Log.i("파일 경로", "cat " + file.getAbsolutePath() + " > " + hostFile.getAbsolutePath()); try { ShellManager.cat("cat " + file.getAbsolutePath() + " > " + hostFile.getAbsolutePath()); } catch (Exception e) { e.printStackTrace(); } } | cs |
Host파일에 Block할 url을 위와같이 작성.
가칭 Hosts파일을 만들어 ExternalStorage에 임의 경로에 놓고, 원하는 Host명을 작성한다.
그 후 cat 명령어를 통해 system내부로 이동한다. (루팅된 기기만 가능)
중요한 부분은 명령인수가 mv, cp가 아닌 cat을 이용한다.
cp는 busybox에서만 지원하고 mv는 먹히지 않았다.
# cat 덮어씌울파일 > 덮어질곳
ShellManager 클래스 내부의 cat 메소드를 보자면 아래와 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public static void cat(String cmd){ StringBuilder text = new StringBuilder(); Process process = null; try { process = Runtime.getRuntime().exec("su"); DataOutputStream out = new DataOutputStream(process.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); out.writeBytes("mount -o rw,remount /system" + "\n"); out.writeBytes(cmd + "\n"); out.writeBytes("exit\n"); out.flush(); String line; while((line = in.readLine()) != null){ text.append(line + System.lineSeparator()); } } catch (IOException e) { e.printStackTrace(); } Log.i("프로세스 cat", text.toString()); } | cs |
su를 필수적으로 사용하여야한다. 루팅이 아닌 기기에서는 sh를 사용해도 의미가 없었다.
반드시 DataOutPutStream으로 writeBytes 메소드를 사용 해야한다. 일반 타 파생 OutputStream 클래스의 write는 먹히지 않았다.
mount -o re, remount /system 하여 리마운트가 필요한데, 이는 기기마다 다른 부분이니
API가 낮은 기기에서는 http://1004lucifer.blogspot.com/2015/05/android-read-only-file-system.html 이 사이트를 참고하길 바란다.
-추신-
기타 ADB 명령어만 실행을 원한다면 예) pm list, am force-stop package 등등
process를 exec만 하여도 실행이 된다. su를 적용할 필요도 없다.
아래 메서드를 참고하면 되겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public static String cmd(String cmd){ StringBuilder text = new StringBuilder(); try { Process process = Runtime.getRuntime().exec(cmd); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); process.waitFor(); String line; while((line = in.readLine()) != null){ text.append(line + System.lineSeparator()); } } catch (Exception e) { e.printStackTrace(); } Log.i("프로세스 cmd", text.toString()); return text.toString(); } | cs |