Android O 는 Runtime. getRuntime (). exec 에서 생 성 된 프로 세 스 번호 PID 를 가 져 오고 adb 셸 의 Ctrl + C 동작 을 모 의 합 니 다.

4658 단어
배경: 회사 의 핸드 메 이 드 장치 로 mic 두 개 를 만 들 었 습 니 다.공장 테스트 apk 를 쓰 는 동료 가 테스트 코드 를 쓸 때 상부 의 AudioMedia 나 MediaRecorder 관련 api 로 하지 않 았 습 니 다.Runtime. getRuntime (). exec (...) 로 tinymix, tinycap 명령 을 실행 하여 테스트 합 니 다.
녹음 과정: 먼저 tinymix 로 관련 흐름 을 열 고 tinycap 로 녹음 을 시작 합 니 다.그리고 tiny mix 는 관련 흐름 을 닫 으 면 tiny cap 은 자동 으로 멈 춥 니 다.
Bug: tiny mix 가 관련 흐름 을 닫 으 면 tiny cap 이 응답 에서 자동 으로 멈 추 는 데 오래 걸 립 니 다. 10s 이상 입 니 다.이것 은 분명히 받 아들 이기 어렵다.
    
해결 방향: adb 셸 후 tiny mix 를 실행 하여 관련 흐름 을 열 고 tiny cap 에서 녹음 을 시작 한 다음 에 ctrl + c 로 녹음 을 끝 냅 니 다. 녹음 파일 은 ok 이 고 재생 할 수 있 습 니 다.그러면 우리 의 해결 방향 은 tinycap 에 대응 하 는 프로 세 스 (Runtime. getRuntime (). exec 가 이 명령 을 수행 할 때 발생 하 는 프로 세 스) 를 미리 중단 하 는 것 입 니 다.
시도: 이 프로 세 스 를 직접 가 져 옵 니 다. Process = Runtime. getRuntime (). exec, p. destroy (). 실 패 했 습 니 다. tiny cap 이 멈 추 었 지만 생 성 된 wav 오디 오 파일 은 재생 되 지 않 습 니 다.
이것 은 ctrl + c 이 조작 이 실제 적 으로 강 살 프로 세 스 가 아니 라 는 것 을 설명 한다.인터넷 조회 에서 ctrl + c 가 실제 SIGINT 라 는 신 호 를 보 낸 것 을 알 게 되 었 다.그럼 이 신 호 를 시 뮬 레이 션 해 보 겠 습 니 다. kill 명령 으로 가능 합 니 다.kill-2 pid.주의 - 2, SIGINT 에 적합 합 니 다. kill 명령 의 관련 매개 변 수 는 인터넷 으로 조회 할 수 있 습 니 다.
그럼 첫 번 째 단 계 는 tiny cap 의 pid 를 먼저 받 아야 합 니 다.
몇 가지 방법 을 시도 했다.
1. 반사, stackoverflow 에서 찾 은        fail
public static int getPid(Process p) {
    int pid = -1;

    try {
        Field f = p.getClass().getDeclaredField("pid");
        f.setAccessible(true);
        pid = f.getInt(p);
        f.setAccessible(false);
    } catch (Throwable e) {
        pid = -1;
    }
    return pid;
}

