Android 침묵 설치 와 스마트 설치 의 실현 방법

프로필
최근 안 드 로 이 드 의 침묵 설치 와 스마트 설 치 를 연구 해 블 로그 에 기록 했다.침묵 설치 란 소리 없 이 배경 에 apk 를 설치 하 는 것 으로 인터페이스 알림 이 없습니다.스마트 설 치 는 설치 인터페이스 가 있 지만 모두 자동 이 므 로 사용자 가 클릭 할 필요 가 없다.
우선 두 가 지 를 강조 합 니 다:침묵 설 치 는 루트 권한 이 있어 야 합 니 다.스마트 설 치 는 사용자 가 수 동 으로 무장 애 서 비 스 를 시작 해 야 합 니 다.
2 원리
침묵 설치,마 운 트 해제 의 원 리 는 pm install 명령 을 이용 하여 apk 를 설치 하 는 것 입 니 다.pm uninstall 은 apk 를 마 운 트 해제 하 는 것 입 니 다.스마트 설 치 는 안 드 로 이 드 시스템 이 제공 하 는 무장 애 서비스 Accessibility Service 를 이용 하여 사용자 의 클릭 을 모 의 하여 자동 으로 설치 하 는 것 입 니 다.
3pm 명령 안내
(1) pm install
pm install 명령 의 용법 및 매개 변 수 는 다음 과 같 습 니 다.

<code class="hljs haml">pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH
Options:
 -l: install the package with FORWARD_LOCK.
 -r: reinstall an exisiting app, keeping its data.
 -t: allow test .apks to be installed.
 -i: specify the installer package name.
 -s: install package on sdcard.
 -f: install package on internal flash.</code>
(2) pm uninstall
pm uninstall 명령 의 용법 및 매개 변 수 는 다음 과 같 습 니 다.

<code class="hljs livecodeserver">pm uninstall [-k] PACKAGE
Options:
 -k: keep the data and cache directories around.</code>
위의 영 어 는 매우 간단 해서 설명 하지 않 는 다.
4 침묵 설치
프 리 젠 테 이 션 을 편리 하 게 하기 위해 서,나 는 아이 치 이의 설치 패 키 지 를 test.apk 라 고 이름 을 바 꾸 어 sdcard 에 놓 았 다.당신 은 스스로 아이 치 이 홈 페이지 에 가서 다운로드 할 수도 있 고,스스로 apk 를 찾 아 sdcard 에 올 릴 수도 있 습 니 다.그러나 apk 의 가방 이름 을 알 아야 합 니 다.나중에 마 운 트 해제 할 때 사용 해 야 합 니 다.
선행 코드:

