意图putExtra方法的最大长度? (强制closures)

我需要一些帮助来debugging我的应用程序。 首先:在模拟器和其他一些设备上,我的应用运行良好。 在我的设备上,我得到了一个closures力量(没有强制closures信息)。

如果应用程序的“活动”发生更改,则会发生“崩溃”。

这里是MainActivity类的一些代码。 它只是通过webview从网页上读取html内容。 不,不可能通过HttpRequest做到这一点,因为我无法模拟发布请求。

 public class MainActivity extends Activity { public final static String EXTRA_HTML = "com.example.com.test.HTML"; private WebView mWebView; private ProgressDialog mDialog; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = (WebView) findViewById(R.id.webView1); CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.removeAllCookie(); mWebView.setBackgroundColor(0); mWebView.setWebChromeClient(new WebChromeClient() { public boolean onConsoleMessage(ConsoleMessage cmsg) { if (cmsg.message().startsWith("MAGIC")) { mDialog.cancel(); /*HashMap<String, String> message = new HashMap<String, String>();*/ String msg = cmsg.message().substring(5); Intent intent = new Intent(MainActivity.this, ReadDataActivity.class); /*message.put("message", msg);*/ /*intent.putExtra(EXTRA_HTML, message);*/ intent.putExtra(EXTRA_HTML, msg); startActivity(intent); } return false; } }); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setPluginState(PluginState.OFF); mWebView.getSettings().setLoadsImagesAutomatically(false); mWebView.getSettings().setBlockNetworkImage(true); mWebView.getSettings().setAppCacheEnabled(true); mWebView.getSettings().setSavePassword(true); mWebView.getSettings() .setCacheMode(WebSettings.LOAD_NORMAL); mWebView.setWebViewClient(new WebViewClient() { public void onPageFinished(WebView view, String address) { if (address.indexOf("mySession") != -1) { view.loadUrl("javascript:console.log('MAGIC'+document.getElementsByTagName('html')[0].innerHTML);"); } }); mWebView.loadUrl("http://www.myurl.de"); } 

所以,在onConsoleMessage()方法中,我只是将HTML代码传递给另一个Activity类,它读取,parsing和显示内容。

现在的问题是,在此时应该加载ReadDataActivity类,应用程序就会closures,并返回到主屏幕,而不需要任何消息或用户对话框。

是否有可能是作为一个string传递给ReadDataActivity的HTML代码是大? 我也尝试添加一个HashMap中的string的HTML代码,但问题是一样的。

一些想法,我可以做些什么来debugging这个问题? 也许我应该尝试创build一个Parcelable对象?

在模拟器中一切工作正常。

问候,桑德罗

根据我的经验(前一段时间),您可以在封装在Intent中的Bundle放置1MB的数据。 我想,这个限制是有效的,直到FroyoGingerBread

但是,为了解决这个问题,我build议你将你的内容保存在一个临时文件中,然后把临时文件的path/ URI传递给你的第二个活动。 然后在第二个活动中,从文件中读出内容,执行所需的操作,最后删除该文件。

如果你愿意的话,你也可以为这个任务joinShared_Preferences – 如果你认为处理文件是麻烦的。

我对使用Intent可以传输的最大数据量做了一些研究。 而且这个限制似乎远不及1MB或90KB,更像是500KB (API 10,16,19和23testing)。

我写了一篇关于这个话题的博客文章,你可以在这里find它: https : //www.neotechsoftware.com/blog/android-intent-size-limit

1MB的固定大小不仅限于意图。由Intent,Content Provider,Messenger,电话,振动器等所有系统服务通过Binder使用IPC基础设施提供者。此外,活动生命周期callback也使用此基础设施。

1MB是系统在特定时刻执行的所有绑定事务的总体限制。

如果在发送意图时发生大量事务,即使额外的数据量不大,也可能会失败。 http://codetheory.in/an-overview-of-android-binder-framework/

在Jelly Bean中 ,Intent的大小限制还是相当低,比1MB(90K左右)还要低,所以即使你的应用只针对最新的Android版本,也应该对数据长度保持谨慎。

比赛迟到了一点,但是我碰到了同样的问题。 把数据写入文件在我的情况下并没有什么意义,但我在search答案时遇到了这个问题:

http://developer.android.com/guide/faq/framework.html#3

使用单例对我来说更好,因为不需要磁盘IO。 如果数据不需要保持,性能更好。

这是一个示例实现:

 public class DataResult { private static DataResult instance; private List<SomeObject> data = null; protected DataResult() { } public static DataResult getInstance() { if (instance == null) { instance = new DataResult(); } return instance; } public List<SomeObject> getData() { return data; } public void setData(List<SomeObject> data) { this.data = data; } } 

然后你可以在一个活动中使用这个设置:

 DataResult.getInstance().setData(data); 

并在这样的其他活动:

 List<SomeObject> data = DataResult.getInstance().getData(); 

在活动之间传递大量数据的另一种解决scheme是使用静态字段。 在你的情况下,将此行添加到ReadDataActivity类

 public static String msg; 

然后,您可以在MainActivity类中使用静态字段msg,如下所示

 ReadDataActivity.msg = cmsg.message().substring(5); 

最后开始你的活动没有额外的投入

 Intent intent = new Intent(MainActivity.this, ReadDataActivity.class); startActivity(intent); 

我已经看到,通过写入和读取文件组成的性能较差。 然后我看到了这个解决scheme: 。 所以我正在使用这个解决scheme:

 public class ExtendedDataHolder { private static ExtendedDataHolder ourInstance = new ExtendedDataHolder(); private final Map<String, Object> extras = new HashMap<>(); private ExtendedDataHolder() { } public static ExtendedDataHolder getInstance() { return ourInstance; } public void putExtra(String name, Object object) { extras.put(name, object); } public Object getExtra(String name) { return extras.get(name); } public boolean hasExtra(String name) { return extras.containsKey(name); } public void clear() { extras.clear(); } } 

然后在MainActivity中,我把它称为如下:

 ExtendedDataHolder extras = ExtendedDataHolder.getInstance(); extras.putExtra("extra", new byte[1024 * 1024]); extras.putExtra("other", "hello world"); startActivity(new Intent(MainActivity.this, DetailActivity.class)); 

并在DetailActivity

 ExtendedDataHolder extras = ExtendedDataHolder.getInstance(); if (extras.hasExtra("other")) { String other = (String) extras.getExtra("other"); } 

活页夹事务缓冲区具有有限的固定大小 – 1Mb。 但是问题在于缓冲区在进程中正在进行的所有事务共享

所以尽量保持你的意图数据尽可能小。

使用static Stringvariables是很好的。 如果用户需要在不同的HTML之间来回切换,也可以像这样使用LruCache

  static LruCache<String, String> mMemoryCache; final int kiloByte = 1024; . . final int maxMemoryKB = (int) (Runtime.getRuntime().maxMemory() / kiloByte); // then choose how much you want to allocate for cache final int cacheSizeKB = maxMemoryKB / 8; . . mMemoryCache = new LruCache<String, String>(cacheSizeKB) { //@Override protected int sizeOf(String key, String value) { try { byte[] bytesUtf8 = value.getBytes("UTF-8"); return bytesUtf8.length / kiloByte; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return -1; } }; . . String cacheKey = generateUniqueString(key); if (mMemoryCache.get(key) == null) { mMemoryCache.put(cacheKey, yourContent); } Intent intent = new Intent(getApplicationContext(), ReadDataActivity.class); intent.putExtra(EXTRA_HTML, cacheKey); startActivity(intent); 

然后在ReadDataActivity

 Intent intent = getIntent(); String cacheKey = intent.getStringExtra(EXTRA_HTML); String contentString = MainActivity.mMemoryCache.get(cacheKey); doSomethingWith(contentString); 

这个想法来自这里 。