링크:https://stackoverflow.com/questions/13055794/android-runtime-getruntime-exec-get-process-id
필드 는 pid 이지 만 실제 테스트 에서 얻 은 것 은 ppid, 절망 입 니 다.java. lang. Process 라 는 종 류 를 위로 쫓 고 ProcessImpl 을 쫓 아 UNIXProcess 로 갑 니 다. pid 라 는 유용 해 보 이 는 필드 를 제외 하고 pid 를 얻 을 수 있 는 필드 가 없습니다.그래서 실패
2. Running TaskInfo 로        fail
실측 기 계 는 8.0 에서 시스템 ui, launcher, 현재 응용 프로그램 만 받 을 수 있 습 니 다.그래서 실패
3. Running AppProcessInfo 로        fail
Android Manifest 가 권한 을 밝 히 기만 하면 android. permission. REALGET_TASKS, 그리고 시스템 응용 프로그램 으로 모든 응용 프로그램의 pid 를 얻 을 수 있 습 니 다.
하지만 주의 하 세 요. 응용 입 니 다.모두 com. android. settings 와 유사 한 프로 세 스 입 니 다. 그러나 tinycap 같은 Runtime. getRuntime (). exec 에서 생 성 된 프로 세 스 는 이 열 에 없습니다.그래서 실패
4. ps | grep tinycap 시 뮬 레이 션 으로 pid 가 져 오기        success
public String getTinyCapPID() {

   java.lang.Process psProcess = null;
   try {
	   psProcess = Runtime.getRuntime().exec("sh");
   } catch (IOException e) {
	   e.printStackTrace();
   }
   DataOutputStream out = new DataOutputStream(psProcess.getOutputStream());
   InputStream is = psProcess.getInputStream();

   try {
	   out.writeBytes("ps | grep 'tinycap' | cut -c 10-15
"); out.writeBytes("ps
"); out.flush(); } catch (IOException e) { e.printStackTrace(); } try { out.writeBytes("exit
"); out.flush(); psProcess.waitFor(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } String re=""; try { if (is.read() != 0) { byte firstByte = (byte) is.read(); int available = is.available(); byte[] characters = new byte[available + 1]; characters[0] = firstByte; is.read(characters, 1, available); re = new String(characters); } } catch (IOException e) { e.printStackTrace(); } return re; }

실측 이 가능 하 다.success
STEP 2: kill - 2 pid
Process p=Runtime.getRuntime().exec("kill -2 "+ getTinyCapPID());
여기 뒤에 다른 것 을 실행 하려 면, 예 를 들 어 tinyplay.tiny cap 이 죽 었 는 지 확인 하기 위해 서 tiny play 를 실행 합 니 다.먼저 p. wait For () 해 보 세 요.p. waiFor () 가 kill - 2 pid 라 는 명령 을 실행 하 더 라 도 tiny cap 프로 세 스 는 작은 확률 로 바로 kill 에 떨 어 지지 않 습 니 다 (kill - 2 뒤에 마무리 작업 도 했 습 니 다).
그렇게
Process p2=Runtime.getRuntime().exec("tinycap /data/Main.wav");
p2. waitFor () 후 tinyplay 를 실행 합 니 다.
큰 성 과 를 거두다.
PS: Process p = Runtime. getRuntime (). exec (xxx) 로 명령 을 수행 하고 보험 의 측면 에서 p. waitFor () 를 사용 해 야 합 니 다.개인 실천 의 교훈 은 반드시 p. wait For () 로 명령 이 실 행 된 후에 (명령 이 실 행 된 후에 이 명령 을 수행 하 는 프로 세 스 가 없어 진 후에 야 이 코드 가 끝 났 습 니 다. 그렇지 않 으 면 계속 막 혔 습 니 다).다음 단계 에 관련 된 일 을 하 다.
p. waiFor () 를 사용 하지 않 으 면 기본 시스템 은 명령 을 수행 하 는 데 아주 작은 시간 을 줄 것 입 니 다.작은 확률 로 명령 이 제대로 실행 되 지 않 는 경우 가 많다.꼭 나타 나 지 않 는 bug 가 나타 납 니 다.예 를 들 어 필자 위의 Runtime. getRuntime (). exec ("ps | grep 'tiny cap' | cut - c 10 - 15") 는 뒤의 p. waitFor () 가 없 으 면 실제 운행 과정 에서 작은 확률 로 정확 한 pid 를 얻 지 못 해 tiny cap 이 있 는 프로 세 스 를 죽 이지 않 고 더 나 아가 tinyplay 에서 재생 할 수 없습니다.

좋은 웹페이지 즐겨찾기