เมื่อล็อกเอาต์ให้ล้างสแต็คประวัติกิจกรรมป้องกันปุ่ม "ย้อนกลับ" จากการเปิดกิจกรรมที่ลงชื่อเข้าใช้เท่านั้น


235

กิจกรรมทั้งหมดในแอปพลิเคชันของฉันต้องการให้ผู้ใช้ลงชื่อเข้าใช้เพื่อดู ผู้ใช้สามารถออกจากระบบได้เกือบทุกกิจกรรม นี่คือข้อกำหนดของแอปพลิเคชัน ที่จุดใด ๆ Activityหากผู้ใช้ล็อกเอาผมต้องการที่จะส่งให้ผู้ใช้เข้าสู่ระบบ ณ จุดนี้ฉันต้องการให้กิจกรรมนี้อยู่ด้านล่างของสแต็คประวัติเพื่อให้การกดปุ่ม "ย้อนกลับ" ส่งคืนผู้ใช้ไปยังหน้าจอหลักของ Android

ฉันเคยเห็นคำถามนี้ถามสถานที่ที่แตกต่างกันไม่กี่ทั้งหมดตอบด้วยคำตอบที่คล้ายกัน (ที่ฉันร่างที่นี่) แต่ฉันต้องการที่จะก่อให้เกิดที่นี่เพื่อรวบรวมข้อเสนอแนะ

ฉันได้ลองเปิดกิจกรรมการเข้าสู่ระบบโดยการตั้งค่าIntentสถานะFLAG_ACTIVITY_CLEAR_TOPที่ดูเหมือนว่าจะทำตามที่ระบุไว้ในเอกสาร แต่ไม่บรรลุเป้าหมายของฉันในการวางกิจกรรมการเข้าสู่ระบบที่ด้านล่างของสแต็คประวัติศาสตร์และป้องกันผู้ใช้จากการนำทางย้อนกลับ ไปยังกิจกรรมการลงชื่อเข้าใช้ที่เห็นก่อนหน้านี้ ฉันพยายามใช้android:launchMode="singleTop"กิจกรรมการเข้าสู่ระบบในรายการด้วย แต่สิ่งนี้ไม่บรรลุเป้าหมายของฉันเช่นกัน (และดูเหมือนว่าจะไม่มีผลกระทบต่อไป)

ฉันเชื่อว่าฉันต้องล้างสแต็คประวัติหรือจบกิจกรรมที่เปิดก่อนหน้านี้ทั้งหมด

ทางเลือกหนึ่งคือการมีonCreateสถานะเข้าสู่ระบบการตรวจสอบของแต่ละกิจกรรมและfinish()หากไม่ได้เข้าสู่ระบบ ฉันไม่ชอบตัวเลือกนี้เนื่องจากปุ่มย้อนกลับจะยังคงใช้งานได้นำทางกลับเป็นกิจกรรมที่ปิดตัวเอง

ตัวเลือกถัดไปคือการเก็บรักษาLinkedListของการอ้างอิงถึงกิจกรรมที่เปิดอยู่ทั้งหมดที่สามารถเข้าถึงได้แบบคงที่จากทุกที่ (อาจใช้การอ้างอิงที่อ่อนแอ) เมื่อออกจากระบบฉันจะเข้าถึงรายการนี้และทำซ้ำกิจกรรมที่เปิดก่อนหน้านี้ทั้งหมดโดยเรียกใช้finish()แต่ละรายการ ฉันจะเริ่มใช้วิธีนี้ในไม่ช้า

อย่างไรก็ตามฉันควรใช้Intentเล่ห์เหลี่ยมธงเพื่อบรรลุเป้าหมายนี้ ฉันมีความสุขเกินกว่าจะพบว่าฉันสามารถทำตามข้อกำหนดของแอปพลิเคชันของฉันได้โดยไม่ต้องใช้วิธีใดวิธีหนึ่งจากสองวิธีที่ฉันได้อธิบายไว้ข้างต้น

