libsuperuser 프로필

5544 단어
배경
    일 한 지 이렇게 오래 되 었 는데, 나 는 내 옆 에 있 는 프로그래머 가 하나의 폴 더 를 방문 하여 su 의 셸, chmod 777 somefolder 를 시작 하고, 어떤 폴 더 의 읽 기와 쓰기 권한 을 개방 하 는 것 을 자주 보 았 다.기능 은 이 루어 졌 습 니 다. 하지만 생각해 보 세 요. 루트 작업 을 수행 할 때 슈퍼 user 와 같은 방어 소프트웨어 가 대화 상자 경 고 를 꺼 냅 니 다. 사용자 가 유 어 앱 을 신뢰 한 후에 핸드폰 에 있 는 폴 더 의 권한 을 777 로 변경 한 다음 에 다른 앱 이 접근 하지 말 아야 할 파일 에 장애 없 이 접근 할 수 있 을 때 죄책 감 을 느끼 지 않 습 니까?짧 은 시간 안에 특정한 파일 의 권한 을 변경 하고 방문 이 끝 난 후에 바 꾸 면 받 아들 일 수 있 을 지 모 르 지만 전체 폴 더 777 은 너무 과장 되 었 다.
사실 배경 에서 셸 을 시작 하고 su 를 실행 한 다음 이 셸 에 명령 을 입력 하면 됩 니 다.게다가 이미 만들어 진 라 이브 러 리 도 있 고 간단 하고 알 기 쉬 운 demo 도 있다.libsuperuser( http://su.chainfire.eu/) 바로 이런 창고 입 니 다.
사용 방식
방식 1: 일반적인 배경 작업
          List Shell.SH.run(String command)
List Shell.SH.run(List commands)
List Shell.SH.run(String[] commands)
방식 2: 루트 형 조작
List Shell.SU.run(String command)
List Shell.SU.run(List commands)
List Shell.SU.run(String[] commands)
방식 3:
        Shell. Interactive. addCommand 시리즈 함수, 리 셋 함수 OnCommandResultListener 와 OnCommandLine Listener 지원
    private void sendRootCommand() {
        rootSession.addCommand(new String[] { "id", "date", "ls -l /" }, 0,
                new Shell.OnCommandResultListener() {
            public void onCommandResult(int commandCode, int exitCode, List<String> output) {
                if (exitCode < 0) {
                    reportError("Error executing commands: exitCode " + exitCode);
                } else {
                    updateResultStatus(true, output);
                    appendLineToOutput("----------");
                    appendLineToOutput("ls -l /");
                }
            }
        });

 사용 시 보조 스 레 드 에서 호출 해 야 합 니 다. 예 를 들 어 AsyncTask, 예 를 들 어 IntentService 등 입 니 다.
기능 실현 의 핵심 은 아래 코드 세그먼트 에 있 습 니 다.
public static List<String> run(String shell, String[] commands, String[] environment,
            boolean wantSTDERR) {
            ...
            // setup our process, retrieve STDIN stream, and STDOUT/STDERR
            // gobblers
            Process process = Runtime.getRuntime().exec(shell, environment);
            DataOutputStream STDIN = new DataOutputStream(process.getOutputStream());
            StreamGobbler STDOUT = new StreamGobbler(shellUpper + "-", process.getInputStream(),
                    res);
            StreamGobbler STDERR = new StreamGobbler(shellUpper + "*", process.getErrorStream(),
                    wantSTDERR ? res : null);
            // start gobbling and write our commands to the shell
            // STDOUT STDERR       ,         
            STDOUT.start();
            STDERR.start();
            try {
                for (String write : commands) {
                    Debug.logCommand(String.format("[%s+] %s", shellUpper, write));
                    STDIN.write((write + "
").getBytes("UTF-8"));                     STDIN.flush();                 }                 STDIN.write("exit
".getBytes("UTF-8"));                 STDIN.flush();             } catch (IOException e) {                 if (e.getMessage().contains("EPIPE")) {                     // method most horrid to catch broken pipe, in which case we                     // do nothing. the command is not a shell, the shell closed                     // STDIN, the script already contained the exit command, etc.                     // these cases we want the output instead of returning null                 } else {                     // other issues we don't know how to handle, leads to                     // returning null                     throw e;                 }             }             // wait for our process to finish, while we gobble away in the             // background             process.waitFor();             // make sure our threads are done gobbling, our streams are closed,             // and the process is destroyed - while the latter two shouldn't be             // needed in theory, and may even produce warnings, in "normal" Java             // they are required for guaranteed cleanup of resources, so lets be             // safe and do this on Android as well             try {                 STDIN.close();             } catch (IOException e) {                 // might be closed already             }             STDOUT.join();             STDERR.join();             process.destroy();             // in case of su, 255 usually indicates access denied             if (SU.isSU(shell) && (process.exitValue() == 255)) {                 res = null;             }         } catch (IOException e) {             // shell probably not found             res = null;         } catch (InterruptedException e) {             // this should really be re-thrown             res = null;         }         Debug.logCommand(String.format("[%s%%] END", shell.toUpperCase(Locale.ENGLISH)));         return res;     }

결어
    나 도 한 동료 가 응용 시장 app 을 할 때 '침묵 설치' 기능 을 실현 해 야 한 다 는 것 을 만난 적 이 있다. apk 다운로드 가 끝나 면 배경 에서 조용히 app 을 설치 하 는 것 이다. 즉, su 의 셸 에서 pm install 과 다른 보조 기능 을 실행 한 다음 에 한참 을 다 듬 어서 야 나 에 게 왜 DeviceA 에서 통 하고 DeviceB 에서 안 되 는 지 물 었 다.나 는 그 에 게 성숙 한 실현 방식 이 있다 고 말 했다. 나중에 해 보 자. OK.성숙 한 실현 방식 이 있 으 면 직접 가 져 와 서 사용 하거나 이 코드 를 읽 고 핵심 코드 를 스스로 추출 하 세 요.

좋은 웹페이지 즐겨찾기