要抓取系统日记,只需运行adb logcat即可,但需要在终端上运行命令才行。安装第
三方应用需要adb shell pm grant 包名 android.permission.READ_LOGS才能读到系统
日记,这是由于android.permission.READ_LOGS不能直接申请导致。现在的手机平台都
是在拨号界面输入一串字符,即可调用app抓取日记(如mtk平台输入*#*#3646633#*#*,可
调用mtklogger),于是自己写了一个demo(Android7.0 mtk)。
输入字符串启动应用原理
packages/services/Telephony/src/com/android/phone/SpecialCharSequenceMgr.java
static private boolean handleSecretCode(Context context, String input) { // Secret codes are in the form *#*#<code>#*#* int len = input.length(); if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) { Intent intent = new Intent(TelephonyIntents.SECRET_CODE_ACTION, Uri.parse("android_secret_code://" + input.substring(4, len - 4))); context.sendBroadcast(intent); return true; } return false; }
这里发出了广播,我们只需监听该广播即可。
public class BroastcastReceiverService extends Service { private BroadcastReceiver receiver; private String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE"; private String TAG = "logcat"; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.e(TAG,"BroastcastReceiverService start"); receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.e(TAG,"onReceive"); if (intent.getAction().equals(SECRET_CODE_ACTION)){ Uri uri = intent.getData(); String host=uri.getHost(); String scheme=uri.getScheme(); Log.e(TAG,host); Log.e(TAG,scheme); if(host.equals("888")) { Log.e(TAG,"start logcatread app"); Intent intentobj = new Intent(BroastcastReceiverService.this,MainActivity.class); startActivity(intentobj); } } } }; IntentFilter filter = new IntentFilter(SECRET_CODE_ACTION); filter.addDataScheme("android_secret_code"); registerReceiver(receiver, filter); } @Override public void onDestroy() { } }
AndroidManifest.xml加上
<service android:name="BroastcastReceiverService" android:exported="true" android:enabled="true"/>
启动该服务
frameworks/base/services/java/com/android/server/SystemServer.java
startSystemUi方法中加上
Intent intent1 = new Intent(); intent.setComponent(new ComponentName("www.com.logcatreader", "www.com.logcatreader.BroastcastReceiverService")); context.startServiceAsUser(intent, UserHandle.SYSTEM);这里会报错ActivityManager: Unable to start service Intent { cmp=www.com.logcatreader/.BroastcastReceiverService } U=0: not found
查到是这里出错
frameworks/base/core/java/android/content/pm/PackageUserState.java
public boolean isMatch(ComponentInfo componentInfo, int flags) { if (!isInstalled(flags)) return false; if (!isEnabled(componentInfo, flags)) return false; if ((flags & MATCH_SYSTEM_ONLY) != 0) { if (!componentInfo.applicationInfo.isSystemApp()) { return false; } } final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0) && !componentInfo.directBootAware; final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0) && componentInfo.directBootAware; Log.v(TAG,matchesUnaware+""+matchesAware); Log.v(TAG,flags+""); return matchesUnaware || matchesAware; }AndroidManifest.xml加上
android:directBootAware="true"系统休眠后,该服务就被杀掉到了,在AndroidManifest.xml加上
android:persistent="true"
抓取logcat代码
@Override public void run() { try { File folder = new File("/mnt/sdcard/Android/syslog"); if(!folder.exists()) { boolean ret=folder.mkdirs(); if(!ret) { Log.e(TAG, "create folder failed"); return; } } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");// HH:mm:ss Date date = new Date(System.currentTimeMillis()); String tg = simpleDateFormat.format(date); Log.e(TAG, tg); file = new File(folder, tg + ".txt"); String line; if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { return; } } Process process = Runtime.getRuntime().exec("logcat"); out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true))); Log.e(TAG, "Process : " + process); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); while ((line = bufferedReader.readLine()) != null) { out.write(line); out.write("\r\n"); if(!isObserverLog){ out.close(); Log.e(TAG, "close" ); break; } } } catch (IOException e) { e.printStackTrace(); }; Log.e(TAG, "thread exit" ); }
再把应用的图标隐藏掉,在AndroidManifest.xml注释
<category android:name="android.intent.category.LAUNCHER" />
将该应用编译进系统
在AndroidManifest.xml加上android:sharedUserId="android.uid.system"这里用android-studio写代码,调试完后,选择Build->Bulid-APK(s),app/build/outputs/apk/debug/app-debug.apk
即我们需要的apk,并将该app改名为logcatreader.apk
编写Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := logcatreader LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_TAGS := optional LOCAL_BUILT_MODULE_STEM := package.apk LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true LOCAL_SRC_FILES := $(LOCAL_MODULE).apk include $(BUILD_PREBUILT)mmm进行编译(如果要编译到系统,加入PRODUCT_PACKAGES+=logcatreader),并push到系统。
源码地址 https://github.com/wew888/logcatreader.git