มีวิธีในการทำสิ่งนี้ให้สำเร็จโดยใช้Intentหรือการตั้งค่ารายการหรือตัวเลือกที่สองของฉันการรักษาLinkedListกิจกรรมที่เปิดไว้เป็นตัวเลือกที่ดีที่สุดหรือไม่? หรือมีตัวเลือกอื่นที่ฉันสามารถมองเห็นได้อย่างสมบูรณ์?

คำตอบ:


213

ฉันขอแนะนำให้คุณใช้วิธีอื่นที่แข็งแกร่งกว่า IMHO โดยทั่วไปคุณต้องออกอากาศข้อความออกจากระบบไปยังกิจกรรมทั้งหมดของคุณที่จำเป็นต้องอยู่ภายใต้สถานะการเข้าสู่ระบบ ดังนั้นคุณสามารถใช้sendBroadcastและติดตั้ง a BroadcastReceiverใน Actvities ทั้งหมดของคุณ บางสิ่งเช่นนี้

/** on your logout method:**/
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.package.ACTION_LOGOUT");
sendBroadcast(broadcastIntent);

ผู้รับ (กิจกรรมที่ปลอดภัย):

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /**snip **/
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.package.ACTION_LOGOUT");
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("onReceive","Logout in progress");
            //At this point you should start the login activity and finish this one
            finish();
        }
    }, intentFilter);
    //** snip **//
}

27
@Christopher แต่ละกิจกรรมจะทำการลงทะเบียนสำหรับการออกอากาศเมื่อมันถูกสร้างขึ้น เมื่อไปถึงพื้นหลัง (เช่นกิจกรรมใหม่มาที่ด้านบนสุดของสแต็ค) onStop () จะถูกเรียกใช้ แต่จะยังสามารถรับการถ่ายทอดได้ คุณเพียงแค่ต้องแน่ใจว่าคุณโทร unregisterReceiver () ใน onDestroy () แทนที่จะเป็น onStop ()
รัสเซลเดวิส

9
สิ่งนี้ใช้งานได้หรือไม่หากกิจกรรมบางอย่างในกองซ้อนถูกปิดโดยระบบปฏิบัติการเพื่อกู้คืนหน่วยความจำ กล่าวคือ ระบบจะพิจารณาว่ามันเสร็จสิ้นจริง ๆ หลังจากส่งสัญญาณออกอากาศไปแล้วและจะไม่สร้างมันขึ้นมาใหม่เมื่อกดปุ่มย้อนกลับ?
ม.ค. Żankowski

5
ในขณะนี้ดูเหมือนว่าจะเป็นทางออกที่ดี แต่ก็เป็นสิ่งสำคัญที่จะต้องทราบว่านี่ไม่ใช่ซิงโครนัส
Che Jami

34
ทางออกที่ดี แต่แทนที่จะใช้การลงทะเบียน Broadcast receiver ตามที่อธิบายไว้ในรหัสด้านบนคุณควรใช้ LocalBroadcastManager.getInstance (this) .registerReceiver (... ) และ LocalBroadcastManager.getInstance (this) .unregisterReceiver (.. ) . แอปพลิเคชันอื่น ๆ ของคุณสามารถรับความตั้งใจได้จากแอปพลิเคชั่นอื่น ๆ (ความกังวลด้านความปลอดภัย)
Uku Loskit

5
@Warlock คุณถูกต้อง ข้อผิดพลาดของวิธีนี้คือเมื่อกิจกรรมในแบ็คสแต็คถูกทำลายโดยระบบ (สามารถเกิดขึ้นได้จากหลายสาเหตุเช่นสถานการณ์จำลองหน่วยความจำต่ำที่บันทึกไว้) ในกรณีนั้นอินสแตนซ์ของกิจกรรมจะไม่ได้รับการออกอากาศ แต่ระบบจะยังคงนำทางกลับผ่านกิจกรรมนั้นโดยสร้างใหม่ สิ่งนี้สามารถทดสอบ / ทำซ้ำได้โดยเปิดการตั้งค่านักพัฒนา "Don't Keep Activities"
Eric Schlenz

