Pergunta

Comecei a usar o Android StrictMode e descobri que seria ótimo tê -lo sempre em execução durante o desenvolvimento e não apenas em uma filial especial que criei no Git. A razão pela qual fiz isso é o meu requisito de aplicativos para executar com 1.6 ou mais.

Eu li no blog do Android Developer que você pode configurá -lo para ativá -lo por reflexão. Eu estava me perguntando como isso seria realmente e se fosse possível ter isso documentado aqui (ou em outro lugar), em vez de ter todo mundo que deseja usá -lo funcionando.

Foi útil?

Solução 2

Então, eu não queria esperar e decidi fazer o esforço e implementar isso sozinho. Basicamente, ele se resume a envolver o StrictMode em uma classe de wrapper e decidir no tempo de execução via reflexão, se pudermos ativá -lo.

Eu documentei em detalhes Em uma postagem no blog e disponibilizou -o em Github.

Outras dicas

Eu li a postagem do blog de Manfred, mas não funciona se você definir Versão da plataforma de destino menor que 2.3 Porque StrictMode.enableDefaults(); O método não está disponível.

Aqui está minha solução que depende totalmente da reflexão e não gera erros de compilação:

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

Eu vi sua postagem no blog. Como você só deseja configurar o StrictMode no máximo uma vez por arquivo java, faria algum sentido simplificar o código para solicitar a configuração da seguinte maneira?

Aqui está um StrictModewrapper alternativo:

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

Do seu código, você só precisa fazer o seguinte:

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

Onde isto é o contexto local, como sua atividade ou aplicação ou qualquer outra coisa. Isso parece funcionar para o Android pré-2.3 e também fornece o poder de usar os outros métodos das classes do construtor para configurar exatamente o que você gostaria.

Reuni outra variação do tema acima, que descrevi em uma postagem no blog aqui. A principal diferença na minha abordagem é que ela também fornece invólucros para os objetos de política de disco e VM, para que você possa facilmente agradar o código de ingresso strictmode com alterações de política temporária. O feedback é bem -vindo.

Para o código de pixels, também adicionei isso (com base no exemplo do 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);

Defina o Android manifestado a algo assim.

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

Use o código abaixo no método 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);

}

Nota: Desative o aviso, pois você já está verificando qual versão do Android usará este código.

Este código será ativado se a versão Android for maior que o Android 2.2

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top