পুরো ইতিহাসের স্ট্যাক সাফ করুন এবং অ্যান্ড্রয়েডে একটি নতুন ক্রিয়াকলাপ শুরু করুন


332

স্ট্যাকের উপরে কোনও ক্রিয়াকলাপ শুরু করা, পুরো ইতিহাসটি পরিষ্কার করার আগেই কি এটি সম্ভব?

পরিস্থিতি

আমার কাছে একটি ক্রিয়াকলাপের স্ট্যাক রয়েছে যা হয়-> বি-> সি বা বি-> সি যায় (স্ক্রিন এ ব্যবহারকারীদের টোকেন নির্বাচন করে তবে অনেক ব্যবহারকারীর কাছে কেবল একটিমাত্র টোকেন থাকে)।

স্ক্রিন সিতে ব্যবহারকারী কোনও পদক্ষেপ নিতে পারে যা স্ক্রিন বিকে অবৈধ করে তোলে তাই অ্যাপ্লিকেশনটি ইতিমধ্যে স্ট্যাকের মধ্যে নেই কিনা তা বিবেচনা না করেই এগুলি স্ক্রিন এ এ নিতে চায়। আমার অ্যাপ্লিকেশনটিতে স্ট্যাকের একমাত্র আইটেমটি স্ক্রিন এ হওয়া উচিত।

মন্তব্য

আরও অনেক অনুরূপ প্রশ্ন রয়েছে, তবে আমি এই সঠিক প্রশ্নের উত্তর দেয় এমন কিছুই পাই না। আমি কল করার চেষ্টা করেছি getParent().finish()- এর ফলে সর্বদা শূন্য পয়েন্টার ব্যতিক্রম হয়। FLAG_ACTIVITY_CLEAR_TOPক্রিয়াকলাপটি ইতিমধ্যে স্ট্যাকের মধ্যে থাকলে কেবলমাত্র কাজ করে।

উত্তর:


658

এপিআই স্তরের ১১-তে একটি নতুন ইন্টেন্ট ফ্ল্যাগ যুক্ত করা হয়েছে কেবল এটির জন্য: ইনটেন্ট.এফএলএজি_এটিটিভিটি_সিএলএইআর

কেবল পরিষ্কার করতে, এটি ব্যবহার করুন:

জাভা

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);


Kotlin

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK


দুর্ভাগ্যক্রমে এপিআই lvl <= 10 এর জন্য, আমি এখনও এর কোনও পরিষ্কার সমাধান খুঁজে পাইনি। "DontHackAndroidLikeThis" সমাধান প্রকৃতপক্ষে বিশুদ্ধ গোরুর গাড়ি নেই। আপনার এটা করা উচিৎ না. :)

সম্পাদনা: @ বেন পিয়ারসনের মন্তব্য অনুসারে, এপিআই <= 10 এর জন্য এখন কেউ ইনট্যান্টকম্যাট ক্লাস ব্যবহার করতে পারে । IntentCompat.FLAG_ACTIVITY_CLEAR_TASKটাস্ক সাফ করার জন্য কেউ পতাকা ব্যবহার করতে পারে । সুতরাং আপনি 11 টি প্রাক এপিআই স্তরের সমর্থন করতে পারেন।


23
কেবল স্পষ্ট করার জন্য, এটি ব্যবহার করুন: intent.setFlags (ইনটেন্ট.এফএলএজি_এসিটিভিটি_নিউব_টাস্ক | ইনটেন্ট.এফএলএজি_এসিটিভিটি_সিএলএইআর_এসএসি);
ব্যবহারকারী 123321

2
Intent.FLAG_ACTIVITY_NEW_TASK না করে অ্যাপ্লিকেশান কখনও কখনও তে Android 4 নিজেই বন্ধ
max4ever

22
ইন্টেন্টকম্পেটের এখন টাস্কটি সাফ করার জন্য একটি পতাকা রয়েছে, তাই আপনি পূর্ব এপিআই স্তরের 11 - ডেভেলপার.অ্যান্ড্রয়েড
বেন পিয়ারসন

10
ইনট্যান্টকম্প্যাট.এফএলএজি_এসিটিভিটি_সিএলআর_এইএসপি < ডিভেলপার.অ্যান্ড্রয়েড
অ্যান্ড্রয়েড /

7
ইন্টেন্টকম্পেটের পতাকাটি কেবল একটি ক্র্যাশ এড়ানোর জন্য, তবে @ ডেভিড যেমন বলেছেন তেমন কিছুই করেন না।
18:44

49

কেস 1: কেবল দুটি এবং ক্রিয়াকলাপ:

