ฉันจะค้นหาหน่วยความจำที่ใช้กับแอปพลิเคชัน Android ของฉันได้โดยทางโปรแกรมอย่างไร
ฉันหวังว่าจะมีวิธีที่จะทำ นอกจากนี้ฉันจะรับหน่วยความจำฟรีของโทรศัพท์ได้อย่างไร
ฉันจะค้นหาหน่วยความจำที่ใช้กับแอปพลิเคชัน Android ของฉันได้โดยทางโปรแกรมอย่างไร
ฉันหวังว่าจะมีวิธีที่จะทำ นอกจากนี้ฉันจะรับหน่วยความจำฟรีของโทรศัพท์ได้อย่างไร
คำตอบ:
โปรดทราบว่าการใช้หน่วยความจำบนระบบปฏิบัติการสมัยใหม่เช่น Linux นั้นเป็นพื้นที่ที่ซับซ้อนและยากต่อการเข้าใจ ในความเป็นจริงโอกาสที่คุณจะตีความตัวเลขใด ๆ ที่คุณได้รับนั้นต่ำมาก (ค่อนข้างทุกครั้งที่ฉันดูหมายเลขการใช้หน่วยความจำกับวิศวกรคนอื่น ๆ มีการพูดคุยกันนานเกี่ยวกับสิ่งที่พวกเขาจริง ๆ แล้วหมายความว่าจะส่งผลให้เกิดข้อสรุปที่คลุมเครือเท่านั้น)
หมายเหตุ: ตอนนี้เรามีเอกสารมากมายเกี่ยวกับการจัดการหน่วยความจำของแอพของคุณซึ่งครอบคลุมเนื้อหาส่วนใหญ่ที่นี่และเป็นข้อมูลล่าสุดเกี่ยวกับสถานะของ Android
สิ่งแรกคือการอ่านส่วนสุดท้ายของบทความนี้ซึ่งมีการอภิปรายบางส่วนเกี่ยวกับวิธีการจัดการหน่วยความจำบน Android:
การเปลี่ยนแปลง API บริการเริ่มต้นด้วย Android 2.0
ตอนนี้ActivityManager.getMemoryInfo()
เป็น API ระดับสูงสุดของเราสำหรับการดูการใช้งานหน่วยความจำโดยรวม นี่เป็นส่วนใหญ่ที่จะช่วยให้แอพพลิเคชั่นเกจว่าระบบใกล้จะมาถึงที่จะไม่มีหน่วยความจำมากขึ้นสำหรับกระบวนการพื้นหลังดังนั้นจึงจำเป็นต้องเริ่มต้นฆ่ากระบวนการที่ต้องการเช่นบริการ สำหรับแอพพลิเคชั่นจาวาล้วนๆสิ่งนี้ควรใช้เพียงเล็กน้อยเนื่องจากขีด จำกัด ของฮีพของ Java อยู่ในส่วนหนึ่งเพื่อหลีกเลี่ยงหนึ่งแอพที่จะทำให้ระบบเครียดจนถึงจุดนี้
การลดระดับลงคุณสามารถใช้ Debug API เพื่อรับข้อมูลระดับเคอร์เนลแบบดิบเกี่ยวกับการใช้หน่วยความจำ: android.os.Debug.MemoryInfo
หมายเหตุเริ่มต้นด้วย 2.0 นอกจากนี้ยังมี API ActivityManager.getProcessMemoryInfo
เพื่อรับข้อมูลนี้เกี่ยวกับกระบวนการอื่น: ActivityManager.getProcessMemoryInfo (int [])
ส่งคืนโครงสร้าง MemoryInfo ระดับต่ำที่มีข้อมูลทั้งหมดนี้:
/** The proportional set size for dalvik. */
public int dalvikPss;
/** The private dirty pages used by dalvik. */
public int dalvikPrivateDirty;
/** The shared dirty pages used by dalvik. */
public int dalvikSharedDirty;
/** The proportional set size for the native heap. */
public int nativePss;
/** The private dirty pages used by the native heap. */
public int nativePrivateDirty;
/** The shared dirty pages used by the native heap. */
public int nativeSharedDirty;
/** The proportional set size for everything else. */
public int otherPss;
/** The private dirty pages used by everything else. */
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
public int otherSharedDirty;
แต่เป็นสิ่งที่แตกต่างระหว่างPss
, PrivateDirty
และSharedDirty
... ดีตอนนี้สนุกจะเริ่มขึ้น
หน่วยความจำจำนวนมากใน Android (และระบบ Linux โดยทั่วไป) มีการใช้งานร่วมกันจริงในหลาย ๆ กระบวนการ ดังนั้นจำนวนหน่วยความจำที่กระบวนการใช้นั้นไม่ชัดเจนจริงๆ เพิ่มเพจนั้นลงบนดิสก์ (ให้สลับอย่างเดียวซึ่งเราไม่ได้ใช้บน Android) และชัดเจนน้อยกว่า
ดังนั้นถ้าคุณใช้ RAM จริงทั้งหมดที่แมปในแต่ละกระบวนการและรวมกระบวนการทั้งหมดคุณอาจจะต้องจบลงด้วยจำนวนที่มากกว่า RAM ทั้งหมดที่เกิดขึ้นจริง
Pss
จำนวนเป็นตัวชี้วัดคำนวณเคอร์เนลที่จะเข้าสู่การแชร์หน่วยความจำบัญชี - พื้นหน้าของ RAM ในแต่ละกระบวนการที่มีการปรับสัดส่วนโดยอัตราส่วนของจำนวนของกระบวนการอื่น ๆ ที่ยังมีการใช้หน้านั้น วิธีนี้คุณสามารถเพิ่ม pss ในกระบวนการทั้งหมดเพื่อดู RAM ทั้งหมดที่ใช้และเปรียบเทียบ pss ระหว่างกระบวนการเพื่อให้เข้าใจถึงน้ำหนักสัมพัทธ์
ตัวชี้วัดที่น่าสนใจอื่น ๆ ที่นี่คือPrivateDirty
ซึ่งโดยทั่วไปคือปริมาณของ RAM ภายในกระบวนการที่ไม่สามารถทำเพจได้กับดิสก์ (ไม่ได้รับการสนับสนุนจากข้อมูลบนดิสก์เดียวกัน) และไม่ถูกแชร์กับกระบวนการอื่น ๆ อีกวิธีในการดูนี่คือ RAM ที่จะพร้อมใช้งานกับระบบเมื่อกระบวนการนั้นหายไป (และอาจรวมเข้ากับแคชและการใช้งานอื่นอย่างรวดเร็ว)
นั่นเป็น SDK APIs ที่ค่อนข้างดีสำหรับเรื่องนี้ อย่างไรก็ตามมีมากกว่าที่คุณสามารถทำได้ในฐานะนักพัฒนาซอฟต์แวร์ด้วยอุปกรณ์ของคุณ
การใช้adb
มีข้อมูลจำนวนมากที่คุณสามารถรับเกี่ยวกับการใช้หน่วยความจำของระบบที่กำลังทำงานอยู่ หนึ่งที่พบบ่อยคือคำสั่งadb shell dumpsys meminfo
ที่จะคายออกข้อมูลมากมายเกี่ยวกับการใช้หน่วยความจำของแต่ละกระบวนการ Java ที่มีข้อมูลข้างต้นเช่นเดียวกับความหลากหลายของสิ่งอื่น ๆ นอกจากนี้คุณยังสามารถตรึงชื่อหรือ pid ของกระบวนการเดียวที่จะเห็นตัวอย่างเช่นadb shell dumpsys meminfo system
ให้กระบวนการฉัน:
** MEMINFO ใน pid 890 [ระบบ] ** native dalvik รวมทั้งหมด ขนาด: 10940 7047 N / A 17987 จัดสรร: 8943 5516 N / A 14459 ฟรี: 336 1531 N / A 1867 (Pss): 4585 9282 11916 25783 (แบ่งปันสกปรก): 2184 3596 916 6696 (สกปรกสกปรก): 4504 5956 7456 17916 วัตถุ Views: 149 ViewRoots: 4 AppContexts: 13 กิจกรรม: 0 สินทรัพย์: 4 ผู้จัดการสินทรัพย์: 4 Local Binders: 141 Binder proxy: 158 ผู้รับความตาย: 49 Sockets OpenSSL: 0 SQL กอง: 205 dbFiles: 0 numPagers: 0 inactivePageKB: 0 activePageKB: 0
ส่วนด้านบนเป็นส่วนหลักซึ่งsize
ขนาดโดยรวมในพื้นที่ที่อยู่ของฮีปหนึ่ง ๆallocated
คือ kb ของการจัดสรรจริงที่ฮีปคิดว่ามีfree
อยู่คือ kb ที่เหลือฟรีฮีพที่มีสำหรับการจัดสรรเพิ่มเติมpss
และpriv dirty
เป็นแบบเดียวกัน ตามที่กล่าวไว้ก่อนหน้าเฉพาะหน้าที่เกี่ยวข้องกับแต่ละฮีป
adb shell procrank
ถ้าคุณเพียงต้องการที่จะดูที่การใช้งานหน่วยความจำผ่านกระบวนการทั้งหมดที่คุณสามารถใช้คำสั่ง ผลลัพธ์ของสิ่งนี้ในระบบเดียวกันดูเหมือนว่า:
PID Vss Rss Pss ใช้ cmdline 890 84456K 48668K 25850K 21284K system_server 1231 50748K 39088K 17587K 13792K com.android.launcher2 947 34488K 28528K 10834K 9308K com.android.wallpaper 987 26964K 26956K 8751K 7308K com.google.process.gapps 954 24300K 24296K 6249K 4824K com.android.phone 948 23020K 23016K 5864K 4748K com.android.inputmethod.latin 888 25728K 25724K 5774K 3668K zygote 977 24100K 24096K 5667K 4340K android.process.acore ... 59 336K 332K 99K 92K / system / bin / installd 60 396K 392K 93K 84K / system / bin / keystore 51 280K 276K 74K 68K / system / bin / servicemanager 54 256K 252K 69K 64K / system / bin / debuggerd
ที่นี่Vss
และRss
คอลัมน์เป็นเสียงรบกวน (เหล่านี้คือพื้นที่ที่อยู่ตรงไปข้างหน้าและการใช้ RAM ของกระบวนการซึ่งถ้าคุณเพิ่มการใช้ RAM ในกระบวนการที่คุณได้รับเป็นจำนวนมากอย่างน่าขัน)
Pss
คือเท่าที่เราได้เห็นมาก่อนและเป็นUss
Priv Dirty
สิ่งที่น่าสนใจที่จะต้องทราบที่นี่: Pss
และUss
เล็กน้อย (หรือมากกว่าเล็กน้อย) meminfo
แตกต่างจากสิ่งที่เราเห็นใน ทำไมถึงเป็นอย่างนั้น? procrank ดีใช้กลไกเคอร์เนลที่แตกต่างกันในการรวบรวมข้อมูลของมันmeminfo
และพวกเขาให้ผลแตกต่างกันเล็กน้อย ทำไมถึงเป็นอย่างนั้น? สุจริตฉันไม่ได้เบาะแส ฉันเชื่อว่าprocrank
อาจเป็นสิ่งที่ถูกต้องมากขึ้น ... แต่จริงๆแล้วนี่แค่ทิ้งประเด็นไว้: "เอาข้อมูลความทรงจำใด ๆ ที่คุณได้รับมาด้วยเกลือเม็ด; มักจะเป็นเมล็ดที่มีขนาดใหญ่มาก"
ในที่สุดก็มีคำสั่งadb shell cat /proc/meminfo
ที่ให้บทสรุปของการใช้หน่วยความจำโดยรวมของระบบ มีข้อมูลจำนวนมากที่นี่เพียงไม่กี่ตัวเลขแรกที่ควรพูดถึง (และคนที่เหลือที่เข้าใจโดยคนไม่กี่คนและคำถามของฉันเกี่ยวกับคนเหล่านั้นเกี่ยวกับพวกเขามักทำให้เกิดคำอธิบายที่ขัดแย้งกัน):
MemTotal: 395144 kB MemFree: 184936 kB บัฟเฟอร์: 880 kB แคช: 84104 kB SwapCached: 0 kB
MemTotal
คือจำนวนหน่วยความจำทั้งหมดที่มีสำหรับเคอร์เนลและพื้นที่ผู้ใช้ (มักน้อยกว่า RAM จริงของอุปกรณ์เนื่องจาก RAM บางตัวนั้นจำเป็นสำหรับวิทยุบัฟเฟอร์ DMA และอื่น ๆ )
MemFree
คือจำนวน RAM ที่ไม่ได้ใช้งานเลย จำนวนที่คุณเห็นที่นี่สูงมาก โดยทั่วไปแล้วในระบบ Android จะเป็นเพียงไม่กี่ MB เนื่องจากเราพยายามใช้หน่วยความจำที่มีอยู่เพื่อให้กระบวนการทำงานต่อไป
Cached
เป็นแรมที่ใช้สำหรับแคชของระบบไฟล์และสิ่งอื่น ๆ ระบบทั่วไปจะต้องมี 20MB หรือมากกว่านั้นเพื่อหลีกเลี่ยงการเข้าสู่สถานะเพจไม่ดี Android killer หน่วยความจำไม่พอปรับสำหรับระบบเฉพาะเพื่อให้แน่ใจว่ากระบวนการพื้นหลังถูกฆ่าก่อนที่ RAM ที่แคชจะถูกใช้มากเกินไปโดยพวกเขาจะส่งผลให้เพจจิ้ง
ใช่คุณสามารถรับข้อมูลหน่วยความจำโดยทางโปรแกรมและตัดสินใจว่าจะใช้งานหน่วยความจำมากหรือไม่
รับ VM Heap Size โดยโทร:
Runtime.getRuntime().totalMemory();
รับหน่วยความจำ VM ที่จัดสรรโดยการโทร:
Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
รับ VM Heap Size Limit โดยโทร:
Runtime.getRuntime().maxMemory()
รับหน่วยความจำที่จัดสรรโดยการโทร:
Debug.getNativeHeapAllocatedSize();
ฉันสร้างแอพเพื่อหาพฤติกรรม OutOfMemoryError และตรวจสอบการใช้หน่วยความจำ
https://play.google.com/store/apps/details?id=net.coocood.oomresearch
คุณสามารถรับซอร์สโค้ดได้ที่ https://github.com/coocood/oom-research
นี่คืองานที่กำลังดำเนินการ แต่นี่คือสิ่งที่ฉันไม่เข้าใจ:
ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );
List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}
Collection<Integer> keys = pidMap.keySet();
for(int key : keys)
{
int pids[] = new int[1];
pids[0] = key;
android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
{
Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n");
Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
}
}
เหตุใด PID จึงไม่แมปกับผลลัพธ์ใน activityManager.getProcessMemoryInfo () เห็นได้ชัดว่าคุณต้องการทำให้ข้อมูลผลลัพธ์มีความหมายดังนั้นทำไม Google จึงทำให้มันยากที่จะเชื่อมโยงผลลัพธ์? ระบบปัจจุบันทำงานได้ไม่ดีนักหากฉันต้องการประมวลผลการใช้หน่วยความจำทั้งหมดเนื่องจากผลลัพธ์ที่ส่งคืนเป็นอาร์เรย์ของวัตถุ android.os.Debug.MemoryInfo แต่ไม่มีวัตถุใดที่บอกให้คุณทราบว่ามีการเชื่อมโยงกับอะไร หากคุณผ่านไปในหลาย ๆ pids คุณจะไม่มีทางเข้าใจผลลัพธ์ ตามที่ฉันเข้าใจการใช้งานมันไม่มีความหมายเลยที่จะส่งผ่าน pid มากกว่าหนึ่งครั้งและถ้าเป็นกรณีนี้เหตุใดจึงต้องทำเช่นนั้นเพื่อให้ ActivityManager.getProcessMemoryInfo () ใช้อาร์เรย์ int เท่านั้น?
Hackbod's เป็นหนึ่งในคำตอบที่ดีที่สุดของ Stack Overflow มันพ่นแสงไปที่วัตถุที่คลุมเครือมาก มันช่วยฉันได้มาก
แหล่งข้อมูลที่มีประโยชน์จริง ๆ คือวิดีโอที่ต้องดู: Google I / O 2011: การจัดการหน่วยความจำสำหรับแอพ Android
UPDATE:
Process Stats บริการค้นหาวิธีที่แอพของคุณจัดการหน่วยความจำอธิบายที่โพสต์บล็อกProcess Process: ทำความเข้าใจว่าแอพของคุณใช้ RAMโดย Dianne Hackborn อย่างไร:
Android สตูดิโอ 0.8.10+ ได้แนะนำเครื่องมือที่มีประโยชน์อย่างไม่น่าเชื่อที่เรียกว่าหน่วยความจำการตรวจสอบ
สิ่งที่ดีสำหรับ:
- แสดงหน่วยความจำที่มีอยู่และใช้แล้วในกราฟและเหตุการณ์การเก็บขยะเมื่อเวลาผ่านไป
- ทดสอบอย่างรวดเร็วว่าแอพพลิเคชั่นความช้าอาจเกี่ยวข้องกับเหตุการณ์การรวบรวมขยะมากเกินไปหรือไม่
- ทดสอบอย่างรวดเร็วว่าแอปขัดข้องอาจเกี่ยวข้องกับหน่วยความจำไม่เพียงพอหรือไม่
รูปที่ 1. บังคับให้เหตุการณ์ GC (รวบรวมขยะ) บน Android Memory Monitor
คุณสามารถมีข้อมูลที่ดีมากมายเกี่ยวกับการใช้ RAM แบบเรียลไทม์ของแอปโดยใช้มัน
1) ฉันเดาว่าอย่างน้อยก็ไม่ใช่จาก Java
2)
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo mi = new MemoryInfo();
activityManager.getMemoryInfo(mi);
Log.i("memory free", "" + mi.availMem);
เราพบว่าวิธีมาตรฐานทั้งหมดในการรับหน่วยความจำทั้งหมดของกระบวนการปัจจุบันมีปัญหาบางอย่าง
Runtime.getRuntime().totalMemory()
: ส่งคืนหน่วยความจำ JVM เท่านั้นActivityManager.getMemoryInfo()
, Process.getFreeMemory()
และสิ่งอื่นที่อยู่บนพื้นฐาน/proc/meminfo
- ข้อมูลหน่วยความจำผลตอบแทนที่เกี่ยวกับกระบวนการทั้งหมดรวมกัน (เช่นandroid_util_Process.cpp )Debug.getNativeHeapAllocatedSize()
- ใช้mallinfo()
ข้อมูลส่งคืนเกี่ยวกับการจัดสรรหน่วยความจำที่ดำเนินการโดยmalloc()
และฟังก์ชันที่เกี่ยวข้องเท่านั้น (ดูandroid_os_Debug.cpp )Debug.getMemoryInfo()
- ทำงานได้ แต่ช้าเกินไป ใช้เวลาประมาณ200msในNexus 6สำหรับการโทรครั้งเดียว ค่าใช้จ่ายด้านประสิทธิภาพทำให้ฟังก์ชั่นนี้ไร้ประโยชน์สำหรับเราในขณะที่เราเรียกมันว่าเป็นประจำและทุกการโทรค่อนข้างชัดเจน (ดูandroid_os_Debug.cpp )ActivityManager.getProcessMemoryInfo(int[])
- โทรDebug.getMemoryInfo()
ภายใน (ดูActivityManagerService.java )สุดท้ายเราก็ใช้รหัสต่อไปนี้:
const long pageSize = 4 * 1024; //`sysconf(_SC_PAGESIZE)`
string stats = File.ReadAllText("/proc/self/statm");
var statsArr = stats.Split(new [] {' ', '\t', '\n'}, 3);
if( statsArr.Length < 2 )
throw new Exception("Parsing error of /proc/self/statm: " + stats);
return long.Parse(statsArr[1]) * pageSize;
มันกลับVmRSSเมตริก คุณสามารถค้นหารายละเอียดเพิ่มเติมได้ที่นี่: หนึ่ง , สองและสาม
PSฉันสังเกตเห็นว่าชุดรูปแบบยังคงมีข้อมูลโค้ดจริงและเรียบง่ายของวิธีการประเมินการใช้หน่วยความจำส่วนตัวของกระบวนการหากประสิทธิภาพไม่ใช่ข้อกำหนดที่สำคัญ:
Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
Debug.getMemoryInfo(memInfo);
long res = memInfo.getTotalPrivateDirty();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
res += memInfo.getTotalPrivateClean();
return res * 1024L;
ใน android studio 3.0 พวกเขาได้แนะนำ android-profiler เพื่อช่วยให้คุณเข้าใจว่าแอปของคุณใช้ทรัพยากรหน่วยความจำเครือข่ายและแบตเตอรี่อย่างไร
https://developer.android.com/studio/profile/android-profiler
มีคำตอบมากมายที่ด้านบนซึ่งจะช่วยคุณได้อย่างแน่นอน แต่(หลังจาก 2 วันของการซื้อและการวิจัยเกี่ยวกับเครื่องมือหน่วยความจำ adb)ฉันคิดว่าฉันสามารถช่วยด้วยความเห็นของฉันเช่นกัน
ตามที่ Hackbod พูดว่า: ดังนั้นหากคุณใช้ RAM จริงทั้งหมดที่แมปเข้ากับแต่ละกระบวนการและเพิ่มกระบวนการทั้งหมดคุณอาจต้องจบลงด้วยจำนวน RAM ที่แท้จริงทั้งหมด ดังนั้นจึงไม่มีวิธีที่คุณจะได้รับจำนวนหน่วยความจำที่แน่นอนต่อกระบวนการ
แต่คุณสามารถเข้าใกล้มันได้ด้วยตรรกะบางอย่าง .. และฉันจะบอกวิธี ..
มีบางอย่างที่ชอบ
android.os.Debug.MemoryInfo
และActivityManager.getMemoryInfo()
กล่าวถึงข้างต้นซึ่งคุณอาจได้อ่านและใช้แล้ว แต่ฉันจะพูดถึงวิธีอื่น
ดังนั้นก่อนอื่นคุณต้องเป็นผู้ใช้รูทเพื่อให้มันใช้งานได้ ได้รับในคอนโซลที่มีสิทธิ์รากโดยการดำเนินการในขั้นตอนและได้รับมันsu
output and input stream
แล้วส่งผ่านid\n
(ป้อน)ใน ouputstream และเขียนเพื่อส่งออกกระบวนการหากจะได้รับที่มี InputStream uid=0
, คุณเป็นผู้ใช้ราก
ตอนนี้นี่คือตรรกะที่คุณจะใช้ในกระบวนการข้างต้น
เมื่อคุณได้รับ ouput สตรีมของกระบวนการผ่านคุณสั่ง (procrank, dumpsys meminfo ฯลฯ ... ) ด้วย\n
แทนที่จะเป็น idและได้รับinputstream
และอ่านมันเก็บกระแสในไบต์ [], ถ่าน [] ฯลฯ ใช้ข้อมูลดิบ .. และคุณ เสร็จแล้ว!!!!!
การอนุญาต:
<uses-permission android:name="android.permission.FACTORY_TEST"/>
ตรวจสอบว่าคุณเป็นผู้ใช้รูทหรือไม่:
// su command to get root access
Process process = Runtime.getRuntime().exec("su");
DataOutputStream dataOutputStream =
new DataOutputStream(process.getOutputStream());
DataInputStream dataInputStream =
new DataInputStream(process.getInputStream());
if (dataInputStream != null && dataOutputStream != null) {
// write id to console with enter
dataOutputStream.writeBytes("id\n");
dataOutputStream.flush();
String Uid = dataInputStream.readLine();
// read output and check if uid is there
if (Uid.contains("uid=0")) {
// you are root user
}
}
ดำเนินการคำสั่งของคุณด้วย su
Process process = Runtime.getRuntime().exec("su");
DataOutputStream dataOutputStream =
new DataOutputStream(process.getOutputStream());
if (dataOutputStream != null) {
// adb command
dataOutputStream.writeBytes("procrank\n");
dataOutputStream.flush();
BufferedInputStream bufferedInputStream =
new BufferedInputStream(process.getInputStream());
// this is important as it takes times to return to next line so wait
// else you with get empty bytes in buffered stream
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// read buffered stream into byte,char etc.
byte[] bff = new byte[bufferedInputStream.available()];
bufferedInputStream.read(bff);
bufferedInputStream.close();
}
}
คุณจะได้รับข้อมูลดิบในสายเดียวจากคอนโซลแทนในบางกรณีจาก API ใด ๆ ที่มีความซับซ้อนในการจัดเก็บที่คุณจะต้องแยกออกจากกันได้ด้วยตนเอง
นี่เป็นเพียงการลองโปรดแนะนำฉันหากฉันพลาดบางสิ่งบางอย่าง