Câu hỏi StrictMode cho các phiên bản nền tảng thấp hơn


Tôi đã bắt đầu sử dụng Android StrictMode và thấy rằng nó sẽ là tuyệt vời để có nó luôn luôn chạy trong quá trình phát triển và không chỉ trên một chi nhánh đặc biệt tôi tạo ra trong git. Lý do tôi làm điều này là yêu cầu ứng dụng của tôi chạy với 1.6 trở lên.

Tôi đọc trên blog nhà phát triển Android mà bạn có thể thiết lập để bạn kích hoạt nó thông qua phản ánh. Tôi chỉ tự hỏi làm thế nào mà thực sự sẽ như thế và nếu nó có thể có thể có tài liệu này ở đây (hoặc ở một nơi khác) hơn là có tất cả mọi người muốn sử dụng nó làm việc ra chính mình.


12
2018-01-06 00:19


gốc


nếu tôi không nhận được một câu trả lời ở đây tôi sẽ tìm ra bản thân mình khi tôi có một chút thời gian để làm điều đó .. cần phải chuẩn bị cho andevcon vào lúc này mặc dù .. - Manfred Moser


Các câu trả lời:


Tôi đã đọc bài đăng trên blog của Manfred nhưng nó không hoạt động nếu bạn đặt phiên bản nền tảng đích thấp hơn 2.3 bởi vì StrictMode.enableDefaults(); phương thức không khả dụng.

Đây là giải pháp của tôi dựa hoàn toàn vào sự phản chiếu và không tạo ra lỗi biên dịch:

    try {
        Class<?> strictModeClass = Class.forName("android.os.StrictMode", true, Thread.currentThread()
                .getContextClassLoader());

        Class<?> threadPolicyClass = Class.forName("android.os.StrictMode$ThreadPolicy", true, Thread
                .currentThread().getContextClassLoader());

        Class<?> threadPolicyBuilderClass = Class.forName("android.os.StrictMode$ThreadPolicy$Builder", true,
                Thread.currentThread().getContextClassLoader());

        Method setThreadPolicyMethod = strictModeClass.getMethod("setThreadPolicy", threadPolicyClass);

        Method detectAllMethod = threadPolicyBuilderClass.getMethod("detectAll");
        Method penaltyMethod = threadPolicyBuilderClass.getMethod("penaltyLog");
        Method buildMethod = threadPolicyBuilderClass.getMethod("build");

        Constructor<?> threadPolicyBuilderConstructor = threadPolicyBuilderClass.getConstructor();
        Object threadPolicyBuilderObject = threadPolicyBuilderConstructor.newInstance();

        Object obj = detectAllMethod.invoke(threadPolicyBuilderObject);

        obj = penaltyMethod.invoke(obj);
        Object threadPolicyObject = buildMethod.invoke(obj);
        setThreadPolicyMethod.invoke(strictModeClass, threadPolicyObject);

    } catch (Exception ex) {
        Log.w(TAG, ex);
    }

9
2017-11-15 15:04



Việc thực hiện là trong github và đã được thử nghiệm và sử dụng bởi nhiều người. Nó hoạt động tốt. Tôi dùng nó mỗi ngày. Nhưng có ... nếu bạn cần mục tiêu dưới 2,3, thủ thuật của bạn sẽ hoạt động tốt. - Manfred Moser
@ManfredMoser Lý do duy nhất tôi đăng nó là cần phải hỗ trợ các mục tiêu thấp hơn 2,3. Giải pháp của bạn là tốt, nhưng trong trường hợp đặc biệt này, nó không hoạt động. - pixel
cảm ơn @ManfredMoser - Luigi Agosti


Vì vậy, tôi không muốn chờ đợi và quyết định thực hiện nỗ lực và thực hiện điều này bản thân mình. Về cơ bản nó tóm tắt để gói StrictMode trong một lớp trình bao bọc và quyết định thời gian chạy qua sự phản chiếu nếu chúng ta có thể kích hoạt nó.