151

ดูเหมือนว่าเป็นข้อความที่ผู้เขียนโปรแกรม Android คนใหม่ใช้เวลาทั้งวันทำการค้นคว้าปัญหานี้และอ่านกระทู้ทั้งหมดของ StackOverflow ตอนนี้ฉันเพิ่งเริ่มใหม่และฉันปล่อยให้ร่องรอยของประสบการณ์ต่ำต้อยของฉันเพื่อช่วยผู้แสวงบุญในอนาคต

ครั้งแรกไม่มีวิธีที่ชัดเจนหรือทันทีจะทำเช่นนี้ต่อการวิจัยของฉัน(as of September 2012).คุณจะคิดว่าคุณสามารถที่เรียบง่ายstartActivity(new Intent(this, LoginActivity.class), CLEAR_STACK)แต่ไม่มี

ที่คุณสามารถทำได้startActivity(new Intent(this, LoginActivity.class))ด้วยFLAG_ACTIVITY_CLEAR_TOP- และนี่จะทำให้กรอบการค้นหาลงกองหาเช่นเดิมก่อนหน้านี้ของคุณ LoginActivity, สร้างมันและล้างส่วนที่เหลือของ (ขึ้นไป) สแต็ค และเนื่องจากการเข้าสู่ระบบน่าจะอยู่ที่ด้านล่างของสแต็คตอนนี้คุณมีสแต็กว่างเปล่าและปุ่ม Back เพิ่งออกจากแอปพลิเคชัน

แต่ - ใช้งานได้เฉพาะเมื่อคุณปล่อยให้อินสแตนซ์ดั้งเดิมของ LoginActivity ยังมีชีวิตอยู่ที่ฐานของสแต็กของคุณ หากเช่นเดียวกับโปรแกรมเมอร์จำนวนมากคุณเลือกfinish()ที่LoginActivityเมื่อผู้ใช้ล็อกอินสำเร็จแล้วจะไม่อยู่บนฐานของสแต็กอีกต่อไปและFLAG_ACTIVITY_CLEAR_TOPความหมายใช้ไม่ได้ ... คุณจะสร้างใหม่LoginActivityที่ด้านบนของสแต็กที่มีอยู่ ซึ่งเกือบจะไม่ใช่สิ่งที่คุณต้องการอย่างแน่นอน (พฤติกรรมแปลก ๆ ที่ผู้ใช้สามารถ 'ถอย' ออกจากการเข้าสู่ระบบไปยังหน้าจอก่อนหน้า)

ดังนั้นถ้าคุณมีก่อนหน้านี้finish()'งคุณจะต้องไล่ตามกลไกบางอย่างสำหรับการล้างสแต็คของคุณแล้วเริ่มต้นใหม่LoginActivity LoginActivityดูเหมือนว่าคำตอบ@doreamonในหัวข้อนี้เป็นทางออกที่ดีที่สุด (อย่างน้อยต่อตาที่ต่ำต้อยของฉัน):

https://stackoverflow.com/a/9580057/614880

ฉันสงสัยอย่างยิ่งว่าความหมายที่ซับซ้อนของการที่คุณออกจาก LoginActivity ยังมีชีวิตอยู่ทำให้เกิดความสับสนมาก

โชคดี.


5
คำตอบที่ดี. เคล็ดลับ FLAG_ACTIVITY_CLEAR_TOP ที่คนส่วนใหญ่แนะนำให้ใช้เพียงใช้งานไม่ได้หากคุณลงชื่อเข้าใช้งานเสร็จแล้ว
Konsumierer

