Syncope.T-*
Published 2019. 3. 25. 12:29
[Android] Host 파일 수정 BackEnd/Android
728x90

본인은 문서를 읽는 타입이 아니므로 무조건 부딪히면서 감으로 해결하는 방식으로 코딩을 하기 때문에

어디 사이트에선 이렇답디다. 이게 더 좋답디다. 시시비비 가리는걸 별로 좋아하진 않습니다.

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

profile

Syncope.T-*

@Syncope

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...