Androidの奇抜な問題の全記録-(一)
8704 ワード
1.androidはfragmentで作成したtabページを使用し、メインインタフェースがバックグラウンドに切り替わり、システムメモリが不足している場合、メインインタフェースがシステムに強制回収された後、再びcreateされてfragmentが重なる.
メインインタフェースのtab切替はfragment切替を使用して実現されるため、メインactivityはv 7のAppCompatActivityから継承され、AppCompatActivityはFragmentActivityから継承される
FragmentActivityのonSaveInstanceStateメソッドを見てみましょう.
コードにこんな一節がある
FragmentActivityは、onSaveInstanceStateに現在のインタフェースのすべてのfragmentの状態を保存しているため、メインインタフェースactivityが破棄された後にfragmentがonSaveInstanceStateに保存され、メインインタフェースActivityがフロントに戻ってシステムによって再作成されたときに、元のfragmentのビュー状態がFragmentActivityに復元され、同時にメインインタフェースActivityのoncreateメソッドが再実行され、既存のfragmentに基づいてfragmentが繰り返し作成されます.
以下に、いくつかのソリューションを示します.
1.oncreateでoncreateメソッドで渡されたsavedInstancesStateがnullであるかどうかを判断し、nullに対して完全なfragment tab初期化作業を実行し、そうでなければ初期化を実行しない場合、構想コードは以下の通りである.
2.この方法は怠け者の方法の一つであり、oncreateではsuperである.oncreateが実行される前にsaveInstanceのfragment状態をすべて空にします.これにより、Activityが再作成されたときに元のfragmentが状態に戻らず、Activityの通常のcreateに従って実行されます.
3.同じ怠け者の方法で、onSaveInstanceStateメソッドを書き直し、親saveInstanceStateへの呼び出しを注釈するが、これには多くの副作用があり、システム自身が実現したonSaveInstanceStateは完全に機能しなくなるので、あまりお勧めしない.参考コード:
2.Appをパッケージ化した後、一部の携帯電話にインストールし、インストールが完了したら、直接システムインストール画面の開いたボタンをクリックし、ホームボタンをクリックしてホームページに移動し、起動アイコンをクリックし、繰り返し起動を適用する(この問題は最初にappをインストールしたときにのみ発生し、その後appを終了して再実行し、ホームをクリックし、起動アイコンをクリックしても問題は発生しない)
ソリューションは、起動ページにコード判定を追加し、起動したActivityが現在のタスクのルートActivityでない場合、直接finishを削除します.コードは次のとおりです.
3.呼び出しシステムカメラを適用した後、アプリケーションデータの紛失、アプリケーションクラッシュなどを返す
携帯電話でシステムカメラを呼び出す場合、メモリが不足してカメラを呼び出すappやappの呼び出しカメラのActivityインタフェースが強制的に回収される確率が高いため、呼び出しカメラのActivityはonSaveInstanceStateを書き換える必要があり、onSaveInstanceStateメソッドでローカル変数を保存し、同時にonRestoreInstanceState法でこれらの局所変数を再取得し,必要な論理処理を行う.
4.一部の古い機種では、システムカメラを呼び出してActivity Not Found異常を報告する
このようなエラーは、一般的に2つのケースで発生します.一部の機器にはカメラが備え付けられていない 一部機器にsdカードがない この2つの状況を処理するために、カメラを起動するときに簡単な判断をしました.
5.Android 4.1などでEventBus報aused by:java.lang.ClassNotFoundException: Didn’t find class “android.os.PersistableBundle” on path: DexPathList
このエラーの原因は、onSaveInstanceState(Bundle outState,PersistableBundle outPersistentState)という方法を何気なく書き換え、自分のコードをチェックし、onSaveInstanceState(Bundle outState)を使用してコードロジックを処理することが一般的です.
6.ピクチャフレームfrescoを導入するとis 32-bit instead of 64-bitのエラーが発生する
プロジェクトには他のサードパーティのsoライブラリが参照されていますが、arm 64-v 8ディレクトリのsoファイルはありません.frescoのライブラリファイルにはarm 64-v 8ディレクトリが作成されています.
Androidがsoファイルを検索するルールに従って、Androidデバイスは対応するcpuアーキテクチャディレクトリを優先的に検索し、対応するディレクトリが見つからない場合はarmeabiディレクトリの下で互換的にsoファイルを呼び出すが、対応するディレクトリが検索できれば、そのディレクトリの下のsoライブラリのみを呼び出す.既存のsoライブラリに対応するディレクトリの下のsoファイルがなければ、対応するディレクトリsoライブラリが見つからないため、エラーが発生します.
では、私のプロジェクトはarm 64-v 8のディレクトリを作成していません.なぜエラーが発生したのでしょうか.検査の結果、私たちのfrescoライブラリは互換性のため、デフォルトで対応するarm 64-v 8のライブラリディレクトリを作成していましたが、私のプロジェクトの他のsoライブラリには対応するarm 64-v 8アーキテクチャがありません.そのため、appはarm 64ビットデバイスにインストールされたときにarm 64-v 8のsoディレクトリを検索し、is 32-bit instead of 64-bitのエラーを報告します.
ソリューション:プロジェクトが参照したsoライブラリにarm 64-v 8アーキテクチャに対応するsoライブラリを追加します. gradleのdefaultConfigに を設定
メインインタフェースのtab切替はfragment切替を使用して実現されるため、メインactivityはv 7のAppCompatActivityから継承され、AppCompatActivityはFragmentActivityから継承される
FragmentActivityのonSaveInstanceStateメソッドを見てみましょう.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
if (mPendingFragmentActivityResults.size() > 0) { outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG,mNextCandidateRequestIndex);
int[] requestCodes = new int[mPendingFragmentActivityResults.size()];
String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];
for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {
requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);
fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);
}
outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);
outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);
}
}
コードにこんな一節がある
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
FragmentActivityは、onSaveInstanceStateに現在のインタフェースのすべてのfragmentの状態を保存しているため、メインインタフェースactivityが破棄された後にfragmentがonSaveInstanceStateに保存され、メインインタフェースActivityがフロントに戻ってシステムによって再作成されたときに、元のfragmentのビュー状態がFragmentActivityに復元され、同時にメインインタフェースActivityのoncreateメソッドが再実行され、既存のfragmentに基づいてfragmentが繰り返し作成されます.
以下に、いくつかのソリューションを示します.
1.oncreateでoncreateメソッドで渡されたsavedInstancesStateがnullであるかどうかを判断し、nullに対して完全なfragment tab初期化作業を実行し、そうでなければ初期化を実行しない場合、構想コードは以下の通りである.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
// create
initTab();
}
else {
// create
}
}
2.この方法は怠け者の方法の一つであり、oncreateではsuperである.oncreateが実行される前にsaveInstanceのfragment状態をすべて空にします.これにより、Activityが再作成されたときに元のfragmentが状態に戻らず、Activityの通常のcreateに従って実行されます.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
savedInstanceState.putParcelable("android:support:fragments", null);
}
super.onCreate(savedInstanceState);
}
3.同じ怠け者の方法で、onSaveInstanceStateメソッドを書き直し、親saveInstanceStateへの呼び出しを注釈するが、これには多くの副作用があり、システム自身が実現したonSaveInstanceStateは完全に機能しなくなるので、あまりお勧めしない.参考コード:
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
// super.onSaveInstanceState(outState, outPersistentState);
}
2.Appをパッケージ化した後、一部の携帯電話にインストールし、インストールが完了したら、直接システムインストール画面の開いたボタンをクリックし、ホームボタンをクリックしてホームページに移動し、起動アイコンをクリックし、繰り返し起動を適用する(この問題は最初にappをインストールしたときにのみ発生し、その後appを終了して再実行し、ホームをクリックし、起動アイコンをクリックしても問題は発生しない)
ソリューションは、起動ページにコード判定を追加し、起動したActivityが現在のタスクのルートActivityでない場合、直接finishを削除します.コードは次のとおりです.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(savedInstanceState);
// Activity
if (!isTaskRoot()) {
finish();
return;
}
}
3.呼び出しシステムカメラを適用した後、アプリケーションデータの紛失、アプリケーションクラッシュなどを返す
携帯電話でシステムカメラを呼び出す場合、メモリが不足してカメラを呼び出すappやappの呼び出しカメラのActivityインタフェースが強制的に回収される確率が高いため、呼び出しカメラのActivityはonSaveInstanceStateを書き換える必要があり、onSaveInstanceStateメソッドでローカル変数を保存し、同時にonRestoreInstanceState法でこれらの局所変数を再取得し,必要な論理処理を行う.
4.一部の古い機種では、システムカメラを呼び出してActivity Not Found異常を報告する
このようなエラーは、一般的に2つのケースで発生します.
private void showCamera() {
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mTakePhotoUri = FileUtils.getOutputMediaFileUri(FileUtils.MEDIA_TYPE_IMAGE);
mFilePath = mTakePhotoUri.getPath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, mTakePhotoUri);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
} catch (ActivityNotFoundException e) {
showShortToast(R.string.error_no_camera);
}
}
else {
showShortToast(R.string.error_no_sdcard);
}
}
5.Android 4.1などでEventBus報aused by:java.lang.ClassNotFoundException: Didn’t find class “android.os.PersistableBundle” on path: DexPathList
このエラーの原因は、onSaveInstanceState(Bundle outState,PersistableBundle outPersistentState)という方法を何気なく書き換え、自分のコードをチェックし、onSaveInstanceState(Bundle outState)を使用してコードロジックを処理することが一般的です.
6.ピクチャフレームfrescoを導入するとis 32-bit instead of 64-bitのエラーが発生する
プロジェクトには他のサードパーティのsoライブラリが参照されていますが、arm 64-v 8ディレクトリのsoファイルはありません.frescoのライブラリファイルにはarm 64-v 8ディレクトリが作成されています.
Androidがsoファイルを検索するルールに従って、Androidデバイスは対応するcpuアーキテクチャディレクトリを優先的に検索し、対応するディレクトリが見つからない場合はarmeabiディレクトリの下で互換的にsoファイルを呼び出すが、対応するディレクトリが検索できれば、そのディレクトリの下のsoライブラリのみを呼び出す.既存のsoライブラリに対応するディレクトリの下のsoファイルがなければ、対応するディレクトリsoライブラリが見つからないため、エラーが発生します.
では、私のプロジェクトはarm 64-v 8のディレクトリを作成していません.なぜエラーが発生したのでしょうか.検査の結果、私たちのfrescoライブラリは互換性のため、デフォルトで対応するarm 64-v 8のライブラリディレクトリを作成していましたが、私のプロジェクトの他のsoライブラリには対応するarm 64-v 8アーキテクチャがありません.そのため、appはarm 64ビットデバイスにインストールされたときにarm 64-v 8のsoディレクトリを検索し、is 32-bit instead of 64-bitのエラーを報告します.
ソリューション:
ndk {
// SO ,
abiFilters 'armeabi' , 'x86'
}