Làm cách nào để khám phá việc sử dụng bộ nhớ của ứng dụng của tôi trong Android?


800

Làm cách nào để tìm bộ nhớ được sử dụng trên ứng dụng Android của tôi, theo lập trình?

Tôi hy vọng có một cách để làm điều đó. Ngoài ra, làm thế nào để tôi có được bộ nhớ miễn phí của điện thoại?


2
Hoặc nếu bất cứ ai muốn biết thêm về tất cả những điều này thì vui lòng tham khảo http://elinux.org/Android_Memory_Usage

Câu trả lời:


1008

Lưu ý rằng việc sử dụng bộ nhớ trên các hệ điều hành hiện đại như Linux là một lĩnh vực cực kỳ phức tạp và khó hiểu. Trong thực tế, khả năng bạn thực sự diễn giải chính xác bất cứ con số nào bạn nhận được là cực kỳ thấp. (Khá nhiều mỗi khi tôi nhìn vào số lượng sử dụng bộ nhớ với các kỹ sư khác, luôn có một cuộc thảo luận dài về ý nghĩa thực sự của chúng mà chỉ dẫn đến một kết luận mơ hồ.)

Lưu ý: hiện tại chúng tôi có nhiều tài liệu mở rộng hơn về Quản lý bộ nhớ ứng dụng của bạn bao gồm nhiều tài liệu ở đây và cập nhật hơn với trạng thái của Android.

Điều đầu tiên có lẽ là đọc phần cuối của bài viết này có một số thảo luận về cách quản lý bộ nhớ trên Android:

Thay đổi API dịch vụ bắt đầu với Android 2.0

Bây giờ ActivityManager.getMemoryInfo()là API cấp cao nhất của chúng tôi để xem xét việc sử dụng bộ nhớ tổng thể. Điều này chủ yếu là để giúp một ứng dụng đánh giá mức độ gần của hệ thống để không còn bộ nhớ cho các quy trình nền, do đó cần phải bắt đầu tiêu diệt các quy trình cần thiết như dịch vụ. Đối với các ứng dụng Java thuần túy, điều này sẽ ít được sử dụng, vì giới hạn vùng heap Java có một phần để tránh một ứng dụng không thể làm căng thẳng hệ thống đến thời điểm này.

Ở cấp độ thấp hơn, bạn có thể sử dụng API gỡ lỗi để nhận thông tin cấp độ hạt nhân thô về việc sử dụng bộ nhớ: android.os.Debug.MemoryInfo

Lưu ý bắt đầu với 2.0 cũng có API ActivityManager.getProcessMemoryInfo, để có được thông tin này về một quy trình khác: ActivityManager.getProcessMemoryInfo (int [])