এখানে ক্রিয়াকলাপ প্রবাহ হ'ল-> বি। বি থেকে ব্যাকবটনে ক্লিক করার পরে আমাদের অ্যাপ্লিকেশনটি বন্ধ করতে হবে তখন কেবলমাত্র কল ফিনিস থেকে ক্রিয়াকলাপ বি শুরু করার সময় এটি অ্যান্ড্রয়েডকে অ্যাক্টিভিটি এ ব্যাকস্ট্যাক.ইগ এ অ্যাক্টিভিটি এ স্টোর করা থেকে আটকাবে is অ্যাপ্লিকেশনটির লডিং / স্প্ল্যাশ স্ক্রিন।

Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();

কেস 2: দুটি অ্যাক্টিভিটি:

যদি অ-> বি-> সি-> ডি-> বি এর মতো প্রবাহ থাকে এবং ক্রিয়াকলাপ ডি থেকে আসার সময় অ্যাক্টিভিটি বিতে ফিরে আসা বোতামটি ক্লিক করার ক্ষেত্রে সেই ক্ষেত্রে আমাদের ব্যবহার করা উচিত।

Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);

এখানে উদ্বেগ বিটি ইনস্টেন্টের কারণে কোনও নতুন উদাহরণের চেয়ে ব্যাকস্ট্যাক থেকে শুরু করা হবে F ফ্ল্যাজ_এসিটিভিটি_স্লেয়ার_টপ এবং ইন্টেন্ট F


2
এটি আমার পক্ষে কাজ করেছে। আমি সমস্ত কার্যক্রম সেই পতাকাগুলি রেখেছি fla এই ক্রিয়াকলাপগুলিতে ব্যাক বোতামগুলি পুরোপুরি পূর্ববর্তী ক্রিয়াকলাপে কাজ করে এবং মূল ক্রিয়াকলাপের সাথে ইনটেন্ট ইন্টেন্ট = নতুন ইন্টেন্ট (ইনটেন্ট.এ্যাকশন_গ্রাভ); intent.addCategory (Intent.CATEGORY_HOME); intent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK); startActivity (অভিপ্রায়); শেষ (); পুরো অ্যাপটি বন্ধ রয়েছে, এখনও স্মৃতিতে রয়েছে তবে কোনও সক্রিয় নেই এবং আপনি যদি অ্যাপ্লিকেশনটি পুনরায় চালু করেন তবে স্প্ল্যাশ স্ক্রিনে যায় :)
রকো

এটি সেরা উত্তর হওয়া উচিত। আমার সাথে যদি কারওর মতো দৃশ্য থাকে: এ-> বি-> সি-> ডি-> ই -> (বি) থেকে ই-> বি এর ফলস্বরূপ হওয়া উচিত: এ-> বি
শেম আলেকিস চাভেজ

39

অ্যান্ড্রয়েডের নতুন সংস্করণ> = এপিআই 16 ব্যবহার সহ finishAffinity()

পন্থা> = API 16 এর জন্য উপযুক্ত suitable

Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
  • এটি নতুন ক্রিয়াকলাপ শুরু করার মতো এবং সমস্ত স্ট্যাক সাফ করার মতো।
  • অথবা মেইনএ্যাকটিভিটি / ফার্স্টঅ্যাক্টিভিটিতে পুনঃসূচনা করুন।

1
এটি কৌশলটি করেছে, পতাকাগুলি আমার জন্য 4. xxx এ কাজ করছে না এবং এটি পুরোপুরি কাজ করেছে! ধন্যবাদ
জোনাথন আস্তে

1
আপনার লক্ষ্যটি নীচে এবং বর্তমান ক্রিয়াকলাপ সহ সমস্ত ক্রিয়াকলাপ শেষ করা এবং তাদের নিজস্ব কার্যক্রমে একটি নতুন ক্রিয়াকলাপ শুরু করা যদি সঠিক উত্তর বলে মনে হয়।
টুবি

24

আমি এটিতেও কয়েক ঘন্টা ব্যয় করেছি ... এবং সম্মত হলাম যে FLAG_ACTIVITY_CLEAR_TOP আপনি যা চান তা মনে হচ্ছে: ক্রিয়াকলাপটি চালু করা ছাড়া পুরো স্ট্যাকটি সাফ করুন, সুতরাং পিছনের বোতামটি অ্যাপ্লিকেশনটি থেকে প্রস্থান করে। তবুও মাইক রেপাস যেমন উল্লেখ করেছেন, FLAG_ACTIVITY_CLEAR_TOP কেবল তখনই কাজ করে যখন আপনি যে কার্যকলাপটি চালু করছেন তা ইতিমধ্যে স্ট্যাকের মধ্যে রয়েছে; ক্রিয়াকলাপটি সেখানে না থাকলে পতাকাটি কিছুই করে না।