<code class="hljs cs">//    
 private void installSlient() {
 String cmd = "pm install -r /mnt/sdcard/test.apk";
 Process process = null;
 DataOutputStream os = null;
 BufferedReader successResult = null;
 BufferedReader errorResult = null;
 StringBuilder successMsg = null;
 StringBuilder errorMsg = null;
 try {
  //      root  
  process = Runtime.getRuntime().exec("su");
  os = new DataOutputStream(process.getOutputStream());
  os.write(cmd.getBytes());
  os.writeBytes("
"); os.writeBytes("exit
"); os.flush(); // process.waitFor(); // successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (process != null) { process.destroy(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (Exception e) { e.printStackTrace(); } } // tvTest.setText(" :" + successMsg.toString() + "
" + " : " + errorMsg.toString()); }</code>
이 코드 는 프로그램 에서 pm 명령 을 실행 하 는 것 입 니 다.adb 에서 실행pm install -r /mnt/sdcard/test.apk 하 는 것 과 효과 가 같 습 니 다.관건 적 인 코드 는Runtime.getRuntime().exec(“su”)입 니 다.이 코드 는 루트 권한 을 요구 하기 때문에 핸드폰 은 루트 가 필요 합 니 다.루트 가 싫 으 면 시 뮬 레이 터 를 사용 하 셔 도 됩 니 다. Runtime.getRuntime().exec(“su”) 를 통 해 프로 세 스 대상 을 가 져 오 면 명령 을 쓸 수 있 습 니 다.명령 을 쓸 때마다 줄 을 바 꾸 고''를 쓰 면 됩 니 다.마지막 으로 exit 를 쓰 고 명령 이 실 행 된 환경 을 떠 납 니 다.
5.조용히 마 운 트 해제
침묵 마 운 트 해제 와 침묵 설치 가 같 습 니 다.명령 만 다 릅 니 다.침묵 마 운 트 해제 에는 가방 이름 이 필요 합 니 다.마찬가지 로 침묵 마 운 트 해제 에 도 루트 권한 이 필요 합 니 다.
코드 보기:

<code class="hljs java">//   apk   
private static final String PACKAGE_NAME = "com.qiyi.video";
//    
 private void uninstallSlient() {
 String cmd = "pm uninstall " + PACKAGE_NAME;
 Process process = null;
 DataOutputStream os = null;
 BufferedReader successResult = null;
 BufferedReader errorResult = null;
 StringBuilder successMsg = null;
 StringBuilder errorMsg = null;
 try {
  //     root  
  process = Runtime.getRuntime().exec("su");
  os = new DataOutputStream(process.getOutputStream());
  os.write(cmd.getBytes());
  os.writeBytes("
"); os.writeBytes("exit
"); os.flush(); // process.waitFor(); // successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (process != null) { process.destroy(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (Exception e) { e.printStackTrace(); } } // tvTest.setText(" :" + successMsg.toString() + "
" + " : " + errorMsg.toString()); }</code>
침묵 설치 와 같은 코드 는 설명 하지 않 습 니 다.그리고 만약 에 apk 의 가방 이름 을 모른다 면 컴 파일 한 후에 AndroidManifest.xml 파일 을 보 세 요.만약 에 이 파일 을 열 면 모두 어 지 러 운 코드 입 니 다.헷 갈 렸 다 는 것 을 설명 합 니 다.그러면 직접 설치 한 다음 에/data/data 아래 에 가서 가방 을 찾 으 세 요.물론 핸드폰 은 root 가 있어 야/data/data 디 렉 터 리 에 들 어 갈 수 있 습 니 다.
6 스마트 설치
스마트 설 치 는 조금 번 거 롭 습 니 다.원 리 는 안 드 로 이 드 가 제공 하 는 Accessibility Service 서 비 스 를 사용 하 는 것 입 니 다.이 서 비 스 는 화면의 노드 를 얻 을 수 있 습 니 다.한 노드 는 하나의 view 입 니 다.우리 가 쓴 xml 파일 에 있 는 모든 라벨 은 하나의 노드 입 니 다.그 다음 에 사용자 의 조작 을 모 의 한 다음 에 이 노드 에 대해 클릭,미끄럼 등 작업 을 할 수 있 습 니 다.저 희 는 이 원 리 를 이용 하여 설치 단 추 를 자동 으로 클릭 합 니 다.물론 이 서 비 스 를 사용 하려 면 사용자 가 수 동 으로 무장 애 서 비 스 를 켜 야 합 니 다.구체 적 인 실현 방법 을 살 펴 보 자.
(1)AccessibilityService 프로필 만 들 기
res 디 렉 터 리 에 xml 디 렉 터 리 를 만 든 다음 xml 디 렉 터 리 에 accessibility 를 만 듭 니 다.service_config.xml 파일,내용 은 다음 과 같 습 니 다.
res/xml/accessibility_service_config.xml:

<code class="hljs xml" data-filtered="filtered"></accessibility-service></code>
access bility EventTypes:감청 창 에서 어떤 사건 을 모 의 할 수 있 는 지 지정 합 니 다.type:AllMask 는 모든 사건 을 모 의 할 수 있 음 을 표시 합 니 다.
accessibility Feedback Type:무장 애 서비스의 피드백 방식 을 지정 합 니 다.
canRetrieveWindow Content:프로그램 이 창의 노드 와 내용 을 읽 을 수 있 는 지 여 부 를 지정 합 니 다.물론 true 입 니 다.
description:사용자 가 수 동 으로 서 비 스 를 설정 할 때 사용자 에 게 보 여 줍 니 다.
packageNames:어떤 프로그램의 창 활동 을 감청 할 지 지정 합 니 다.com.android.packageinstaller 는 Android 시스템 의 설치 인 터 페 이 스 를 감청 합 니 다.
나머지 매개 변 수 는 그대로 쓰 면 된다.
res/strings.xml:

<code class="hljs xml"><resources>
 <string name="app_name">SlientInstallTest</string>
 <string name="desc">    app    </string>
</resources></code>
(2)AccessibilityService 서비스 만 들 기

<code class="hljs java">public class MyAccessibilityService extends AccessibilityService {
 private static final String TAG = "[TAG]";
 private Map<integer, boolean=""> handleMap = new HashMap<>();
 @Override
 public void onAccessibilityEvent(AccessibilityEvent event) {
 AccessibilityNodeInfo nodeInfo = event.getSource();
 if (nodeInfo != null) {
  int eventType = event.getEventType();
  if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
  if (handleMap.get(event.getWindowId()) == null) {
   boolean handled = iterateNodesAndHandle(nodeInfo);
   if (handled) {
   handleMap.put(event.getWindowId(), true);
   }
  }
  }
 }
 }
 @Override
 public void onInterrupt() {
 }
 //    ,        
 private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {
 if (nodeInfo != null) {
  int childCount = nodeInfo.getChildCount();
  if ("android.widget.Button".equals(nodeInfo.getClassName())) {
  String nodeCotent = nodeInfo.getText().toString();
  Log.d(TAG, "content is: " + nodeCotent);
  if ("  ".equals(nodeCotent) || "  ".equals(nodeCotent) || "  ".equals(nodeCotent)) {
   nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
   return true;
  }
  }
  //  ScrollView         
  else if ("android.widget.ScrollView".equals(nodeInfo.getClassName())) {
  nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
  }
  for (int i = 0; i < childCount; i++) {
  AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);
  if (iterateNodesAndHandle(childNodeInfo)) {
   return true;
  }
  }
 }
 return false;
 }
}</integer,></code>
apk 설치 인터페이스 에 들 어가 면 onAccessibilityEvent()방법 을 되 돌려 줍 니 다.저 희 는 TYPE 에 만 관심 이 있 습 니 다.WINDOW_CONTENT_CHANGED 와 TYPEWINDOW_STATE_CHANGED 두 이 벤트 는 중복 처 리 를 방지 하기 위해 하나의 map 로 이 벤트 를 걸 러 내 고 그 다음 에 노드 를 옮 겨 다 니 며'설치','완료','확인'단 추 를 찾 으 면 클릭 합 니 다.설치 인터페이스 가 굴 러 야 설치 단추 가 나타 나 기 때문에 ScrollView 를 만 났 을 때 스크롤 합 니 다.
(3)AndroidManifest 에 서비스 설정

<code class="hljs xml"><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE">
  <intent-filter>
  <category android:name="android.intent.category.LAUNCHER">
  </category></action></intent-filter>
 </activity>
 <service android:label="    App" android:name=".MyAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
  <intent-filter>
  </action></intent-filter>
  <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config">
 </meta-data></service>
 </application></uses-permission></code>
포 인 트 는 뒤의 service 태그 입 니 다.
android:label:이것 이 바로 사용자 가 본 무장 애 서비스의 이름 입 니 다.
android:permission:BIND 를 사용 해 야 합 니 다.ACCESSIBILITY_서비스 라 는 권한.
action:android.accessibility service.accessibility Service 는 이 action 이 있어 야 사용자 가 설정 에서 우리 의 서 비 스 를 볼 수 있 습 니 다.그렇지 않 으 면 사용자 가 우리 가 쓴 서 비 스 를 시작 할 수 없고 우리 가 쓴 MyAccessibility Service 에 들 어 갈 수 없습니다.따라서 잘못 쓰 지 않도록 주의 하 십시오.무장 애 서비스 에 우리 가 쓴 서비스 가 없 는 것 을 발견 하면 여 기 를 확인 하 십시오.
(4)스마트 설치 코드 호출
앞 에 준비 작업 이 끝 난 후에 지금 사용 해 야 합 니 다.스마트 설치 코드 는 다음 과 같 습 니 다.

<code class="hljs cs"> //    
 private void smartInstall() {
 Uri uri = Uri.fromFile(new File("/mnt/sdcard/test.apk"));
 Intent localIntent = new Intent(Intent.ACTION_VIEW);
 localIntent.setDataAndType(uri, "application/vnd.android.package-archive");
 startActivity(localIntent);
 }</code>
(5)스마트 설치 서비스 수 동 설정
코드 가 실 행 된 후에 사용자 가 스마트 설치 서 비 스 를 켜 서 사용자 가 스스로 찾 도록 하 는 것 은 현명 하지 못 하기 때문에 우 리 는 자발적으로 설정 인터페이스 로 뛰 어야 한다.코드 는 다음 과 같다.

<code class="hljs cs">//              
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);</code>
다음 그림 과 같이 설정:

보이 시 나 요?위 에 표 시 된 것 은 Service 에 있 는 label 의 값 입 니 다.위 에 옵션 이 없 으 면 AndroidManifest 에 있 는 Service 설정 을 확인 하 십시오.
'스마트 설치 앱'을 클릭 하여 서 비 스 를 시작 합 니 다.다음 그림:

그 중의 제시 문 자 는 바로 우리 가 res/xml/accessibilityservice_config.xml 파일 에 설 정 된 description 속성
7.우리 만 쓰 는 app 은 자동 으로 설치 할 수 있 습 니 다.
이렇게 코드 를 쓰 면 실행 할 수 있 습 니 다.단 추 를 누 르 면 sdcard 에 있 는 test.apk 를 자동 으로 설치 합 니 다.그러나 모든 apk 가 자동 으로 설치 되 는 것 을 발견 할 수 있 습 니 다.이것 은 우리 의 요구 에 부합 되 지 않 습 니 다.우 리 는 우리 가 쓴 app 을 통 해 자동 으로 설치 할 수 있 고 다른 apk 는 사용자 가 수 동 으로 주문 해 야 합 니 다.이 문 제 를 어떻게 해결 합 니까?
사고방식:MainActivity 에서 Public static boolean flag 를 만 들 고 MyAccessibility Service 의 onAccessibility Event()에 flag 판단 을 추가 한 다음 에 스마트 설치 전 flag 를 true 로 호출 하여 apk 설치 이벤트 의 방송 수신 기 를 만 듭 니 다.apk 설치 가 완 료 된 후에 false 를 false 로 설정 하면 다른 apk 가 자동 으로 설치 되 지 않 고 이 문 제 를 해결 할 수 있 습 니 다.
아래 위의 전체 코드.
8 전체 코드
app/MainActivity.java:

<code class="hljs java">public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 private static final String TAG = "[TAG][MainActivity]";
 private static final String PACKAGE_NAME = "com.qiyi.video";
 private String apkPath = "/mnt/sdcard/test.apk";
 public static boolean flag = false;//       app        
 private TextView tvTest;
 private MyInstallReceiver receiver;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 tvTest = (TextView) findViewById(R.id.tv_test);
 findViewById(R.id.btn_install).setOnClickListener(this);
 findViewById(R.id.btn_uninstall).setOnClickListener(this);
 findViewById(R.id.btn_set).setOnClickListener(this);
 findViewById(R.id.btn_smart_install).setOnClickListener(this);
 //  apk    
 receiver = new MyInstallReceiver();
 IntentFilter filter = new IntentFilter();
 filter.addAction("android.intent.action.PACKAGE_ADDED");
 filter.addAction("android.intent.action.PACKAGE_REMOVED");
 filter.addDataScheme("package");
 this.registerReceiver(receiver, filter);
 }
 @Override
 public void onClick(View v) {
 switch (v.getId()) {
  //    
  case R.id.btn_install:
  installSlient();
  break;
  //    
  case R.id.btn_uninstall:
  uninstallSlient();
  break;
  //       
  case R.id.btn_set:
  //             
  Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
  startActivity(intent);
  break;
  //    
  case R.id.btn_smart_install:
  //       app      
  flag = true;
  smartInstall();
  break;
 }
 }
 //    
 private void installSlient() {
 String cmd = "pm install -r /mnt/sdcard/test.apk";
 Process process = null;
 DataOutputStream os = null;
 BufferedReader successResult = null;
 BufferedReader errorResult = null;
 StringBuilder successMsg = null;
 StringBuilder errorMsg = null;
 try {
  //      root  
  process = Runtime.getRuntime().exec("su");
  os = new DataOutputStream(process.getOutputStream());
  os.write(cmd.getBytes());
  os.writeBytes("
"); os.writeBytes("exit
"); os.flush(); // process.waitFor(); // successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (process != null) { process.destroy(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (Exception e) { e.printStackTrace(); } } // tvTest.setText(" :" + successMsg.toString() + "
" + " : " + errorMsg.toString()); } // private void uninstallSlient() { String cmd = "pm uninstall " + PACKAGE_NAME; Process process = null; DataOutputStream os = null; BufferedReader successResult = null; BufferedReader errorResult = null; StringBuilder successMsg = null; StringBuilder errorMsg = null; try { // root process = Runtime.getRuntime().exec("su"); os = new DataOutputStream(process.getOutputStream()); os.write(cmd.getBytes()); os.writeBytes("
"); os.writeBytes("exit
"); os.flush(); // process.waitFor(); // successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (process != null) { process.destroy(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (Exception e) { e.printStackTrace(); } } // tvTest.setText(" :" + successMsg.toString() + "
" + " : " + errorMsg.toString()); } // private void smartInstall() { Uri uri = Uri.fromFile(new File(apkPath)); Intent localIntent = new Intent(Intent.ACTION_VIEW); localIntent.setDataAndType(uri, "application/vnd.android.package-archive"); startActivity(localIntent); } // apk private class MyInstallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) { // install String packageName = intent.getDataString(); Log.i(TAG, " :" + packageName); // , flag, apk flag = false; } if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) { // uninstall String packageName = intent.getDataString(); Log.i(TAG, " :" + packageName); } } } @Override protected void onDestroy() { super.onDestroy(); if (receiver != null) { unregisterReceiver(receiver); } } }</code>
화면 에 세 개의 버튼 만 있다.
res/layout/activity_main.xml:

<code class="hljs xml"><!--?xml version="1.0" encoding="utf-8"?-->
<relativelayout android:layout_height="match_parent" android:layout_width="match_parent" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools">
 <textview android:id="@+id/tv_test" android:layout_height="wrap_content" android:layout_width="match_parent" android:text=""><button android:id="@+id/btn_install" android:layout_centerinparent="true" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="  "></button><button android:id="@+id/btn_uninstall" android:layout_below="@id/btn_install" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="  "></button><button android:id="@+id/btn_set" android:layout_below="@id/btn_uninstall" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="        "></button></textview></relativelayout></code><button android:id="@+id/btn_smart_install" android:layout_below="@id/btn_set" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="    "><code class="hljs xml">
</code></button>
서비스 프로필
res/xml/accessibility_service_config.xml

<code class="hljs xml" data-filtered="filtered"></accessibility-service></code>
지능 설치 서비스
app/MyAccessibilityService.java:

<code class="hljs java">public class MyAccessibilityService extends AccessibilityService {
 private static final String TAG = "[TAG]";
 private Map<integer, boolean=""> handleMap = new HashMap<>();
 @Override
 public void onAccessibilityEvent(AccessibilityEvent event) {
 AccessibilityNodeInfo nodeInfo = event.getSource();
 if (nodeInfo != null && MainActivity.flag) {
  int eventType = event.getEventType();
  if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
  if (handleMap.get(event.getWindowId()) == null) {
   boolean handled = iterateNodesAndHandle(nodeInfo);
   if (handled) {
   handleMap.put(event.getWindowId(), true);
   }
  }
  }
 }
 }
 @Override
 public void onInterrupt() {
 }
 //    ,        
 private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {
 if (nodeInfo != null) {
  int childCount = nodeInfo.getChildCount();
  if ("android.widget.Button".equals(nodeInfo.getClassName())) {
  String nodeCotent = nodeInfo.getText().toString();
  Log.d(TAG, "content is: " + nodeCotent);
  if ("  ".equals(nodeCotent) || "  ".equals(nodeCotent) || "  ".equals(nodeCotent)) {
   nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
   return true;
  }
  }
  //  ScrollView         
  else if ("android.widget.ScrollView".equals(nodeInfo.getClassName())) {
  nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
  }
  for (int i = 0; i < childCount; i++) {
  AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);
  if (iterateNodesAndHandle(childNodeInfo)) {
   return true;
  }
  }
 }
 return false;
 }
}</integer,></code>
마지막 으로 프로필 AndroidManifest.xml:

<code class="hljs xml"><manifest package="com.slientinstalltest" xmlns:android="https://schemas.android.com/apk/res/android">
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE">
  <intent-filter>
  <category android:name="android.intent.category.LAUNCHER">
  </category></action></intent-filter>
 </activity>
 <service android:label="    App" android:name=".MyAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
  <intent-filter>
  </action></intent-filter>
  <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config">
 </meta-data></service>
 </application>
</uses-permission></manifest></code>
메모:설치 할 apk 를 sdcard 에 올 리 고 코드 에 있 는 apk 경로 와 가방 이름 을 수정 하 십시오.
9 실행 효과
 
10 총화
Android 스마트 설치 의 원 리 는 갈고리 와 유사 한 서 비 스 를 이용 한 것 입 니 다.이 서 비 스 는 위 챗 에서 보 너 스 를 빼 앗 는 개발 에 도 사용 할 수 있 습 니 다.어 떻 습 니까?ios 보다 재 미 있 는 것 이 아 닙 니까?

좋은 웹페이지 즐겨찾기