Điều này trả về cấu trúc MemoryInfo cấp thấp với tất cả các dữ liệu này:

    /** 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;

Nhưng như những gì khác biệt là giữa Pss, PrivateDirtySharedDirty... cũng tại những niềm vui bắt đầu.

Rất nhiều bộ nhớ trong Android (và các hệ thống Linux nói chung) thực sự được chia sẻ qua nhiều quy trình. Vì vậy, bao nhiêu bộ nhớ mà một quá trình sử dụng là thực sự không rõ ràng. Thêm vào đầu trang phân trang đó ra đĩa (huống chi là trao đổi mà chúng ta không sử dụng trên Android) và nó thậm chí còn chưa rõ ràng.

Do đó, nếu bạn lấy tất cả RAM vật lý thực sự được ánh xạ vào từng quy trình và cộng tất cả các quy trình, có thể bạn sẽ kết thúc với số lượng lớn hơn nhiều so với tổng RAM thực tế.

Các Psssố là một thước đo các tính kernel mà sẽ đưa vào chia sẻ bộ nhớ tài khoản - về cơ bản mỗi trang của RAM trong một quá trình được thu nhỏ bằng một tỷ số giữa số quy trình khác cũng sử dụng trang đó. Bằng cách này, bạn có thể (về lý thuyết) cộng pss trên tất cả các quy trình để xem tổng RAM họ đang sử dụng và so sánh pss giữa các quy trình để có được ý tưởng sơ bộ về trọng lượng tương đối của chúng.

Một số liệu thú vị khác ở đây là PrivateDirty, về cơ bản là lượng RAM bên trong quá trình không thể phân trang vào đĩa (nó không được hỗ trợ bởi cùng một dữ liệu trên đĩa) và không được chia sẻ với bất kỳ quy trình nào khác. Một cách khác để xem xét điều này là RAM sẽ có sẵn cho hệ thống khi quá trình đó biến mất (và có thể nhanh chóng bị chìm vào bộ nhớ cache và các ứng dụng khác của nó).

Đó là khá nhiều API SDK cho việc này. Tuy nhiên, có nhiều hơn bạn có thể làm như một nhà phát triển với thiết bị của bạn.

Sử dụng adb, có rất nhiều thông tin bạn có thể nhận được về việc sử dụng bộ nhớ của một hệ thống đang chạy. Một phổ biến là lệnh adb shell dumpsys meminfosẽ đưa ra một loạt thông tin về việc sử dụng bộ nhớ của mỗi quy trình Java, có chứa thông tin trên cũng như nhiều thứ khác. Bạn cũng có thể giải quyết tên hoặc pid của một quy trình duy nhất để xem, ví dụ, adb shell dumpsys meminfo systemđưa cho tôi quy trình hệ thống:

** MEMINFO trong pid 890 [hệ thống] **
                    tổng cộng dalvik khác
            kích thước: 10940 7047 N / A 17987
       phân bổ: 8943 5516 N / A 14459
            miễn phí: 336 1531 N / A 1867
           (Pss): 4585 9282 11916 25783
  (chia sẻ bẩn): 2184 3596 916 6696
    (bẩn): 4504 5956 7456 17916

 Các đối tượng
           Lượt xem: 149 Lượt xem: 4
     AppContexts: 13 Hoạt động: 0
          Tài sản: 4 Tài sản quản lý: 4
   Chất kết dính cục bộ: 141 Chất kết dính proxy: 158
Người nhận tử vong: 49
 Ổ cắm OpenSSL: 0

 SQL
            đống: 205 dbFiles: 0
       numPager: 0 inactivePageKB: 0
    activePageKB: 0

Phần trên cùng là một trong những chính, nơi sizelà tổng kích thước trong không gian địa chỉ của một đống Đặc biệt, allocatedlà kb phân bổ thực tế rằng đống nghĩ nó có, freelà kb còn lại giải phóng đống có cho bổ sung cân đối, và psspriv dirtyđều giống nhau như đã thảo luận trước khi cụ thể đến các trang được liên kết với mỗi đống.

Nếu bạn chỉ muốn xem việc sử dụng bộ nhớ trong tất cả các quy trình, bạn có thể sử dụng lệnh adb shell procrank. Đầu ra của điều này trên cùng một hệ thống trông giống như:

  PID Vss Rss Pss Sử dụng cmdline
  890 84456K 48668K 25850K 21284K hệ thống máy chủ
 1231 50748K 39088K 17587K 13792K com.android.launcher2
  947 34488K 28528K 10834K 9308K com.android.wallapers
  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
  Hợp tử 888 25728K 25724K 5774K 3668K
  977 24100K 24096K 5667K 4340K android. Process.acore
...
   59 336K 332K 99K 92K / hệ thống / thùng / lượt cài đặt
   60 396K 392K 93K 84K / hệ thống / thùng / kho khóa
   51 280K 276K 74K 68K / hệ thống / thùng / nhân viên phục vụ
   54 256K 252K 69K 64K / hệ thống / thùng / gỡ lỗi

Ở đây Vss, Rsscác cột và các cột về cơ bản là nhiễu (đây là không gian địa chỉ thẳng và mức sử dụng RAM của một quy trình, trong đó nếu bạn thêm mức sử dụng RAM trên các quy trình, bạn sẽ nhận được một số lượng lớn một cách lố bịch).

Psslà như chúng ta đã thấy trước đây, và UssPriv Dirty.

Điều thú vị cần lưu ý ở đây: PssUsshơi khác (hoặc hơn một chút) khác với những gì chúng ta đã thấy meminfo. Tại sao vậy? Vâng procrank sử dụng một cơ chế nhân khác để thu thập dữ liệu của nó so với meminfothực tế và chúng cho kết quả hơi khác nhau. Tại sao vậy? Thành thật mà nói tôi không có manh mối. Tôi tin rằng procrankcó thể chính xác hơn ... nhưng thực sự, điều này chỉ để lại quan điểm: "lấy bất kỳ thông tin bộ nhớ nào bạn nhận được bằng một hạt muối; thường là một hạt rất lớn."

Cuối cùng, có lệnh adb shell cat /proc/meminfođưa ra một bản tóm tắt về việc sử dụng bộ nhớ tổng thể của hệ thống. Có rất nhiều dữ liệu ở đây, chỉ một vài con số đầu tiên đáng để thảo luận (và những con số còn lại được ít người hiểu và câu hỏi của tôi về những người đó về chúng thường dẫn đến những giải thích mâu thuẫn):

MemTotal: 395144 kB
MemFree: 184936 kB
Bộ đệm: 880 kB
Đã lưu: 84104 kB
Hoán đổi: 0 kB

MemTotal là tổng dung lượng bộ nhớ khả dụng cho kernel và dung lượng người dùng (thường ít hơn RAM vật lý thực tế của thiết bị, vì một số RAM đó là cần thiết cho radio, bộ đệm DMA, v.v.).

MemFreelà dung lượng RAM hoàn toàn không được sử dụng. Con số bạn thấy ở đây rất cao; thông thường trên hệ thống Android, đây sẽ chỉ là một vài MB, vì chúng tôi cố gắng sử dụng bộ nhớ khả dụng để duy trì hoạt động của các quy trình

Cachedlà RAM được sử dụng cho bộ đệm hệ thống tập tin và những thứ khác. Các hệ thống điển hình sẽ cần phải có 20 MB hoặc hơn để tránh tình trạng phân trang xấu; Trình diệt bộ nhớ Android được điều chỉnh cho một hệ thống cụ thể để đảm bảo rằng các tiến trình nền bị hủy trước khi RAM được lưu trữ quá nhiều bởi chúng dẫn đến việc phân trang như vậy.


1
Hãy xem pixelbeat.org/scripts/ps_mem.py sử dụng các kỹ thuật được đề cập ở trên để hiển thị RAM đã sử dụng cho các chương trình
pixelbeat

17
Viết rất hay! Tôi đã viết một bài về quản lý bộ nhớ và sử dụng các công cụ khác nhau để kiểm tra việc sử dụng heap của bạn ở đây macgyverdev.blogspot.com/2011/11/ chủ nếu có ai thấy nó hữu ích.
Johan Norén

3
Chính xác thì hai cột "dalvik" là "bản địa" là gì?
dacongy

1
Chính xác thì "bản địa" "dalvik" "khác" là gì? Trong ứng dụng của tôi, "khác" là rất lớn? Làm thế nào tôi có thể giảm nó?
hạ cánh

Tôi có thể sử dụng "dumpsys adb shell meminfo", nhưng "adb shell procrank” cho tôi biết.. "/ System / bin / sh: procrank: not found" Tôi không có một clue.Wish bạn có thể giúp tôi
Hugo

79

Có, bạn có thể lấy thông tin bộ nhớ theo chương trình và quyết định có thực hiện công việc đòi hỏi nhiều bộ nhớ hay không.

Nhận VM Heap Size bằng cách gọi:

Runtime.getRuntime().totalMemory();

Nhận bộ nhớ VM được phân bổ bằng cách gọi:

Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

Nhận giới hạn kích thước heap VM bằng cách gọi:

Runtime.getRuntime().maxMemory()

Nhận bộ nhớ phân bổ riêng bằng cách gọi:

Debug.getNativeHeapAllocatedSize();

Tôi đã tạo một ứng dụng để tìm ra hành vi OutOfMemoryError và theo dõi việc sử dụng bộ nhớ.

https://play.google.com/store/apps/details?id=net.coocood.oomresearch

Bạn có thể lấy mã nguồn tại https://github.com/coocood/oom-research


7
Liệu thời gian chạy này sẽ trả về việc sử dụng bộ nhớ theo quy trình hiện tại hay toàn bộ hệ thống?
Mahendran

1
@mahemadhi từ phương thức JavaDoc của TotalMemory () "Trả về tổng dung lượng bộ nhớ có sẵn cho chương trình đang chạy"
Alex

Đây không phải là một câu trả lời chính xác cho câu hỏi. Câu trả lời không phải là về một ứng dụng cụ thể.
Amir Rezazadeh

52

Đây là một công việc đang tiến triển, nhưng đây là điều tôi không hiểu:

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");
    }
}

Tại sao PID không được ánh xạ tới kết quả trong ActivityManager.getProcessMemoryInfo ()? Rõ ràng bạn muốn làm cho dữ liệu kết quả có ý nghĩa, vậy tại sao Google làm cho nó rất khó để tương quan kết quả? Hệ thống hiện tại thậm chí không hoạt động tốt nếu tôi muốn xử lý toàn bộ việc sử dụng bộ nhớ vì kết quả trả về là một mảng các đối tượng android.os.Debug.MemoryInfo, nhưng không có đối tượng nào thực sự cho bạn biết chúng có liên quan gì đến chúng. Nếu bạn chỉ đơn giản vượt qua trong một mảng của tất cả các pids, bạn sẽ không có cách nào để hiểu kết quả. Theo tôi hiểu, nó được sử dụng, nó khiến cho việc truyền nhiều hơn một pid cùng một lúc trở nên vô nghĩa, và nếu đó là trường hợp, tại sao làm cho nó hoạt động như vậy thì trình quản lý.getProcessMemoryInfo () chỉ mất một mảng int?


2
Chúng có khả năng theo thứ tự giống như mảng đầu vào.
taer

2
Đó dường như là một cách rất không trực quan để làm việc. Vâng, đó có lẽ là trường hợp, nhưng làm thế nào là OOP?
Ryan Beesley

6
API được thiết kế cho hiệu quả, không dễ sử dụng hoặc đơn giản. Đây không phải là thứ mà 99% ứng dụng nên chạm vào, vì vậy hiệu quả là mục tiêu thiết kế quan trọng nhất.
hackbod

2
Đủ công bằng. Tôi đang cố gắng viết một công cụ nội bộ để theo dõi việc sử dụng bộ nhớ cho một hoặc nhiều ứng dụng chúng tôi đang viết. Do đó, tôi đang tìm cách để thực hiện giám sát này trong khi tác động ít nhất đến các quy trình khác, nhưng vẫn chi tiết với kết quả nhất có thể (xử lý hậu kỳ). Lặp lại các quy trình và sau đó thực hiện các cuộc gọi cho mỗi quy trình dường như không hiệu quả, giả sử có một số chi phí cho mỗi cuộc gọi .getProcessMemoryInfo. Nếu mảng trả về được đảm bảo theo cùng thứ tự với cuộc gọi, tôi sẽ xử lý kết quả một cách mù quáng và chỉ giả sử tính chẵn lẻ.
Ryan Beesley

5
Đây là một vấn đề nhỏ, nhưng đối với Nhật ký, không cần thiết phải thêm một nguồn cấp dữ liệu, được xử lý cho bạn.
ThomasW

24

Hackbod là một trong những câu trả lời hay nhất về Stack Overflow. Nó ném ánh sáng vào một chủ đề rất tối. Nó đã giúp tôi rất nhiều.

Một tài nguyên thực sự hữu ích khác là video phải xem này: Google I / O 2011: Quản lý bộ nhớ cho các ứng dụng Android


CẬP NHẬT:

Thống kê quy trình, một dịch vụ để khám phá cách ứng dụng của bạn quản lý bộ nhớ được giải thích tại bài đăng trên blog Chỉ số quy trình: Hiểu cách ứng dụng của bạn sử dụng RAM của Dianne Hackborn:


19

Android Studio 0.8.10+ đã giới thiệu một công cụ cực kỳ hữu ích có tên Memory Monitor .

nhập mô tả hình ảnh ở đây

Những gì nó tốt cho:

  • Hiển thị bộ nhớ khả dụng và được sử dụng trong biểu đồ và các sự kiện thu gom rác theo thời gian.
  • Nhanh chóng kiểm tra xem sự chậm chạp của ứng dụng có thể liên quan đến các sự kiện thu gom rác quá mức hay không.
  • Nhanh chóng kiểm tra xem sự cố ứng dụng có thể liên quan đến việc hết bộ nhớ hay không.

nhập mô tả hình ảnh ở đây

Hình 1. Buộc một sự kiện GC (Bộ sưu tập rác) trên Trình theo dõi bộ nhớ Android

Bạn có thể có nhiều thông tin tốt về mức tiêu thụ thời gian thực RAM của ứng dụng bằng cách sử dụng nó.


16

1) Tôi đoán là không, ít nhất là không phải từ Java.
2)

ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo mi = new MemoryInfo();
activityManager.getMemoryInfo(mi);
Log.i("memory free", "" + mi.availMem);

1
thay đổi thành (ActivityManager ActivityManager = (ActivityManager) getSystemService (ACTIVITY_SERVICE);) thay vì (ActivityManager ActivityManager = = (ActivityManager) getSystemService (ACTIVITY_SERVICE);)
Rajkamal

7

Chúng tôi phát hiện ra rằng tất cả các cách tiêu chuẩn để có được tổng bộ nhớ của quy trình hiện tại có một số vấn đề.

  • Runtime.getRuntime().totalMemory(): chỉ trả về bộ nhớ JVM
  • ActivityManager.getMemoryInfo(), Process.getFreeMemory()Và bất cứ điều gì khác dựa trên /proc/meminfo- trở về thông tin bộ nhớ về tất cả các quá trình kết hợp (ví dụ android_util_Process.cpp )
  • Debug.getNativeHeapAllocatedSize()- chỉ sử dụng mallinfo()thông tin trả về phân bổ bộ nhớ được thực hiện bởi malloc()và chỉ các chức năng liên quan (xem android_os_Debug.cpp )
  • Debug.getMemoryInfo()- thực hiện công việc nhưng quá chậm. Mất khoảng 200ms trên Nexus 6 cho một cuộc gọi. Chi phí hoạt động làm cho chức năng này trở nên vô dụng đối với chúng tôi khi chúng tôi gọi nó thường xuyên và mọi cuộc gọi đều khá đáng chú ý (xem android_os_Debug.cpp )
  • ActivityManager.getProcessMemoryInfo(int[])- gọi Debug.getMemoryInfo()nội bộ (xem ActivityManagerService.java )

Cuối cùng, chúng tôi đã kết thúc bằng cách sử dụng mã sau đây:

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;

Nó trả về số liệu VmRSS . Bạn có thể tìm thêm chi tiết về nó ở đây: một , haiba .


PS Tôi nhận thấy rằng chủ đề vẫn còn thiếu một đoạn mã thực tế và đơn giản về cách ước tính mức sử dụng bộ nhớ riêng của quy trình nếu hiệu suất không phải là một yêu cầu quan trọng:

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;


1

Có rất nhiều câu trả lời ở trên chắc chắn sẽ giúp bạn nhưng (sau 2 ngày đủ khả năng và nghiên cứu về các công cụ bộ nhớ adb) Tôi nghĩ rằng tôi có thể giúp với ý kiến của mình .

Như Hackbod nói: Do đó, nếu bạn lấy tất cả RAM vật lý thực sự được ánh xạ vào từng quy trình và cộng tất cả các quy trình, có thể bạn sẽ kết thúc với số lượng lớn hơn nhiều so với tổng RAM thực tế. vì vậy không có cách nào bạn có thể có được số lượng bộ nhớ chính xác cho mỗi quá trình.

Nhưng bạn có thể đến gần nó bằng một số logic..và tôi sẽ nói như thế nào ..

Có một số API như android.os.Debug.MemoryInfoActivityManager.getMemoryInfo()được đề cập ở trên mà bạn có thể đã được đọc và sử dụng nhưng tôi sẽ nói về cách khác

Vì vậy, trước tiên bạn cần phải là người dùng root để nó hoạt động. Nhận được vào giao diện điều khiển với đặc quyền gốc bằng cách thực hiện sutrong quá trình và nhận được nó output and input stream. Sau đó chuyển id\n (enter) trong ouputstream và ghi nó vào quá trình đầu ra, Nếu sẽ nhận được một luồng đầu vào có chứa uid=0, bạn là người dùng root.

Bây giờ đây là logic mà bạn sẽ sử dụng trong quá trình trên

Khi bạn nhận được dòng thông tin của quá trình, bạn sẽ ra lệnh (procrank, dumpsys meminfo, v.v.) \nthay vì id và lấy nó inputstreamvà đọc, lưu trữ luồng theo byte [], char [] vv .. sử dụng raw thô..và bạn xong rồi !!!!!

sự cho phép

<uses-permission android:name="android.permission.FACTORY_TEST"/>

Kiểm tra nếu bạn là người dùng root:

// 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
   } 
}

Thực hiện lệnh của bạn với 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();
 }
}

logcat: kết quả

Bạn nhận được một dữ liệu thô trong một chuỗi từ bảng điều khiển thay vì trong một số trường hợp từ bất kỳ API nào, rất phức tạp để lưu trữ vì bạn sẽ cần phải tách nó theo cách thủ công .

Đây chỉ là một thử, xin vui lòng gợi ý cho tôi nếu tôi bỏ lỡ điều gì đó

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.