ขอบคุณสำหรับคำตอบสถานการณ์สมมติอื่น ๆ ก็เหมือนเมื่อมีเซสชัน (เช่น fb) แม้ว่าเราจะไม่เรียกกิจกรรมการเข้าสู่ระบบดังนั้นจึงไม่มีกิจกรรมการเข้าสู่ระบบในกอง แนวทางที่กล่าวมาข้างต้นนั้นไร้ประโยชน์
Prashanth Debbadwar

118

UPDATE

finishAffinity()วิธีsuper จะช่วยลดรหัส แต่บรรลุเดียวกัน มันจะเสร็จสิ้นกิจกรรมปัจจุบันเช่นเดียวกับกิจกรรมทั้งหมดในกองใช้getActivity().finishAffinity()ถ้าคุณอยู่ในส่วน

finishAffinity(); 
startActivity(new Intent(mActivity, LoginActivity.class));

คำตอบเดิม

สมมติว่า LoginActivity -> HomeActivity -> ... -> SettingsActivity call signOut ():

void signOut() {
    Intent intent = new Intent(this, HomeActivity.class);
    intent.putExtra("finish", true);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // To clean up all activities
    startActivity(intent);
    finish();
}

HomeActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    boolean finish = getIntent().getBooleanExtra("finish", false);
    if (finish) {
        startActivity(new Intent(mContext, LoginActivity.class));
        finish();
        return;
    }
    initializeView();
}

มันเหมาะกับฉันหวังว่ามันจะมีประโยชน์สำหรับคุณเช่นกัน :)


1
ฉันคิดว่าโซลูชันของคุณจะถือว่าผู้ใช้คลิกที่ signOut และกลับไปที่กิจกรรมเดียว (HomeActivity) เกิดอะไรขึ้นถ้าคุณมี 10 กิจกรรมในกองซ้อน?
IgorGanapolsky

11
หากคุณมี 10 กิจกรรมที่ด้านบนของ HomeActivity การตั้งค่าสถานะ FLAG_ACTIVITY_CLEAR_TOP จะช่วยทำความสะอาดทั้งหมด
thanhbinh84

1
สิ่งนี้สามารถใช้งานได้เมื่อเริ่มต้น HomeActivity คุณจะได้รับ OnCreate of HomeActivity การเริ่มต้นกิจกรรมภายในบ้านนั้นไม่จำเป็นว่าจะต้องสร้างขึ้นมาใหม่เว้นแต่ว่ามันจะเสร็จสิ้นหรือถูกทำลายไปแล้ว ถ้า HomeActivity ไม่จำเป็นต้องถูกสร้างขึ้นใหม่ OnCreate จะไม่ถูกเรียกและหลังจากที่คุณออกจากระบบคุณจะนั่งทำกิจกรรมที่บ้าน
topwik

1
นี่เป็นวิธีการแก้ปัญหาที่เป็นไปได้และเกี่ยวข้องกับการเข้ารหัสคุณลักษณะที่ง่าย (สำหรับผู้ใช้) เช่นการออกจากระบบ
Subin Sebastian

2
การตั้งค่าสถานะ Intent.FLAG_ACTIVITY_CLEAR_TOP ช่วยล้างกิจกรรมทั้งหมดรวมถึง HomeActivity ดังนั้นเมธอด onCreate () จะถูกเรียกเมื่อคุณเริ่มกิจกรรมนี้อีกครั้ง
thanhbinh84

73

หากคุณใช้ API 11 หรือสูงกว่าคุณสามารถลองสิ่งนี้: - FLAG_ACTIVITY_CLEAR_TASKดูเหมือนว่าจะแก้ไขปัญหาที่คุณพบ เห็นได้ชัดว่า pre-API 11 ฝูงชนจะต้องใช้การรวมกันของการมีกิจกรรมทั้งหมดตรวจสอบพิเศษตามที่ @doreamon แนะนำหรือกลอุบายอื่น ๆ

