私のアプリは通常、特定のデバイスで奇妙な問題に直面するまで、問題なく動作します。アプリには2つのアクティビティがあります。 ActivityA内でActivityBを開始した後、ActivityAは問題なく開始します。ただし、ハードウェアボタンを押し戻すか、finish()を呼び出してActivityAに戻った後、 ActivityBのcloseButtonの内部で、ActivityAは自身をリロードします。それはonCreate()を再びトリガーし、そのすべてのコンテンツをリロードします。そして、私は電話の向きを変えていません。この奇妙な動作は、アプリの1.000ダウンロード以上の15台の電話でのみ発生します。
この問題はGalaxy S3でのみ発生しますAndroid OS 4.1.2。これも奇妙です。
これがなぜ起こっているのかあなたは何か考えがありますか?
次のようにボタンリスナー内で新しいアクティビティを開始すると:
ActivityA.Java(MesajlarListViewActivity)
public class MesajlarListViewActivity extends TrackedActivity {
Context context = null;
// contacts JSONArray
JSONArray contacts = null;
ArrayList<Message> productArray = new ArrayList<Message>();
private ProductAdapter adapter;
private ListView productList;
private Runnable viewOrders;
private HoloProgressIndicator profilInfoProgress = null;
ImageView kapatButton = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mesajlar_list);
context = this;
kapatButton = (ImageView) findViewById(R.id.kapat_button);
/* kapat button onclick listener. */
// =================================================================================================================
kapatButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view)
{
// Set vibration on touch.
KnetGenericClass.vibratePhone(context);
finish();
}
});
// =================================================================================================================
//Progress bar.
profilInfoProgress = (HoloProgressIndicator) findViewById(R.id.profil_info_progress);
// cheking internet connectivity.
if(KnetGenericClass.checkInternetConnection(context))
{
// start task!
/* internet var ise web service baglantisi kurmaya baslayabiliriz. */
startActivityIndicatorWithThread();
}
else
{
KnetGenericClass.printErrorMessage(context, "Bağlantı Hatası",
"Lütfen internet bağlantınızı kontrol ediniz.");
}
productList = (ListView) findViewById(R.id.product_list);
adapter = new ProductAdapter(this, R.layout.message_row, productArray);
productList.setAdapter(adapter);
// When user click a view on list view new page is appearing.
productList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
// Set vibration on touch.
KnetGenericClass.vibratePhone(context);
/* Navigate to message detay activity class with ilan ID. */
Intent myIntent = new Intent(view.getContext(), MesajDetayActivity.class);
myIntent.putExtra("messageID", productArray.get(position).getId());
startActivity(myIntent);
// setting image of clicked message null.
RelativeLayout relativeLayout = (RelativeLayout) view;
ImageView unreadedImageView = (ImageView) relativeLayout.findViewById(R.id.unreaded_image);
unreadedImageView.setImageResource(0);
}
});
}
public class ProductAdapter extends ArrayAdapter<Message> {
ArrayList<Message> items;
public ProductAdapter(Context context, int textViewResourceId, ArrayList<Message> objects) {
super(context, textViewResourceId, objects);
this.items = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
if(convertView == null)
{
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.message_row, null);
}
ImageView unreadedImageView = (ImageView) convertView.findViewById(R.id.unreaded_image);
TextView productName = (TextView) convertView.findViewById(R.id.product_name);
TextView productDetail = (TextView) convertView.findViewById(R.id.product_detail);
// TextView productDate = (TextView)
// convertView.findViewById(R.id.product_date);
TextView sentDate = (TextView) convertView.findViewById(R.id.product_date);
productName.setText(items.get(position).getSender());
productDetail.setText(items.get(position).getTitle());
// String bodyNoHTML = items.get(position).getBody();
if(items.get(position).getIsReaded())
{
unreadedImageView.setImageResource(0);
}
else
{
unreadedImageView.setImageResource(R.drawable.bluedot);
}
String dateStr = items.get(position).getSentDate();
try
{
sentDate.setText(dateStr.substring(6, 8) + "." + dateStr.substring(4, 6) + "." + dateStr.substring(0, 4)
+" "+dateStr.substring(8, 10)+":"+dateStr.substring(10, 12));
}
catch(Exception e)
{
sentDate.setText("");
}
return convertView;
}
}// @end of product adapter class.
/* web service'e baglanti kurulan methodu threadin icerisinde cagiriyoruz. */
public void startActivityIndicatorWithThread()
{
// ==============================================================================================
// getting ilan details into arraylist.
// setting up thread.
viewOrders = new Runnable() {
public void run()
{
getMessageListFromWebService();
}
};
Thread thread = new Thread(null, viewOrders, "MagentoBackground");
thread.start();
profilInfoProgress.start();
// ==============================================================================================
// @end of the thread declaration.
}
public void getMessageListFromWebService()
{
// Creating JSON Parser instance
JSONParser jParser = new JSONParser(context);
// getting JSON string from URL
JSONArray jsonArray = jParser.getAuthorizedInfoFromUrlToJSONArray(
WebServiceInfo.getKnetWebServiceLink()+"/API/Member/GetInboxMessageList", MainActivity.getAccessToken());
// if json is null then there is a problem.
if(jsonArray == null)
{
// if json array is null then print error message.
runOnUiThread(showAlertMessage);
runOnUiThread(returnRes);
return;
}
try
{
// Eger aranilan kritere gore ilan yok ise hata mesaji basiyoruz.
if(jsonArray.length() == 0)
{
// if json array is null then print error message.
runOnUiThread(showAlertIlanYokMessage);
runOnUiThread(returnRes);
return;
}
// looping through All Contacts
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject c = jsonArray.getJSONObject(i);
// Storing each json item in variable
// String id = c.getString(TAG_ID);
String id = c.getString("Id");
String sender = c.getString("Sender");
// String body = c.getString("Body");
String title = c.getString("Title");
String sentDate = c.getString("SentDate");
Boolean isReaded = c.getBoolean("IsRead");
Message productObject = new Message(id, sender, "", title, sentDate, isReaded);
productArray.add(productObject);
}
}
catch (Exception e)
{
Log.e("BACKGROUND_PROC", e.getMessage());
}
runOnUiThread(returnRes);
}
// @end of thread.
private Runnable returnRes = new Runnable() {
public void run()
{
profilInfoProgress.stop();
adapter.notifyDataSetChanged();// refreshing data over adapter in
// list view.
}
};
// @end of thread.
private Runnable showAlertMessage = new Runnable() {
public void run()
{
// Bu hata genelde linkteki problemden, servera ulasilamamasindan
// veya timeouttan meydana gelir.
Toast.makeText(getApplicationContext(),
"Mesajlar alınamadı lütfen daha sonra tekrar deneyiniz.",
Toast.LENGTH_LONG).show();
}
};
private Runnable showAlertIlanYokMessage = new Runnable() {
public void run()
{
// Bu hata aranilan kelimeye gore ilan bulunamazsa gelir.
Toast.makeText(getApplicationContext(),
"Mesajlar bulunamadı.",
Toast.LENGTH_LONG).show();
}
};
}
================================================== ======================
ActivityB.Java(MesajDetayActivity.Java)
public class MesajDetayActivity extends TrackedActivity {
private HoloProgressIndicator profilInfoProgress = null;
TextView titleTextView = null;
TextView senderTextView = null;
TextView dateTextView = null;
WebView bodyWebView = null;
Message messageObject = null;
String messageID = null;
ImageView kapatButton = null;
Context context;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mesajdetaylari);
context = this;
kapatButton = (ImageView) findViewById(R.id.kapat_button);
/* kapat button onclick listener. */
// =================================================================================================================
kapatButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view)
{
// Set vibration on touch.
KnetGenericClass.vibratePhone(context);
finish();
}
});
// =================================================================================================================
//Progress bar.
profilInfoProgress = (HoloProgressIndicator) findViewById(R.id.profil_info_progress);
Bundle extras = getIntent().getExtras();
if(extras != null)
{
messageID = extras.getString("messageID");
}
titleTextView = (TextView) findViewById(R.id.title_textview);
senderTextView = (TextView) findViewById(R.id.sender_textview);
dateTextView = (TextView) findViewById(R.id.date_textview);
bodyWebView = (WebView) findViewById(R.id.mesaj_webView);
// Show the ProgressDialog on this thread
profilInfoProgress.start();
// Start a new thread that will download all the data
new MakeItTask().execute();
}
// Async task.
private class MakeItTask extends AsyncTask<String, Void, Object> {
protected Object doInBackground(String... args)
{
Log.i("MyApp", "Background thread starting");
// This is where you would do all the work of downloading your data
// getting message detay
/* connect to web service */
getMessageDetayFromWebService();
return null;
}
protected void onPostExecute(Object result)
{
// Pass the result data back to the main activity
// TakipListeActivity.this.data = result;
try
{
titleTextView.setText("Başlık: " + messageObject.getTitle());
senderTextView.setText("Gönderen: " + messageObject.getSender());
dateTextView.setText("Tarih: " + messageObject.getSentDate().substring(6, 8) + "."
+ messageObject.getSentDate().substring(4, 6) + "."
+ messageObject.getSentDate().substring(0, 4));
if(!messageObject.getBody().contains("img"))
{
bodyWebView.loadDataWithBaseURL(null, messageObject.getBody(), "text/html", "UTF-8", null);
}
}
catch (Exception e)
{
Log.e(CONNECTIVITY_SERVICE, "Mesaj Detayi bilgileri basilamadi.");
}
profilInfoProgress.stop();
}
}
/* web service'e baglanti kurulan methodu threadin icerisinde cagiriyoruz. */
public void getMessageDetayFromWebService()
{
// Creating JSON Parser instance
JSONParser jParser = new JSONParser(context);
// getting JSON string from URL
JSONObject jsonObject = jParser.getAuthorizedInfoFromUrlToJSONObject(
WebServiceInfo.getKnetWebServiceLink()+"/API/Member/GetInboxMessage/" + messageID, MainActivity.getAccessToken());
// if json is null then there is a problem.
if(jsonObject == null)
{
return;
}
try
{
String title = jsonObject.getString("Title");
String id = jsonObject.getString("Id");
String sender = jsonObject.getString("Sender");
String date = jsonObject.getString("SentDate");
String body = jsonObject.getString("Body");
messageObject = new Message(id, sender, body, title, date, true);
}
catch (Exception e)
{
Log.e("BACKGROUND_PROC", e.getMessage());
}
}// @end of getIlanDetayFromWebService.
}
編集:これら2つのアクティビティだけでなく、一部の電話で同じ動作をするすべてのアクティビティにこの問題があります。
アクティビティを保持しない設定> システム> 開発者向けオプション> アプリが有効かどうか。
アクティビティのドキュメント( http://developer.Android.com/reference/Android/app/Activity.html )は、バックグラウンドアクティビティのライフサイクルについて次のように述べています。
バックグラウンドアクティビティ(ユーザーには表示されず、一時停止されたアクティビティ)は重要ではなくなったため、システムはそのプロセスを安全に強制終了して、他のフォアグラウンドまたは可視プロセスのメモリを解放できます。プロセスを強制終了する必要がある場合、ユーザーがアクティビティに戻ると(画面に再び表示される)、onCreate(Bundle)メソッドは、以前にonSaveInstanceState(Bundle)で提供されていたsavedInstanceStateで呼び出され、ユーザーが最後に離れたときと同じ状態で自分自身を再起動できます。
つまり、ActivityBがアクティブなときに、ActivityAがオペレーティングシステムによって破棄される場合と破棄されない場合があるため、この状況はコードで処理する必要があります。 ActivityAが破棄されている場合、ユーザーがActivityBの戻るボタンを押すと、onCreate(Bundle)が呼び出されます。
Android「アクティビティを保持しない」という開発者設定があります。このオプションの説明は、「ユーザーがアクティビティを離れたらすぐにすべてのアクティビティを破棄する」です。これは、 「見ているし、いくつかの電話でしか見ないので、これはデフォルト以外のシステム設定が原因であるという考えはもっともらしいようです。
理想的ではないにしても、理想的にはこのシナリオでもアプリは機能します。ただし、この設定がアプリの問題である場合は、この問題をユーザーに文書化することをお勧めします。
Android Manifestのlaunchmode
を変更してみましたか?これをアクティビティ宣言に追加してみてください:
_Android:launchMode="singleTask"
_
次に、startActivityForResult
の代わりにstartActivity
を使用してみてください。これにより、アクティビティBが完了すると、アクティビティAはonActivityResult(int, int, Intent)
メソッドを強制的に呼び出します。これにより、onCreate
へのこの(バグのある)呼び出しがスキップされる場合があります。次に、アクティビティAで、メソッドを実装して何かを実行します(デバッグステートメントを出力するなど)。
_@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.i("Test", "Did this work???");
//TODO send notification to your server to verify this works?
}
_
この振る舞いには何の問題もありません。
ActivityA
の状態を保持したい場合は、onSaveInstanceState
およびonRestoreInstanceState
メソッドを使用してください。詳細については、アクティビティライフサイクル http://developer.Android.com/reference/Android/app/Activity.html#ActivityLifecycle を参照してください。
より深い理解のために https://stackoverflow.com/a/10492967/33221 も参照してください。
onCreate()
でレイアウトを提供して、残りの作業をonStart()
で行うことができますか?それがうまくいくなら?
お気に入り:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show);
}
そして
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.i(TAG, "On Start .....");
}
アクティビティライフサイクル を参照
アクティビティAのonStart()およびonResumeメソッドをオーバーライドし、問題が解決しないかどうかを確認します。可能であれば、アクティビティAおよびBコードをここに入力してください。
おそらくあなたは使うべきです
Intent startIntent = new Intent(view.getContext(), ActivityB.class);
startActivity(startIntent);
finish() ;
そして
Intent startIntent = new Intent(view.getContext(), ActivityA.class);
startActivity(startIntent);
finish() ;
戻るか進むたびに。
メモリのせいではないかと思います。
https://www.box.com/s/7pd0as03bb8wwumuc9l9
これらの2つのアクティビティをテストし、この例でも同様に発生しているかどうかを確認する必要があります。 AndroidManifest.xmlファイルのコンテンツも共有してください。デバッグに役立ちます。
activity
/manifest
のAndroid:launchMode="standard"
を使用することで、問題も解決され、正確な問題に直面しました。
アクティビティAはレイアウトR.layout.mesajlar_listを使用します
アクティビティBはレイアウトR.layout.mesajdetaylariを使用します
ただし、どちらにも次のコード行があります。
kapatButton = (ImageView) findViewById(R.id.kapat_button);
R.id.kapat_buttonはどのレイアウトにありますか?異なるレイアウトで同じIDを使用するのは非常に危険です。それがあなたが見ているものを引き起こしていることを保証することはできませんが、それは奇妙な行動を引き起こすかもしれない種類のものです。
この問題は最近発生しました。私はその問題をチェックするのに約2つのオプションの解決策ではあるが役に立たないと思います。
ここで修正した「アクティビティを保持しない」設定について、このコードを使用して、オプションであるかどうかを確認しました(テストデバイスはバージョン2.3.5に基づいてカスタマイズし、このオプションを表示していません)。
private boolean isAlwaysFinishActivitiesOptionEnabled() {
int alwaysFinishActivitiesInt = 0;
if (Build.VERSION.SDK_INT >= 17) {
alwaysFinishActivitiesInt = Settings.System.getInt(getApplicationContext().getContentResolver(), Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0);
} else {
alwaysFinishActivitiesInt = Settings.System.getInt(getApplicationContext().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0);
}
if (alwaysFinishActivitiesInt == 1) {
return true;
} else {
return false;
}
}
私の場合、結果チェックはfalseです。また、アプリケーションを実行しているときにメモリを確認しましたが、何も起こりません。
Android:launchMode="singleTop"
inマニフェストを使用できます。
<activity
Android:name=".MainActivity"
Android:label="@string/app_name"
Android:launchMode="singleTop"
Android:configChanges="orientation|keyboardHidden|screenSize"
Android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action Android:name="Android.intent.action.MAIN"/>
<category Android:name="Android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>