কি করো? এফএলজি_এসিটিভিটি_এনইউউডিওয়াসক দিয়ে স্ট্যাকটিতে যে ক্রিয়াকলাপটি চালু হচ্ছে তা রাখুন, যা সেই ক্রিয়াকলাপটিকে ইতিহাস স্ট্যাকের উপর একটি নতুন টাস্কের সূচনা করে। তারপরে FLAG_ACTIVITY_CLEAR_TOP পতাকা যুক্ত করুন।

এখন, যখন FLAG_ACTIVITY_CLEAR_TOP স্ট্যাকের মধ্যে নতুন ক্রিয়াকলাপটি সন্ধান করতে যায়, তখন সেখানে উপস্থিত থাকবে এবং সমস্ত কিছু সাফ হওয়ার আগে এটি টেনে নেওয়া হবে।

এখানে আমার লগআউট ফাংশন; ভিউ প্যারামিটার হ'ল বোতামটি যাতে ফাংশনটি সংযুক্ত থাকে।

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
আপনি কি CLEAR_TOP এর পরিবর্তে CLEAR_TASK বলতে চাচ্ছেন?
অ্যান্ডি

14

আপনি স্ট্যাক পরিবর্তন করা উচিত নয়। অ্যান্ড্রয়েড ব্যাক বোতামটি কোনও ওয়েব ব্রাউজারের মতো কাজ করা উচিত।

আমি এটি করার একটি উপায় সম্পর্কে ভাবতে পারি, তবে এটি বেশ হ্যাক।

  • আপনার ক্রিয়াকলাপগুলি singleTaskউদাহরণটিতে যুক্ত করে এটি করুন AndroidManifest :

    <activity android:name=".activities.A"
              android:label="@string/A_title"
              android:launchMode="singleTask"/>
    
    <activity android:name=".activities.B"
              android:label="@string/B_title"
              android:launchMode="singleTask"/>
  • Applicationকোনটি প্রসারিত করুন যেখানে কোথায় যেতে হবে তার যুক্তি রাখবে।

উদাহরণ:

public class DontHackAndroidLikeThis extends Application {

  private Stack<Activity> classes = new Stack<Activity>();

  public Activity getBackActivity() {
    return classes.pop();
  }

  public void addBackActivity(Activity activity) {
    classes.push(activity);
  }
}

এ থেকে বি পর্যন্ত:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class); 
startActivity(this, B.class);

বি থেকে সি পর্যন্ত:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class); 
startActivity(this, C.class);

সি তে:

If ( shouldNotGoBackToB() ) {
  DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
  app.pop();
}

এবং pop()স্ট্যাক থেকে পিছনে বোতামটি হ্যান্ডেল করুন ।

আবারও, আপনার এটি করা উচিত নয় :)


শেষ পর্যন্ত আমি স্ট্যাকটি অক্ষত রেখে কেবল ব্যবহারকারীকে বলব যে তাদের বর্তমান স্ক্রিনটি অবৈধ ছিল
কেসব্যাশ

1
খুব হতাশাজনক যে অ্যান্ড্রয়েড আমাদের এইভাবে ইতিমধ্যে ক্রিয়াকলাপ স্ট্যাক পরিচালনা করতে দেয় না। আমি আমার ভবিষ্যতের অ্যান্ড্রয়েড অ্যাপ্লিকেশনগুলিতে এই সমাধানটি ব্যবহার করতে প্রলুব্ধ হব।
সিফ্রন

4
কেন এটি ব্যবহার করা উচিত নয় তা পরিষ্কার করে বলা: এটি মেমরি ফুটো তৈরির একটি দুর্দান্ত উপায়। এক পর্যায়ে ওএস ব্যাকগ্রাউন্ড ক্রিয়াকলাপগুলি মেরে ফেলার সিদ্ধান্ত নিতে পারে, তবে যেহেতু Applicationউদাহরণস্বরূপ ওএস গ্রহণ করে তবে ওএস সেই র‌্যামটি ধ্বংস হওয়া ক্রিয়াকলাপ থেকে মুক্ত করতে সক্ষম হবে না।
ভিট খুডেনকো

@আরহিমডে কি অন্যান্য সমস্যা আছে? কেবল দুর্বল রেফারেন্স রেখে স্মৃতি ফাঁস হওয়া যায়।
নবীন