(หมายเหตุ: ในการใช้สิ่งนี้คุณต้องผ่านFLAG_ACTIVITY_NEW_TASK)

Intent intent = new Intent(this, LoginActivity.class);
intent.putExtra("finish", true); // if you are checking for this in your other Activities
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | 
                Intent.FLAG_ACTIVITY_CLEAR_TASK |
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();

1
ทำงานเหมือนจับใจ ขอบคุณมาก! เมื่อฉันพัฒนาบน min API 14 นั่นเป็นสิ่งเดียวที่จะนำไปใช้
AndyB

1
ฉันคิดว่าเราไม่ต้องการ FLAG_ACTIVITY_CLEAR_TOP เมื่อใช้โซลูชันนี้เพื่อเข้าสู่ระบบกิจกรรม
Bharat Dodeja

ฉันคิดว่าfinish();จะทำงานเพื่อป้องกันไม่ให้กลับไปหลังจากออกจากระบบ ความต้องการในการตั้งค่าสถานะคืออะไร
Pankaj

สิ่งนี้สร้างข้อยกเว้นการเรียก startActivity () จากด้านนอกของบริบทกิจกรรมต้องมีการตั้งค่าสถานะ FLAG_ACTIVITY_NEW_TASK
Aman

31

ฉันใช้เวลาสองสามชั่วโมงนี้ด้วย ... และยอมรับว่าFLAG_ACTIVITY_CLEAR_TOPดูเหมือนสิ่งที่คุณต้องการ: ล้างสแต็กทั้งหมดยกเว้นกิจกรรมที่กำลังเปิดตัวดังนั้นปุ่ม Back จะออกจากแอปพลิเคชัน แต่อย่างที่Mike Repassพูดถึง FLAG_ACTIVITY_CLEAR_TOP จะทำงานได้ก็ต่อเมื่อกิจกรรมที่คุณเปิดตัวมีอยู่แล้วในสแต็ก เมื่อกิจกรรมไม่อยู่ที่นั่นธงจะไม่ทำอะไรเลย

จะทำอย่างไร? วางกิจกรรมที่กำลังเปิดตัวในสแต็กด้วยFLAG_ACTIVITY_NEW_TASKซึ่งทำให้กิจกรรมนั้นเป็นจุดเริ่มต้นของภารกิจใหม่บนสแต็กประวัติ จากนั้นเพิ่มการตั้งค่าสถานะ FLAG_ACTIVITY_CLEAR_TOP

ตอนนี้เมื่อ FLAG_ACTIVITY_CLEAR_TOP ไปหากิจกรรมใหม่ในสแต็คมันจะอยู่ที่นั่นและถูกดึงขึ้นก่อนที่ทุกอย่างจะถูกล้างออก

นี่คือฟังก์ชันออกจากระบบของฉัน พารามิเตอร์ View เป็นปุ่มที่แนบกับฟังก์ชั่น

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}

1
จะไม่ทำงานกับ API <= 10 ตามที่FLAG_ACTIVITY_CLEAR_TASKยังไม่ได้เพิ่ม
คุณได้

1
@christinac คุณกำลังพูดถึง FLAG_ACTIVITY_CLEAR_TOP และข้อมูลโค้ดของคุณมี FLAG_ACTIVITY_CLEAR_TASK; อันไหนถูกต้อง?
แมเรียนPaździoch

10

คำตอบมากมาย อาจเป็นคนนี้จะช่วย -

Intent intent = new Intent(activity, SignInActivity.class)
                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
this.finish();

รุ่น Kotlin-

