Eu tenho um TransactionTooLargeException
. Não reproduzível. Nos documentos, ele diz
A transação do Fichário falhou porque era muito grande.
Durante uma chamada de procedimento remoto, os argumentos e o valor de retorno da chamada são transferidos como objetos Parcel armazenados no buffer de transação do Fichário. Se os argumentos ou o valor de retorno forem muito grandes para caber no buffer de transação, a chamada falhará e TransactionTooLargeException será lançada.
...
Há dois resultados possíveis quando uma chamada de procedimento remoto lança TransactionTooLargeException. O cliente não pôde enviar sua solicitação ao serviço (provavelmente se os argumentos fossem muito grandes para caber no buffer da transação) ou o serviço não pôde enviar sua resposta de volta ao cliente (provavelmente se o valor de retorno fosse muito grande para caber no buffer de transação).
...
Então, em algum lugar, estou passando ou recebendo argumentos que excedem algum limite desconhecido. Onde?
O stacktrace não mostra nada de útil:
java.lang.RuntimeException: Adding window failed
at android.view.ViewRootImpl.setView(ViewRootImpl.java:548)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
... 16 more
android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Parece estar relacionado com pontos de vista? Como isso está relacionado à chamada de procedimento remoto?
Talvez seja importante: Versão Android: 4.0.3, Dispositivo: HTC One X
Respostas:
Encontrei esse problema e descobri que, quando uma quantidade enorme de dados é trocada entre um serviço e um aplicativo (isso envolve a transferência de muitas miniaturas). Na verdade, o tamanho dos dados estava em torno de 500kb e o tamanho do buffer da transação IPC é definido como 1024KB. Não sei por que excedeu o buffer de transação.
Isso também pode ocorrer quando você passa muitos dados por meio de extras intencionais
Quando você receber essa exceção em seu aplicativo, analise seu código.
Como lidar quando você recebe essa exceção
Se possível, divida a operação grande em pequenos pedaços, por exemplo, em vez de chamar applyBatch () com 1000 operações, chame-a com 100 cada.
Não troque dados enormes (> 1 MB) entre serviços e aplicativos
Eu não sei como fazer isso, mas, Não consulte o Android, que pode retornar dados enormes :-)
fonte
getInstalledApplications
. O que pode ser feito para resolver isso?Se você precisar investigar qual parcela está causando a falha, considere tentar o TooLargeTool .
(Encontrei isso como um comentário do @Max Spencer sob a resposta aceita e foi útil no meu caso.)
fonte
bundle.clear()
Essa não é uma resposta definitiva, mas pode esclarecer as causas de um
TransactionTooLargeException
e ajudar a identificar o problema.Embora a maioria das respostas se refira a grandes quantidades de dados transferidos, vejo essa exceção sendo lançada acidentalmente após rolagem e zoom pesados e abrindo repetidamente um menu giratório do ActionBar. O acidente ocorre ao tocar na barra de ação. (este é um aplicativo de mapeamento personalizado)
Os únicos dados transmitidos parecem ser toques do "Input Dispatcher" para o aplicativo. Eu acho que isso não pode chegar a 1 MB no "Transaction Buffer".
Meu aplicativo está sendo executado em um dispositivo quad core de 1,6 GHz e usa 3 threads para levantamento de peso, mantendo um núcleo livre para o thread da interface do usuário. Além disso, o aplicativo usa o android: largeHeap, tem 10 mb de heap não utilizado restante e tem 100 mb de espaço restante para aumentar o heap. Então, eu não diria que é uma questão de recursos.
A falha é sempre imediatamente precedida por estas linhas:
Que não são necessariamente impressos nessa ordem, mas (tanto quanto eu verifiquei) acontecem no mesmo milissegundo.
E o próprio rastreamento de pilha, para maior clareza, é o mesmo da pergunta:
Investigando o código fonte do android, encontramos as seguintes linhas:
frameworks / base / core / jni / android_util_Binder.cpp:
Para mim, parece que estou atingindo esse recurso não documentado, em que a transação falha por outros motivos que não sejam uma transação muito grande. Eles deveriam ter nomeado
TransactionTooLargeOrAnotherReasonException
.No momento, não resolvi o problema, mas, se encontrar algo útil, atualizarei esta resposta.
update: descobriu-se que meu código vazou alguns descritores de arquivo, cujo número é maximizado no linux (normalmente 1024), e isso parece ter desencadeado a exceção. Afinal, era uma questão de recursos. Eu verifiquei isso abrindo
/dev/zero
1024 vezes, o que resultou em todos os tipos de exceções estranhas nas ações relacionadas à interface do usuário, incluindo a exceção acima, e até mesmo alguns SIGSEGVs. Aparentemente, a falha ao abrir um arquivo / soquete não é algo que é tratado / relatado de maneira muito limpa em todo o Android.fonte
o
TransactionTooLargeException
está nos atormentando há cerca de 4 meses e finalmente resolvemos o problema!O que estava acontecendo era que estamos usando
FragmentStatePagerAdapter
umViewPager
. O usuário paginaria e criaria mais de 100 fragmentos (é um aplicativo de leitura).Embora tenhamos gerenciado os fragmentos corretamente
destroyItem()
, na implementação do AndroidFragmentStatePagerAdapter
há um bug, onde ele mantinha uma referência à seguinte lista:E quando o Android
FragmentStatePagerAdapter
tentar salvar o estado, ele chamará a funçãoComo você pode ver, mesmo se você gerenciar adequadamente os fragmentos da
FragmentStatePagerAdapter
subclasse, a classe base ainda armazenará umFragment.SavedState
para cada fragmento criado. OTransactionTooLargeException
ocorreria quando essa matriz foi despejado para umparcelableArray
eo SO não gostaria que 100+ itens.Portanto, a correção para nós era substituir o
saveState()
método e não armazenar nada"states"
.fonte
@Override public Parcelable saveState() { Bundle bundle = (Bundle) super.saveState(); if (bundle != null) { Parcelable[] states = bundle.getParcelableArray("states"); // Subset only last 3 states if (states != null) states = Arrays.copyOfRange(states, states.length > 3 ? states.length - 3 : 0, states.length - 1); bundle.putParcelableArray("states", states); } else bundle = new Bundle(); return bundle; }
Para aqueles que se decepcionaram amargamente em busca de respostas sobre por que o TransactionTooLargeException aparece, tente verificar quanta informação você salva no estado da instância.
No compile / targetSdkVersion <= 23, temos apenas um aviso interno sobre o tamanho grande do estado salvo, mas nada falha:
Mas em compile / targetSdkVersion> = 24, temos uma verdadeira falha de RuntimeException neste caso:
O que fazer?
Salve os dados no banco de dados local e mantenha apenas os IDs no estado da instância que você pode usar para recuperar esses dados.
fonte
Essa exceção geralmente é lançada quando o aplicativo está sendo enviado para o segundo plano.
Por isso, decidi usar o método Fragment de dados para contornar completamente o
onSavedInstanceStae
ciclo de vida. Minha solução também lida com estados complexos de instância e libera memória o mais rápido possível.Primeiro, criei um Farcement simples para armazenar os dados:
Então, na minha Atividade principal, contorno completamente o ciclo de instâncias salvas e adio a respoinsibilidade ao meu Fragmento de dados. Não há necessidade de usar isso nos próprios fragmentos, pois seu estado é adicionado ao estado da atividade automaticamente):
O que resta é simplesmente exibir a instância salva:
Detalhes completos: http://www.devsbedevin.net/avoiding-transactiontoolargeexception-on-android-nougat-and-up/
fonte
onSavedState()
, o que acontece em muitos casos. A mudança na configuração é uma. Trocar de aplicativo e ir para segundo plano são outra. E tem mais.Não há uma causa específica desse problema. Para mim, na minha classe Fragment, eu estava fazendo isso:
em vez disso:
fonte
É importante entender que o buffer da transação é limitado a 1 MB, independentemente dos recursos ou aplicativos do dispositivo. Esse buffer é usado com todas as chamadas de API que você faz e é compartilhado entre todas as transações que um aplicativo está executando no momento.
Eu acredito que ele também contém algum objeto específico, como parcelas e coisas do tipo
(Parcel.obtain())
, por isso é importante sempre combinar todosobtain()
com arecycle()
.Esse erro pode ocorrer facilmente em chamadas de API que retornam muitos dados, mesmo que os dados retornados sejam menores que 1 MB (se outras transações ainda estiverem em execução).
Por exemplo, a
PackageManager.getInstalledApplication()
chamada retorna uma lista de todos os aplicativos instalados. A adição de sinalizadores específicos permite recuperar muitos dados extras. Se o fizer, é provável que falhe, por isso é recomendável não recuperar nenhum dado extra e recuperá-lo por aplicativo.No entanto, a chamada ainda pode falhar, por isso é importante cercá-la com um
catch
e poder tentar novamente, se necessário.Até onde eu sei, não há solução alternativa para esse problema, exceto tentar novamente e garantir o mínimo de informações possível.
fonte
Eu também recebi essa exceção em um Samsung S3. Eu suspeito que 2 causas principais,
Use o DDMS e observe sua pilha enquanto reproduz seu aplicativo, que fornecerá algumas indicações sobre qual setcontentview está criando o problema.
Copiei todos os drawables em todas as pastas para se livrar do problema 2.
Problema resolvido.
fonte
Adicione isso à sua atividade
Funciona para mim espero que também ajude você
fonte
onCreate()
?Então, para nós, estávamos tentando enviar um objeto muito grande por meio de nossa interface AIDL para um serviço remoto. O tamanho da transação não pode exceder 1 MB. A solicitação é dividida em partes separadas de 512 KB e enviada uma por vez pela interface. Uma solução brutal que eu conheço, mas ei - seu Android :(
fonte
Você limpou seu InstanceState antigo do método onSaveInstanceState e ele funcionará bem. Estou usando o FragmentStatePagerAdapter para o meu viewpager, por isso mantenho abaixo o método Override na atividade pai para limpar InstanceState.
Encontrei esta solução a partir daqui android.os.TransactionTooLargeException no Nougat
fonte
Recentemente, também encontrei um caso interessante ao trabalhar com o provedor de contatos do Android .
Eu precisava carregar fotos dos contatos do banco de dados de contatos internos e, de acordo com a arquitetura do sistema, todos esses dados são entregues por meio de consultas ao provedor de contatos.
Como funciona como um aplicativo separado - todos os tipos de transferência de dados são realizados usando o mecanismo Binder e, portanto, o buffer do Binder entra em jogo aqui.
Meu principal erro foi não fechar os
Cursor
dados com blob obtidos do provedor de contatos, de modo que a memória alocada para o provedor aumentasse e isso inflasse o buffer do fichário até que eu recebesse toneladas de!!!FAILED BINDER TRANSACTION!!!
mensagens na saída do LogCat.Portanto, a idéia principal é que, quando você trabalha com provedores de conteúdo externos e recebe
Cursor
s deles, sempre o fecha quando terminar de trabalhar com eles.fonte
Eu enfrentei o mesmo problema quando tentei enviar bitmap via Intent e, ao mesmo tempo, desdobrei o aplicativo.
Como é descrito neste artigo, insira a descrição do link aqui , acontece quando uma Atividade está em processo de parada, o que significa que a Atividade estava tentando enviar seus Pacotes de estado salvos para o sistema operacional do sistema para manter a segurança para restauração posteriormente (após uma alteração na configuração ou processar a morte), mas um ou mais pacotes enviados foram muito grandes.
Eu o resolvi via hack substituindo onSaveInstanceState na minha atividade:
e comentar chamar super. É um truque sujo, mas está funcionando perfeitamente. O bitmap foi enviado com sucesso sem falhas. Espero que isso ajude alguém.
fonte
No meu caso, recebo TransactionTooLargeException como uma falha secundária depois que a biblioteca nativa travou com o SIGSEGV. A falha da biblioteca nativa não é relatada, por isso só recebo TransactionTooLargeException.
fonte
Eu peguei isso no meu syncadapter ao tentar inserir em massa um grande ContentValues []. Decidi corrigi-lo da seguinte maneira:
fonte
Para mim, também foi o
FragmentStatePagerAdapter
, no entanto, a substituiçãosaveState()
não funcionou. Aqui está como eu o consertei:Ao chamar o
FragmentStatePagerAdapter
construtor, mantenha uma lista separada de fragmentos dentro da classe e adicione um método para remover os fragmentos:Em seguida, no
Activity
, salve aViewPager
posição e chameadapter.removeFragments()
noonSaveInstanceState()
método substituído :Por fim, no
onResume()
método substituído , instancie novamente o adaptador, se não estivernull
. (Se estivernull
, então eleActivity
está sendo aberto pela primeira vez ou após o aplicativo ter sido eliminado pelo Android, no qualonCreate
fará a criação do adaptador.)fonte
Certifique-se de não inserir dados de objeto Intent de tamanho grande. No meu caso, estava adicionando o tamanho da String 500k e iniciando outra atividade. Sempre falhava com essa exceção. Evitei compartilhar dados entre as atividades usando variáveis estáticas das atividades - você não precisa enviá-las para o Intent e depois retirá-las.
O que eu tinha:
fonte
Quando estou lidando com o
WebView
no meu aplicativo, isso acontece. Eu acho que está relacionado aosaddView
recursos da interface do usuário. No meu aplicativo, adiciono algum códigoWebViewActivity
como este abaixo e ele funciona ok:fonte
Encontrei a causa raiz disso (obtivemos "falha na adição de janela" e vazamento no descritor de arquivos, como diz o mvds).
Há um erro no
BitmapFactory.decodeFileDescriptor()
Android 4.4. Só ocorre quandoinPurgeable
einInputShareable
deBitmapOptions
estão definidos comotrue
. Isso causa muitos problemas em muitos lugares e interage com arquivos.Observe que o método também é chamado de
MediaStore.Images.Thumbnails.getThumbnail()
.O Universal Image Loader é afetado por esse problema. Picasso e Glide parecem não ser afetados. https://github.com/nostra13/Android-Universal-Image-Loader/issues/1020
fonte
Essa linha de código no método writeToParcel (Parcel dest, int flags) me ajudou a me livrar do TransactionTooLargeException.
Após esse código apenas, estou gravando todos os dados no objeto de parcela, ou seja, dest.writeInt () etc.
fonte
Tente usar
EventBus
ouContentProvider
gostar da solução.Se você estiver no mesmo processo (normalmente todas as suas atividades estariam), tente usar
EventBus
, pois a troca de dados em processo NÃO precisa de um buffer, para que você não precise se preocupar com o tamanho excessivo dos dados. (Você pode simplesmente usar a chamada de método para transmitir dados, e EventBus oculta as coisas feias) Aqui está o detalhe:Se os dois lados do Intent não estiverem no mesmo processo, tente um pouco
ContentProvider
.Consulte TransactionTooLargeException
fonte
Recebi uma TransactionTooLargeException de um erro do Stackoverflow em um teste do Android Espresso. Encontrei o rastreamento da pilha de erros stackoverflow nos logs quando removi o filtro Logcat do meu aplicativo.
Suponho que o Espresso tenha causado a TransactionTooLargeException ao tentar manipular um rastreamento de pilha de exceção realmente grande.
fonte
Pode-se usar:
no Manifesto do Android, na tag do aplicativo.
Isso resolveu o problema no meu caso!
fonte
onSaveInstantState
atividades / fragmentos e salvar grandes listas), não ajudou.Também estava enfrentando esse problema nos dados de bitmap que passavam de uma atividade para outra, mas resolvi fazer meus dados como dados estáticos e isso está funcionando perfeitamente para mim
Em atividade primeiro:
e na segunda atividade:
fonte
Isso estava acontecendo no meu aplicativo porque eu estava passando uma lista de resultados de pesquisa nos argumentos de um fragmento, atribuindo essa lista a uma propriedade do fragmento - que na verdade é uma referência ao mesmo local na memória apontado pelos argumentos do fragmento - e adicionando novos itens para a lista, que também alteraram o tamanho dos argumentos do fragmento. Quando a atividade é suspensa, a classe de fragmento base tenta salvar os argumentos do fragmento em onSaveInstanceState, que trava se os argumentos forem maiores que 1 MB. Por exemplo:
A solução mais fácil nesse caso foi atribuir uma cópia da lista à propriedade do fragmento em vez de atribuir uma referência:
Uma solução ainda melhor seria não passar tantos dados nos argumentos.
Eu provavelmente nunca teria encontrado isso sem a ajuda desta resposta e do TooLargeTool .
fonte
Eu também vivi TransactionTooLargeException. Em primeiro lugar, trabalhei para entender onde isso ocorre. Eu sei a razão pela qual isso ocorre. Todos nós sabemos por causa do grande conteúdo. Meu problema era assim e eu resolvi. Talvez essa solução possa ser útil para qualquer pessoa. Eu tenho um aplicativo que obtém conteúdo da API. Estou obtendo resultado da API na primeira tela e enviando para a segunda tela. Posso enviar esse conteúdo para a segunda tela com êxito. Após a segunda tela, se eu quiser ir para a terceira tela, essa exceção ocorre. Cada uma das minhas telas é criada a partir do fragmento. Percebi isso quando saio da segunda tela. Ele salva o conteúdo do pacote. se esse conteúdo for muito grande, essa exceção acontece. Minha solução é depois que eu recebo o conteúdo do pacote e limpo.
fonte
Uma solução seria o aplicativo gravar o ArrayList (ou qualquer outro objeto que esteja causando o problema) no sistema de arquivos, passar uma referência a esse arquivo (por exemplo, nome do arquivo / caminho) por meio do Intent para o IntentService e deixar o IntentService recuperar o conteúdo do arquivo e convertê-lo novamente em um ArrayList.
Quando o IntentService concluir o arquivo, ele deve ser excluído ou passado as instruções ao aplicativo por meio de um Broadcast Local para excluir o arquivo que ele criou (retornando a mesma referência de arquivo que foi fornecida a ele).
Para mais informações, consulte minha resposta para esse problema relacionado .
fonte
Como Intenções, Provedores de Conteúdo, Messenger, todos os serviços do sistema, como Telefone, Vibrador etc., utilizam o provedor de infraestrutura IPC da Binder. Além disso, os retornos de chamada do ciclo de vida da atividade também usam essa infraestrutura.
1 MB é o limite geral de todas as transações do fichário executadas no sistema em um momento específico.
Caso ocorram muitas transações quando a intenção é enviada, ela poderá falhar, mesmo que os dados extras não sejam grandes. http://codetheory.in/an-overview-of-android-binder-framework/
fonte
Em tantos lugares onde a TransactionTooLargeException pode acontecer - aqui está mais uma novidade no Android 8 - uma falha quando alguém simplesmente começa a digitar um EditText se o conteúdo for muito grande.
Está relacionado ao AutoFillManager (novo na API 26) e ao seguinte código em
StartSessionLocked()
:Se bem entendi, isso chama o serviço de preenchimento automático - passando o AutofillManagerClient no fichário. E quando o EditText tem muito conteúdo, parece causar o TTLE.
Algumas coisas podem atenuá-lo (ou fiz como eu estava testando de qualquer maneira): Adicione
android:importantForAutofill="noExcludeDescendants"
a declaração de layout xml do EditText. Ou no código:Uma segunda solução terrível e terrível também pode ser substituir os métodos
performClick()
eonWindowFocusChanged()
para detectar o erro em uma subclasse do TextEdit. Mas eu não acho isso realmente sábio ...fonte