1, a emergência da situação ANR
Satisfaz o seguinte caso o sistema solicitará a ANR pop
eventos de entrada (chave e toque eventos) não foi processado dentro dos 5S;
(método onRecieve ()) eventos BroadcastReceiver dentro do tempo especificado não processados (broadcast primeiro plano para os 10s, transmissão bastidores para os anos 60);
Serviço de primeiro plano 20s 200s fundo não completou a inicialização ;
o ContentProvider a publicar () não ser concluída dentro de 10s.
Em circunstâncias normais que causou o thread principal está bloqueada.
2. O princípio da ANR
Nenhuma resposta a uma entrada de um processo de exemplo (com base no código 9.0):
ANR pop-up posição da caixa de diálogo e de classe handleShowAnrUi finais AppErrors de método AMS mesmo diretório (). Essa classe é usada para lidar com uma variedade de erro ocorreu no programa, não só a ANR, esta classe também forçou processo Bater.
// base/core/java/com/android/server/am/AppErrors.java
void handleShowAnrUi(Message msg) {
Dialog dialogToShow = null;
synchronized (mService) {
AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
// ...
Intent intent = new Intent("android.intent.action.ANR");
if (!mService.mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
}
mService.broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
if (mService.canShowErrorDialogs() || showBackground) {
dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
proc.anrDialog = dialogToShow;
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.CANT_SHOW);
// Just kill the app if there is no dialog to be shown.
mService.killAppAtUsersRequest(proc, null);
}
}
// If we've created a crash dialog, show it without the lock held
if (dialogToShow != null) {
dialogToShow.show();
}
}
No entanto, chamadas a partir do local de ocorrência para ANR aqui para passar por um monte de classes e métodos. ANR é inicialmente jogado na InputDispatcher.cpp no. Nós podemos definir constantes para encontrar o local onde o gatilho inicial:
// native/services/inputflinger/InputDispatcher.cpp
constexpr nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
A partir da posição desta classe será acionado atravessou camadas de InputManagerService alcance
// base/services/core/java/com/android/server/input/InputManagerService.java
private long notifyANR(InputApplicationHandle inputApplicationHandle,
InputWindowHandle inputWindowHandle, String reason) {
return mWindowManagerCallbacks.notifyANR(
inputApplicationHandle, inputWindowHandle, reason);
}
mWindowManagerCallbacks aqui é InputMonitor:
// base/services/core/java/com/android/server/wm/InputMonitor.java
public long notifyANR(InputApplicationHandle inputApplicationHandle,
InputWindowHandle inputWindowHandle, String reason) {
// ... 略
if (appWindowToken != null && appWindowToken.appToken != null) {
final AppWindowContainerController controller = appWindowToken.getController();
final boolean abort = controller != null
&& controller.keyDispatchingTimedOut(reason,
(windowState != null) ? windowState.mSession.mPid : -1);
if (!abort) {
return appWindowToken.mInputDispatchingTimeoutNanos;
}
} else if (windowState != null) {
try {
// 使用 AMS 的方法
long timeout = ActivityManager.getService().inputDispatchingTimedOut(
windowState.mSession.mPid, aboveSystem, reason);
if (timeout >= 0) {
return timeout * 1000000L; // nanoseconds
}
} catch (RemoteException ex) {
}
}
return 0; // abort dispatching
}
No método acima é chamado e, em seguida, volta para o AMS inputDispatchingTimedOut () método continua a processo e, eventualmente, inputDispatchingTimedOut () método será passado para os AppErrors evento
// base/services/core/java/com/android/server/am/ActivityManagerService.java
public boolean inputDispatchingTimedOut(final ProcessRecord proc,
final ActivityRecord activity, final ActivityRecord parent,
final boolean aboveSystem, String reason) {
// ...
if (proc != null) {
synchronized (this) {
if (proc.debugging) {
return false;
}
if (proc.instr != null) {
Bundle info = new Bundle();
info.putString("shortMsg", "keyDispatchingTimedOut");
info.putString("longMsg", annotation);
finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
return true;
}
}
mHandler.post(new Runnable() {
@Override
public void run() {
// 使用 AppErrors 继续处理
mAppErrors.appNotResponding(proc, activity, parent, aboveSystem, annotation);
}
});
}
return true;
}
Quando os eventos são passados para os AppErrors, ele vai ajudar Handler vai processar a mensagem chama o método original e caixa de diálogo pop-up.
Referência: "princípio ANR Android de análise"
3, solução ANR
Análise das causas e princípios da ANR acima, vamos analisar a forma de resolver o ANR.
1. Use adb log de exportação ANR e analisar
ANR sistema ocorre quando a gravação de informação e arquivo ANR /data/anr/traces.txt armazenada no (relativamente novo no sistema é armazenado em ambos / data / ANR / anr_ arquivo *). Nós podemos usar as seguintes maneiras de exportá-lo para o seu computador, a fim de ANR razão gerado para análise:
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
Quando a análise I ANR ao usar o try comando ANR aos registros de exportação surgiram Permissão negada. Após este tempo, você pode exportar o telefone depois Root, ou tentar modificar as permissões para ler e escrever arquivos, ou optar por exportar os logs para o sdcard no modo de desenvolvedor sdcard e, em seguida, enviar os logs para o terminal de computador para visualização
análise DDMS 2. Use traceview
DDMS abrir no AS, ou para usar o diretório de instalação do SDK diretório monitor.bat abertas DDMs ferramentas abaixo.
Use as ferramentas TraceView pode consultar o artigo: "análise de desempenho TraceView Android do uso (aplicação de análise demorada)"
Esta ideia posicionamento ANR é: use as informações de localização para localizar TraceView método demorado chamada operação demorada.
informações:
- "documentos oficiais ANR".
- "TraceView Android análise de desempenho do uso (aplicação da análise demorada)"
3. Use projeto de código aberto ANR-WatchDog detecta ANR
endereço projeto é Github-ANR-WatchDog
O princípio do projeto: criar uma linha de detecção que continuam a segmento interface do usuário postar uma tarefa, e depois dormir um tempo fixo, como antes e novamente após o segmento a tarefa de detectar se ou não para executar o cargo, assumindo que a tarefa não está em execução, geração ANRError, e terminar o processo.
cena 4. ANR Comum
I / O bloqueio de
congestionamento da rede
multithreading impasse
devido aos resultados do método em um ciclo de programação reativa a morrer
devido a um tempo de execução lógica de negócios é muito longo
5. O método de evitar ANR
segmento interface do usuário apenas na medida do possível, o trabalho associado com a interface do usuário;
; de trabalho (tais como as operações de banco de dados, I / O, operações de rede, etc.), utilizando um processamento segmento de trabalho separada demorado
com Handler para segurar a linha UI interativo e os segmentos de trabalho;
uso RxJava e outras mensagens assíncronas para processar.
Em suma, um princípio é: não no thread principal para fazer a operação demorada.