Intent(this, SignInActivity::class.java).apply {
    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.also { startActivity(it) }
finish()

4

ใช้สิ่งนี้จะเป็นประโยชน์กับคุณ คำตอบ xbakesx ที่ได้รับการแก้ไขเล็กน้อย

Intent intent = new Intent(this, LoginActivity.class);
if(Build.VERSION.SDK_INT >= 11) {
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
} else {
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
startActivity(intent);

4

ทางออกที่ยอมรับไม่ถูกต้องมีปัญหาเนื่องจากการใช้ตัวรับสัญญาณออกอากาศไม่ใช่ความคิดที่ดีสำหรับปัญหานี้ หากกิจกรรมของคุณเรียกว่า onDestroy () วิธีการคุณจะไม่ได้รับ ทางออกที่ดีที่สุดคือการมีค่าบูลีนในการตั้งค่าที่คุณแชร์และตรวจสอบในวิธี onCreate () ของ activty หากไม่ควรถูกเรียกเมื่อผู้ใช้ไม่ได้ลงชื่อเข้าใช้ให้ทำกิจกรรมให้เสร็จสิ้น นี่คือตัวอย่างรหัสสำหรับสิ่งนั้น ง่ายมากและใช้ได้กับทุกสภาวะ

protected void onResume() {
  super.onResume();
  if (isAuthRequired()) {
    checkAuthStatus();
  }
}

private void checkAuthStatus() {
  //check your shared pref value for login in this method
  if (checkIfSharedPrefLoginValueIsTrue()) {
    finish();
  }
}

boolean isAuthRequired() {
  return true;
}

1
เป็นเวลาหลายปีแล้ว แต่ฉันเชื่อว่าฉันทำทั้งสองอย่าง แต่ละกิจกรรมขยาย LoggedInActivity ซึ่งตรวจสอบสถานะการเข้าสู่ระบบของผู้ใช้ใน onCreate () LoggedInActivity ยังฟังการออกอากาศ "ผู้ใช้ออกจากระบบ" และทำทุกอย่างที่จำเป็นเพื่อตอบสนองต่อสิ่งนี้
skyler

2
ยิ่งคุณควรวาง checkAuthStatus ในonResume()methode เพราะเมื่อคุณกดปุ่มย้อนกลับกิจกรรมมีแนวโน้มที่จะดำเนินการต่อแทนที่จะสร้างขึ้น
maysi

1
@maysi ขอบคุณสำหรับคำแนะนำใช่ด้วยวิธีนี้ปุ่มย้อนกลับจะทำงานได้อย่างถูกต้องเช่นกันฉันได้อัพเดตรายการ
Yekmer Simsek

4

บางครั้งfinish()ไม่ทำงาน

ฉันได้แก้ไขปัญหานั้นแล้วด้วย

finishAffinity()


3

ฉันขอแนะนำวิธีการที่แตกต่างกับคำถามนี้ อาจไม่ใช่เครื่องที่มีประสิทธิภาพที่สุด แต่ฉันคิดว่ามันง่ายที่สุดในการใช้และต้องการรหัสน้อยมาก การเขียนรหัสถัดไปในกิจกรรมแรกของคุณ (ในกรณีที่เข้าสู่ระบบในกรณีของฉัน) จะไม่ยอมให้ผู้ใช้กลับไปที่กิจกรรมที่เปิดตัวก่อนหน้านี้หลังจากออกจากระบบ

@Override
public void onBackPressed() {
    // disable going back to the MainActivity
    moveTaskToBack(true);
}

ฉันสมมติว่า LoginActivity เสร็จสิ้นหลังจากที่ผู้ใช้ลงชื่อเข้าใช้เพื่อที่เขาจะไม่สามารถกลับไปใช้ทีหลังได้โดยการกดปุ่มย้อนกลับ แต่ผู้ใช้ต้องกดปุ่มออกจากระบบภายในแอปเพื่อที่จะออกจากระบบอย่างถูกต้อง สิ่งที่ปุ่มออกจากระบบนี้จะนำไปใช้มีจุดประสงค์ง่ายๆดังนี้:

Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();

ยินดีต้อนรับข้อเสนอแนะทั้งหมด


2

คำตอบที่เลือกนั้นฉลาดและซับซ้อน นี่คือวิธีที่ฉันทำ:

LoginActivity เป็นกิจกรรมรูทของภารกิจตั้งค่าandroid: noHistory = "true"ใน Manifest.xml; สมมติว่าคุณต้องการออกจากระบบการตั้งค่าคุณสามารถทำได้ดังนี้:

    Intent i = new Intent(SettingsActivity.this, LoginActivity.class);
    i.addFlags(IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
            | Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(i);

2

นี่คือวิธีแก้ปัญหาที่ฉันพบในแอพ

ใน LoginActivity ของฉันหลังจากประมวลผลการเข้าสู่ระบบได้สำเร็จฉันจะเริ่มต้นถัดไปใหม่ขึ้นอยู่กับระดับ API

Intent i = new Intent(this, MainActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    startActivity(i);
    finish();
} else {
    startActivityForResult(i, REQUEST_LOGIN_GINGERBREAD);
}

จากนั้นในวิธีการเข้าสู่ระบบกิจกรรมการเข้าใช้งานของฉัน:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB &&
        requestCode == REQUEST_LOGIN_GINGERBREAD &&
        resultCode == Activity.RESULT_CANCELED) {
    moveTaskToBack(true);
}

ในที่สุดหลังจากประมวลผลออกจากระบบในกิจกรรมอื่น ๆ :

Intent i = new Intent(this, LoginActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

เมื่ออยู่ใน Gingerbread ทำเช่นนั้นถ้าฉันกดปุ่มย้อนกลับจาก MainActivity แล้ว LoginActivity จะถูกซ่อนทันที ใน Honeycomb และใหม่กว่าฉันเพิ่งเสร็จสิ้น LoginActivity หลังจากประมวลผลการเข้าสู่ระบบและมันถูกสร้างขึ้นใหม่อย่างเหมาะสมหลังจากประมวลผลออกจากระบบ


มันไม่ทำงานสำหรับฉัน ในกรณีของฉันฉันใช้ fragmentactivity ไม่เรียกใช้เมธอด Onactivityresult
โมฮาเหม็ดอิบราฮิม

1

สิ่งนี้ใช้ได้กับฉัน:

     // After logout redirect user to Loing Activity
    Intent i = new Intent(_context, MainActivity.class);
    // Closing all the Activities
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

    // Add new Flag to start new Activity
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    // Staring Login Activity
    _context.startActivity(i);

คุณช่วยอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับโซลูชันที่คุณให้ได้ไหม
abarisone

0

เริ่มกิจกรรมของคุณด้วย StartActivityForResult และในขณะที่คุณออกจากระบบตั้งค่าผลลัพธ์ของคุณและผลลัพธ์ของคุณก็จบกิจกรรม

intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivityForResult(intent, BACK_SCREEN);

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
    case BACK_SCREEN:
        if (resultCode == REFRESH) {
            setResult(REFRESH);
            finish();
        }
        break;
    }
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        AlertDialog alertDialog = builder.create();

        alertDialog
                .setTitle((String) getResources().getText(R.string.home));
        alertDialog.setMessage((String) getResources().getText(
                R.string.gotoHome));
        alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,
                            int whichButton) {

                        setResult(REFRESH);
                        finish();
                    }

                });

        alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,
                            int whichButton) {
                    }
                });
        alertDialog.show();
        return true;
    } else
        return super.onKeyDown(keyCode, event);

}

