StrictMode для более низких версий платформы

Я начал использовать Android StrictMode и обнаружил, что было бы здорово, если бы он всегда работал во время разработки, а не только в специальной ветке, которую я создал в git. Причина, по которой я это сделал, заключается в том, что мои приложения должны работать с 1.6 и выше.

Я читал в блоге разработчиков Android, что вы можете настроить его так, чтобы активировать его через отражение. Мне просто интересно, как это будет выглядеть на самом деле, и возможно ли задокументировать это здесь (или где-то еще), вместо того, чтобы каждый, кто хочет его использовать, работал сам.


person Manfred Moser    schedule 06.01.2011    source источник
comment
если я не получу ответа здесь, я сам разберусь с этим, когда у меня будет немного времени, чтобы сделать это ... хотя в данный момент мне нужно подготовиться к andevcon ..   -  person Manfred Moser    schedule 06.01.2011


Ответы (6)


Я читал сообщение в блоге Манфреда, но оно не работает, если вы установите версию целевой платформы ниже 2.3, потому что метод StrictMode.enableDefaults(); недоступен.

Вот мое решение, которое полностью полагается на отражение и не генерирует ошибок компиляции:

    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);
    }
person pixel    schedule 15.11.2011
comment
Реализация находится на github, проверена и используется многими людьми. Это работает просто отлично. Я использую это каждый день. Но да... если вам нужна цель ниже 2.3, ваш трюк тоже сработает. - person Manfred Moser; 15.11.2011
comment
@ManfredMoser Единственная причина, по которой я это опубликовал, - необходимость поддерживать цели ниже 2.3. Ваше решение хорошее, но в данном конкретном случае оно не работает. - person pixel; 16.11.2011

Поэтому я не хотел ждать и решил приложить усилия и реализовать это самостоятельно. В основном это сводится к обертыванию StrictMode в класс-оболочку и решению во время выполнения с помощью отражения, можем ли мы его активировать.

Я подробно задокументировал это в сообщении блога и сделал его доступным в github.

person Manfred Moser    schedule 07.01.2011
comment
@bla ... пожалуйста, удалите свой отрицательный голос .. Я исправил ссылку .. ей 5 лет. Вещи двигаются.. - person Manfred Moser; 30.03.2016
comment
Спасибо Манфред; понижение, как правило, является эффективным способом исправления ссылок;). Следует проверить наличие классов MorseFlashApplication и StrictModeWrapper. - person blacelle; 30.03.2016

Я видел твой пост в блоге. Поскольку вы хотите настроить StrictMode не более одного раза для каждого файла Java, имеет ли смысл упростить код для вызова настройки следующим образом?

Вот альтернативный StrictModeWrapper:

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

Из вашего кода вам нужно сделать следующее:

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

где this — это локальный контекст, например ваша активность или приложение или что-то еще. Кажется, это работает для Android до версии 2.3, а также дает вам возможность использовать другие методы классов Builder для настройки StrictMode именно так, как вы хотите.

person Dave MacLean    schedule 18.01.2011
comment
Да... это тоже будет работать и может быть немного короче в том смысле, что он даже не пытается использовать отражение, а просто выполняет полную инициализацию. Однако этот способ менее гибкий. Однако верно то, что вы хотите сделать это только один раз. Я просто делаю это в onCreate класса приложения, который в любом случае уже является синглтоном. - person Manfred Moser; 18.01.2011
comment
Однажды я увидел ответ Дайанны Хакборн в группе разработчиков Android, в которой рекомендовалось не расширять приложение, если в этом нет абсолютной необходимости. Политики применяются к потокам, поэтому вы можете инициализировать StrictMode в onCreate() вашей активности запуска, и тогда это должно быть так же хорошо, как инициализация из приложения, поскольку она применялась бы к основному потоку. Если, конечно, вы не запускаете дополнительные потоки, которые хотите отслеживать, но вам также необходимо настроить StrictMode для этих потоков, даже если вы инициализировали приложение. - person Dave MacLean; 18.01.2011
comment
да. Это еще одна возможность. Я также видел эту рекомендацию от Дайанны, но МНОГИЕ приложения, которые я вижу, расширяют приложение, и это работает довольно хорошо. Как говорится.. есть много способов содрать шкуру с кота ;-) - person Manfred Moser; 19.01.2011

Я собрал еще один вариант темы, описанной выше, которую описал в своем блоге здесь. Основное отличие моего подхода заключается в том, что он также предоставляет обертки для объектов политики disk и vm, так что вы можете легко ограничить код, нарушающий StrictMode, временными изменениями политики. Обратная связь приветствуется.

person Andy Dennie    schedule 26.09.2011

В код Pixel я также добавил это (на основе примера StrictMode Android API):

            // 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);
person Unbroken    schedule 31.07.2012

Установите манифест Android примерно так.

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

используйте приведенный ниже код в методе 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);

}

Примечание. Отключите предупреждение, так как вы уже проверяете, какая версия Android будет использовать этот код.

этот код будет активирован, если версия Android выше, чем Android 2.2

person PravinDodia    schedule 04.09.2012
comment
Это не будет работать в более старых версиях Android, так как предполагается, что класс StrictMode доступен... что не так. - person Manfred Moser; 04.09.2012
comment
Я использую это на своем Android 2.2 с новым приложением Popup Facebook. Для этого вам нужно выбрать цель, как указано выше в сообщении, в логарифме будет ошибка, если версия Android ниже 2.3, но это будет означать, что есть это мертвый код. - person PravinDodia; 09.09.2012
comment
это правда, но что касается приведенного выше кода, он должен работать теоретически, я не пробовал для 1.1, но да, он точно будет работать для Android 2.1 и выше. - person PravinDodia; 10.09.2012
comment
@ManfredMoser Я не пробовал на Android 1.1, так как у меня нет SDK для Android 1.1, но я пробовал на Android SDK 1.5. тебе надоел код с 1.1? Пожалуйста, дайте мне знать, если вы пробовали это, чтобы я мог соответствующим образом отредактировать свой ответ. - person PravinDodia; 12.09.2012
comment
У меня работает ниже 2.3. Dalvik зарегистрирует ошибку о том, что он не может найти класс StrictMode, но приложение не рухнет. Это произойдет только в том случае, если мы попытаемся использовать класс StrictMode и войти в ветвь IF, но мы этого не делаем. Следовательно, фрагмент РАБОТАЕТ. - person Zsolt Safrany; 25.10.2012