アプリケーションのデバッグに助けが必要です。まず第一に:エミュレーターや他のいくつかのデバイスでは、アプリは正常に動作しています。デバイスで、強制終了しました(強制終了メッセージなし)。
「クラッシュ」は、アプリのアクティビティが変更された場合に発生します。
MainActivity
クラスのコードを次に示します。 WebViewを介してWebページから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()
メソッドでは、コンテンツを読み取り、解析、表示する別のActivityクラスにhtmlコードを渡すだけです。
問題は、この時点でReadDataActivity
クラスをロードするときに、アプリケーションを閉じて、メッセージやユーザーダイアログなしでホーム画面に戻ることです。
ReadDataActivity
に文字列として渡されるHTMLコードが大きすぎる可能性はありますか? HashMapにHTMLコードを文字列として追加しようとしましたが、問題は同じです。
問題をデバッグするために私ができることはいくつかありますか? Parcelable
オブジェクトを作成しようとする必要がありますか?
エミュレーターでは、すべてが正常に機能しています。
私の経験によると(しばらく前)、Bundle
内にカプセル化されたIntent
に1MBのデータを入れることができます。この制限はFroyoまたはGingerbreadまで有効だったと思います。
ただし、この問題を解決するには、コンテンツを一時ファイルに保存し、一時ファイルのpath/URIを渡すことをお勧めします2番目のアクティビティ。次に、2番目のアクティビティで、ファイルから内容を読み取り、目的の操作を実行して、最後にそのファイルを削除します。
必要に応じて、組み込むこともできます Shared_Preferences このタスクの場合-ファイルの処理が面倒だと思われる場合。
Intentを使用して転送できるデータの最大量について調査しました。そして、制限は1MBや90KBの近くにはないようで、500KB(API 10、16、19、23でテスト済み)に似ています。
このトピックに関するブログ記事を書きました。ここで見つけることができます: https://www.neotechsoftware.com/blog/Android-intent-size-limit
Intentのサイズ制限は Jelly bean でまだかなり低く、1MB(約90K)よりもやや低いため、アプリケーションが最新の= Androidバージョン。
1MBの固定サイズは、インテントに限定されません。インテント、コンテンツプロバイダー、メッセンジャー、電話、バイブレーターなどのすべてのシステムサービスとして、IPC Binderのインフラストラクチャプロバイダーを使用します。さらに、アクティビティライフサイクルコールバックもこのインフラストラクチャを使用します。
1MBは、特定の瞬間にシステムで実行されるすべてのバインダートランザクションの全体的な制限です。
インテントの送信時に多くのトランザクションが発生する場合、追加データが大きくなくても失敗する可能性があります。
http://codetheory.in/an-overview-of-Android-binder-framework/
ゲームに少し遅れましたが、同じ問題に出くわしました。私の場合、データをファイルに書き込むことは実際にはパフォーマンス的に意味がありませんでしたが、答えを探すときにこれに遭遇しました:
http://developer.Android.com/guide/faq/framework.html#
ディスクI/Oは必要ないので、シングルトンを使用する方が適しています。データを永続化する必要がない場合のパフォーマンスの向上。
以下に実装例を示します。
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; }
}
次に、これを使用して1つのアクティビティで設定できます。
DataResult.getInstance().setData(data);
そして、次のような他のアクティビティで取得します。
List<SomeObject> data = DataResult.getInstance().getData();
私は、ファイルの読み書きがパフォーマンスの低下につながることを見てきました。 その後、私はこの解決策を見ました: 。だから私はこのソリューションを使用しています:
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");
}
の用法 static String
変数は適切です。ユーザーが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);
このアイデアは here から生まれました。
バインダトランザクションバッファの制限サイズは1Mbです。しかし問題は、プロセスですべてのトランザクションで共有されるバッファーが進行中であることです。
そのため、毎回インテントのデータをできるだけ小さくするようにしてください。
アクティビティ間で大きなデータを渡すための代替ソリューションは、静的フィールドを使用することです。あなたの場合、この行をReadDataActivityクラスに追加してください
public static String msg;
次に、MainActivityクラス内の静的フィールドmsgを次のように使用できます。
ReadDataActivity.msg = cmsg.message().substring(5);
そして最後に余分なプットなしであなたの活動を開始します
Intent intent = new Intent(MainActivity.this, ReadDataActivity.class);
startActivity(intent);