StrictMode para versões da plataforma mais baixa
-
25-09-2019 - |
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.
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