1
@ নবীন হ্যাঁ, দুর্বল রেফ দিয়ে ফাঁস এড়ানো যেতে পারে, তবে জিসির পরে যদি কোনও লাইভ অ্যাক্টিভিটি রেফ না পাওয়া যায় তবে পুরো পন্থাটি অকেজো। আবারও - এটি করবেন না, এটি অ্যান্ড্রয়েডের জন্য একটি ভুল পদ্ধতির।
ভিট খুডেনকো

12

আপনি কোনও নতুন ক্রিয়াকলাপ শুরু করার সাথে সাথেই ব্যবহার করে startActivityনিশ্চিত হয়ে নিন যে আপনি কল করেছেন finish()যাতে বর্তমানের কার্যকলাপটি নতুনটির পিছনে স্ট্যাক না হয়।


+1 একটি নির্দিষ্ট পরিস্থিতিতে ঠিক এক ক্রিয়াকলাপটিকে ইতিহাসের স্ট্যাকের উপরে রাখা মৌমাছি থেকে রোধ করার জন্য দুর্দান্ত সমাধান।
মার্শবার

27
স্ট্যাকের মধ্যে যদি আপনার একাধিক কার্যকলাপ থাকে তবে কাজ করে না
শেষটি

5

এটা চেষ্টা কর:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();

4

উন্নত পুনঃব্যবহারযোগ্য কোটলিন:

আপনি সেটার পদ্ধতিটি ব্যবহার করে সরাসরি পতাকাটি সেট করতে পারেন। Kotlin ইন orহয় প্রতিস্থাপন জাভা, bitwise বা |

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

আপনি যদি এটি নিয়মিত ব্যবহারের পরিকল্পনা করেন তবে একটি উদ্দেশ্য এক্সটেনশন ফাংশন তৈরি করুন

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

এরপরে অভিপ্রায় শুরু করার আগে আপনি সরাসরি এই ফাংশনটিতে কল করতে পারেন

intent.clearStack()

আপনার যদি অন্য পরিস্থিতিতে অতিরিক্ত পতাকা যুক্ত করার বিকল্পের প্রয়োজন হয় তবে এক্সটেনশন ফাংশনে একটি alচ্ছিক পরম যুক্ত করুন।

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}


2

কোড নীচে চেষ্টা করুন,

Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK| 
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

যদি এই ক্রিয়াকলাপটির মতো আপডেট করা হয় তবে আবার এপিআই কল করুন তবে পূর্বে বিদ্যমান সমস্ত স্ট্যাটাক সাফ হয়ে গেছে
হর্ষ

2

আমার জন্য কেউ উপরে পদ্ধতির কাজ নয়।

পূর্ববর্তী সমস্ত ক্রিয়াকলাপ সাফ করার জন্য কেবল এটি করুন :

finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)

-1

কখনও কখনও আপনার অ্যান্ড্রয়েড এমুলেটর গ্রহন ডিডিএমএস সরঞ্জামটি সংযোগ করতে ব্যর্থ হতে পারে এবং ম্যানুয়ালি অ্যাডাবির কাছে যেতে অনুরোধ করে। সেক্ষেত্রে আপনি কমান্ড প্রম্পটটি ব্যবহার করে অ্যাডবি শুরু করতে বা বন্ধ করতে পারেন।


1
কখনও কখনও আপনার অ্যান্ড্রয়েড এমুলেটর গ্রহন ডিডিএমএস সরঞ্জামটি সংযোগ করতে ব্যর্থ হতে পারে এবং ম্যানুয়ালি অ্যাডাবির কাছে যেতে অনুরোধ করে। সেক্ষেত্রে আপনি কমান্ড প্রম্পটটি ব্যবহার করে অ্যাডবি শুরু করতে বা বন্ধ করতে পারেন। ইন্টেন্ট i = নতুন ইনটেন্ট (OldActivity.this, NewActivity.class); // নতুন টাস্কটি সেট করুন এবং ফ্ল্যাগগুলি সাফ করুন
রাজেশকুমারজি

-2

আমি দেখতে পেয়েছি খুব সহজ হ্যাক এই AndroidManifestহিসাবে নতুন উপাদান যোগ করুন : -

<activity android:name=".activityName"
          android:label="@string/app_name"
          android:noHistory="true"/>

android:noHistoryস্ট্যাক থেকে আপনার অবাঞ্ছিত কার্যকলাপ সাফ করবে।


2
আপনি যদি এই ক্রিয়াকলাপের জন্য অনুমতি চেয়ে থাকেন তবে এই অ্যাপ্রোচমেন্ট Android 6.0+ এ সমস্যার কারণ হতে পারে।
ভিতালিয়া এ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.