0

โซลูชัน @doreamon ที่ให้มาใช้ได้ดีสำหรับทุกกรณียกเว้นกรณีเดียว:

หากหลังจากเข้าสู่ระบบผู้ใช้หน้าจอการเข้าสู่ระบบการฆ่าจะนำทางไปยังหน้าจอกลางโดยตรง เช่นในการไหลของ A-> B-> C นำทางเช่น: เข้าสู่ระบบ -> B -> C -> กดทางลัดไปที่บ้าน การใช้ FLAG_ACTIVITY_CLEAR_TOP จะลบเฉพาะกิจกรรม C เท่านั้นเนื่องจาก Home (A) ไม่ได้อยู่ในประวัติสแต็ก การกดย้อนกลับบนหน้าจอจะนำเรากลับไปที่ B

เพื่อจัดการกับปัญหานี้เราสามารถเก็บ stack กิจกรรม (Arraylist) และเมื่อกดที่บ้านเราจะต้องฆ่ากิจกรรมทั้งหมดใน stack นี้


0

เป็นไปได้ด้วยการจัดการการตั้งค่าสถานะใน SharedPreferences หรือในแอปพลิเคชันกิจกรรม

เมื่อเริ่มต้นแอพ (บนหน้าจอ Splash) ให้ตั้งค่า flag = false เมื่อออกจากระบบคลิกเหตุการณ์เพียงตั้งค่าสถานะเป็นจริงและใน OnResume () ของทุกกิจกรรมตรวจสอบว่าการตั้งค่าสถานะเป็นจริงแล้วโทรเสร็จสิ้น ()