Tôi đã ghi lại chi tiết một cách chi tiết trong một bài đăng trên blog và làm cho nó có sẵn trong github.


8
2018-01-07 08:00



@bla ... vui lòng loại bỏ downvote của bạn .. Tôi cố định liên kết .. đây là 5 tuổi. Mọi thứ di chuyển xung quanh .. - Manfred Moser
Cảm ơn Manfred; một downvote nói chung là một cách hiệu quả để có được các liên kết cố định;). Bạn nên kiểm tra các lớp MorseFlashApplication và StrictModeWrapper. - blacelle


Tôi đã xem bài đăng trên blog của bạn. Vì bạn chỉ muốn thiết lập StrictMode nhiều nhất một lần cho mỗi tệp Java, liệu nó có tạo ra bất kỳ ý nghĩa nào để đơn giản hóa mã để gọi cho thiết lập như sau không?

Đây là một StrictModeWrapper thay thế:

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.StrictMode;

public class StrictModeWrapper {
    public static void init(Context context) {
        // check if android:debuggable is set to true
        int applicationFlags = context.getApplicationInfo().flags;
        if ((applicationFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskReads()
                .detectDiskWrites()
                .detectNetwork()
                .penaltyLog()
                .build());
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects()
                .penaltyLog()
                .penaltyDeath()
                .build());
        }
    }
}

Từ mã của bạn, bạn chỉ cần làm như sau:

try {
    StrictModeWrapper.init(this);
}
catch(Throwable throwable) {
    Log.v("StrictMode", "... is not available. Punting...");
}

Ở đâu điều này là ngữ cảnh cục bộ, chẳng hạn như Hoạt động hoặc Ứng dụng của bạn hoặc bất kỳ điều gì. Điều này dường như làm việc cho Android trước 2.3, và cũng cung cấp cho bạn sức mạnh của việc sử dụng các phương thức khác của các lớp Builder để cấu hình chính xác StrictMode như bạn muốn.


7
2018-01-18 03:45



Có .. điều đó sẽ làm việc quá và có thể là một chút ngắn hơn trong ý nghĩa rằng nó thậm chí không cố gắng sử dụng sự phản ánh nhưng chỉ làm đầy đủ trên init. Nó là một chút ít linh hoạt theo cách này mặc dù. Tuy nhiên, bạn chỉ muốn làm điều này một lần. Tôi chỉ làm điều đó trong onCreate của lớp ứng dụng, đó là một singleton đã được anyway .. - Manfred Moser
Tôi đã từng thấy một câu trả lời từ Dianne Hackborn trên nhóm nhà phát triển Android đề xuất chống lại việc mở rộng ứng dụng nếu nó không thực sự cần thiết. Các chính sách áp dụng cho các chủ đề, vì vậy bạn có thể khởi tạo StrictMode trong onCreate () của hoạt động launcher của bạn, và sau đó nó sẽ tốt như khởi tạo từ ứng dụng vì nó sẽ áp dụng cho chủ đề chính. Trừ khi tất nhiên bạn kích hoạt các chủ đề bổ sung mà bạn muốn theo dõi, nhưng bạn cần thiết lập StrictMode trên các chủ đề đó ngay cả khi bạn đã khởi tạo từ Ứng dụng. - Dave MacLean
Vâng. Đó là một khả năng khác. Tôi cũng thấy rằng đề nghị từ Dianne, nhưng nhiều ứng dụng tôi thấy mở rộng ứng dụng và nó hoạt động khá tốt theo cách đó. Giống như họ nói .. có rất nhiều cách để da một con mèo ;-) - Manfred Moser


Tôi đã cùng nhau đưa ra một biến thể khác về chủ đề trên, mà tôi đã phác thảo trong một bài đăng trên blog đây. Sự khác biệt chính trong cách tiếp cận của tôi là nó cũng cung cấp các trình bao bọc cho các đối tượng chính sách đĩa và vm, do đó bạn dễ dàng có thể đặt mã vi phạm StrictMode với các thay đổi chính sách tạm thời. Phản hồi được hoan nghênh.