มันใช้งานได้เหมือนมีเสน่ห์ :)


0

เมื่อคลิกออกจากระบบคุณอาจเรียกสิ่งนี้ได้

private void GoToPreviousActivity() {
    setResult(REQUEST_CODE_LOGOUT);
    this.finish();
}

onActivityResult () ของกิจกรรมก่อนหน้าเรียกรหัสนี้ด้านบนอีกครั้งจนกว่าคุณจะเสร็จสิ้นกิจกรรมทั้งหมด


1
ซึ่งหมายความว่ามันต้องผ่านทุกกิจกรรมเชิงเส้นแทนที่จะออกอากาศเสร็จสิ้น () ทั้งหมดในครั้งเดียว
IgorGanapolsky

@Igor G. ใช่มันเป็นวิธีทางเลือกในการทำลำดับให้เสร็จสมบูรณ์
Mak

-1

ทางเลือกหนึ่งคือให้มีการตรวจสอบสถานะการเข้าสู่ระบบ onCreate ของแต่ละกิจกรรมและเสร็จสิ้น () หากไม่ได้ลงชื่อเข้าใช้ ฉันไม่ชอบตัวเลือกนี้เนื่องจากปุ่มย้อนกลับจะยังคงใช้งานได้นำทางกลับเป็นกิจกรรมที่ปิดตัวเอง

สิ่งที่คุณต้องการทำคือการโทรออกจากระบบ () และเสร็จสิ้น () บนเมธอด onStop () หรือ onPause () ของคุณ สิ่งนี้จะบังคับให้ Android เรียกใช้ onCreate () เมื่อกิจกรรมถูกนำกลับมาใช้ใหม่เนื่องจากมันจะไม่อยู่ในสแต็กของกิจกรรมอีกต่อไป จากนั้นทำตามที่คุณพูดใน onCreate () ตรวจสอบสถานะการเข้าสู่ระบบและส่งต่อไปยังหน้าจอเข้าสู่ระบบหากไม่ได้เข้าสู่ระบบ

อีกสิ่งที่คุณสามารถทำได้คือการตรวจสอบสถานะการเข้าสู่ระบบใน onResume () และหากไม่ได้เข้าสู่ระบบให้เสร็จสิ้น () และเปิดกิจกรรมการเข้าสู่ระบบ


ฉันไม่ต้องการออกจากระบบในแต่ละกิจกรรมหยุดชั่วคราวหรือหยุด นอกจากนี้แอปพลิเคชันเริ่มต้นออกจากระบบหรือเข้าสู่ระบบดังนั้นฉันไม่จำเป็นต้องตรวจสอบว่าเข้าสู่ระบบจริง ๆ
skyler

@Ricardo: โซลูชันของคุณไม่ต้องการ BroadcastReceiver ใช่ไหม
IgorGanapolsky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.