1
2017-09-26 18:31





Để mã Pixel, tôi cũng đã thêm mã này (dựa trên ví dụ về API Android StrictMode):

            // VM policy
            Class<?> VmPolicyClass = Class.forName("android.os.StrictMode$VmPolicy", true, Thread.currentThread().getContextClassLoader());

            Class<?> VmPolicyBuilderClass = Class.forName("android.os.StrictMode$VmPolicy$Builder", true, Thread.currentThread().getContextClassLoader());

            Method setVmPolicyMethod = strictModeClass.getMethod("setVmPolicy", VmPolicyClass);

            Method detectLeakedSqlLiteObjectsMethod = VmPolicyBuilderClass.getMethod("detectLeakedSqlLiteObjects");
            Method detectLeakedClosableObjectsMethod = null; 
            try
            {
                detectLeakedClosableObjectsMethod = VmPolicyBuilderClass.getMethod("detectLeakedClosableObjects");
            }
            catch (Exception e) {}
            Method penaltyLogMethod = VmPolicyBuilderClass.getMethod("penaltyLog");
            Method penaltyDeathMethod = VmPolicyBuilderClass.getMethod("penaltyDeath");
            Method VmbuildMethod = VmPolicyBuilderClass.getMethod("build");

            Constructor<?> VmPolicyBuilderConstructor = VmPolicyBuilderClass.getConstructor();
            Object VmPolicyBuilderObject = VmPolicyBuilderConstructor.newInstance();

            Object Vmobj = detectLeakedSqlLiteObjectsMethod.invoke(VmPolicyBuilderObject);
            if (detectLeakedClosableObjectsMethod != null) Vmobj = detectLeakedClosableObjectsMethod.invoke(Vmobj);
            Vmobj = penaltyLogMethod.invoke(Vmobj);
            Vmobj = penaltyDeathMethod.invoke(Vmobj);

            Object VmPolicyObject = VmbuildMethod.invoke(Vmobj);
            setVmPolicyMethod.invoke(strictModeClass, VmPolicyObject);

1
2017-07-31 20:35





Đặt Tệp kê khai Android thành một cái gì đó như thế này.

< uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" android:maxSdkVersion="16"/ >

sử dụng mã bên dưới trong phương thức onCreate.

int SDK_INT = android.os.Build.VERSION.SDK_INT;

} if (SDK_INT>8){

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

StrictMode.setThreadPolicy(policy);

}

Lưu ý: Tắt cảnh báo vì bạn đã kiểm tra phiên bản Android nào sẽ sử dụng mã này.

Mã này sẽ được kích hoạt nếu phiên bản Android cao hơn Android 2.2


0
2017-09-04 14:55



Điều này sẽ không hoạt động trên các phiên bản Android cũ hơn vì nó giả định lớp StrictMode có sẵn .. đó không phải là trường hợp. - Manfred Moser
Tôi đang sử dụng trên Android 2.2 của tôi với ứng dụng mới Popup Facebook, Đối với điều này bạn phải chọn mục tiêu như đã nêu ở trên trong bài sẽ có lỗi trong logcat nếu phiên bản android thấp hơn 2.3 nhưng đó sẽ là nói rằng có là một mã chết. - PravinDodia
Khi nói về các phiên bản cũ, các giải pháp khác hoạt động trở lại 1.1 ... - Manfred Moser
thats đúng nhưng như xa như các mã trên là có liên quan nó nên làm việc về mặt lý thuyết, tôi đã không cố gắng cho 1,1 nhưng có chắc chắn nó sẽ làm việc cho Android 2.1 trở lên. - PravinDodia
@ManfredMoser Tôi chưa thử trên Android 1.1 vì tôi không có sdk cho android 1.1 nhưng tôi đã thử trên Android SDK 1.5. bạn có mệt mỏi với mã 1.1 không? Xin vui lòng cho tôi biết nếu bạn đã thử nó để tôi có thể chỉnh sửa câu trả lời của tôi cho phù hợp. - PravinDodia