Ý định rõ ràng


111

Ứng dụng Android của tôi đang được gọi bởi một mục đích đang chuyển thông tin (đang chờ xử lý trên thanh trạng thái).

Khi tôi nhấn nút trang chủ và mở lại ứng dụng của mình bằng cách giữ nút trang chủ, nó sẽ gọi lại ý định và các tính năng bổ sung tương tự vẫn ở đó.

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
      super.onSaveInstanceState(savedInstanceState);
    }
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
      super.onRestoreInstanceState(savedInstanceState);
    }

đây là mã không chạy như nó phải

    String imgUrl;
    Bundle extras = this.getIntent().getExtras();


    if(extras != null){
        imgUrl = extras.getString("imgUrl");
        if( !imgUrl.equals(textView01.getText().toString()) ){

            imageView.setImageDrawable( getImageFromUrl( imgUrl ) );
            layout1.setVisibility(0);
            textView01.setText(imgUrl);//textview to hold the url

        }

    }

Và ý định của tôi:

public void showNotification(String ticker, String title, String message, 
    String imgUrl){
    String ns = Context.NOTIFICATION_SERVICE;
    NotificationManager mNotificationManager = 
        (NotificationManager) getSystemService(ns);
    int icon = R.drawable.icon;        // icon from resources
    long when = System.currentTimeMillis();         // notification time
    CharSequence tickerText = ticker;              // ticker-text

    //make intent
    Intent notificationIntent = new Intent(this, activity.class);
    notificationIntent.putExtra("imgUrl", imgUrl);
    notificationIntent.setFlags(
        PendingIntent.FLAG_UPDATE_CURRENT | 
        PendingIntent.FLAG_ONE_SHOT);
    PendingIntent contentIntent = 
        PendingIntent.getActivity(this, 0, 
        notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | 
        PendingIntent.FLAG_ONE_SHOT);

    //make notification
    Notification notification = new Notification(icon, tickerText, when);
    notification.setLatestEventInfo(this, title, message, contentIntent);
    //flags
    notification.flags = Notification.FLAG_SHOW_LIGHTS | 
        Notification.FLAG_ONGOING_EVENT | 
        Notification.FLAG_ONLY_ALERT_ONCE | 
        Notification.FLAG_AUTO_CANCEL;
    //sounds
    notification.defaults |= Notification.DEFAULT_SOUND;
    //notify
    mNotificationManager.notify(1, notification);
}

Có cách nào để xóa ý định hoặc kiểm tra xem nó đã được sử dụng trước đó chưa?


Bạn có thể đăng mã của bạn?
xandy

Tôi đã thêm mã vào câu hỏi của mình
Mars

Thay vì xóa Intent, bạn có thể xác định loại khởi chạy và xử lý luồng ứng dụng cho phù hợp. Chỉ nhận được Phần bổ sung nếu nó được khởi chạy cho thông báo và không chạy từ nền. stackoverflow.com/questions/4116110/clearing-intent/…
BB

Câu trả lời:


168

CẬP NHẬT:

Tôi đã không nhận ra rằng câu trả lời này sẽ được nhắc đến nhiều như vậy khi lần đầu tiên tôi viết nó cách đây hơn 5 năm!

Tôi sẽ làm rõ để chỉ ra rằng theo câu trả lời của @ tato-rodrigo, điều này sẽ không giúp bạn phát hiện ra một ý định đã được xử lý trong một số tình huống.

Ngoài ra, tôi nên chỉ ra rằng tôi đặt "rõ ràng" trong dấu ngoặc kép vì một lý do - bạn không thực sự xóa ý định bằng cách làm điều này, bạn chỉ đang sử dụng việc xóa phần thừa như một lá cờ rằng ý định này đã được hoạt động nhìn thấy. .


Tôi đã có chính xác cùng một vấn đề.

Câu trả lời trên đưa tôi đi đúng hướng và tôi tìm thấy giải pháp đơn giản hơn, sử dụng:

getIntent().removeExtra("key"); 

gọi phương thức để "xóa" Intent.

Câu trả lời hơi muộn vì điều này đã được hỏi một năm trước, nhưng hy vọng điều này sẽ giúp ích cho những người khác trong tương lai.


4
phương thức removeExtra () có tham số String không? như thế này getIntent (). removeExtra ("String");
tony9099

25
@Maks Tôi có thể sai nhưng tôi nghĩ điều này sẽ không hoạt động trong trường hợp sau: 1) Mở hoạt động thông qua thông báo; 2) Kết thúc hoạt động bằng cách nhấn nút quay lại; 3) Mở lại hoạt động thông qua Lịch sử (Ứng dụng gần đây). Một trường hợp khác là khi hệ thống giết ứng dụng do thiếu tài nguyên (bật "Không giữ hoạt động" theo tùy chọn của nhà phát triển và sau đó chỉ cần nhấn home rồi mở lại hoạt động từ Lịch sử). Tôi đã đăng giải pháp tôi đang sử dụng bên dưới. Nếu bạn có thể bình luận về điều này sẽ tốt.
tato.rodrigo

2
Thật không may, nó không hoạt động cho chúng tôi. Chúng tôi nhận thấy rằng việc bắt đầu một hoạt động mới mà từ đó bắt đầu hoạt động ban đầu sẽ khiến OnNewIntent kích hoạt lại với cùng mục đích.
Le-roy Staines

2
Thay vì xóa Intent, bạn có thể xác định loại khởi chạy và xử lý luồng ứng dụng cho phù hợp. Chỉ nhận được Phần bổ sung nếu nó được khởi chạy cho thông báo và không chạy từ nền. stackoverflow.com/questions/4116110/clearing-intent/…
BB

2
Không làm việc cho tôi. Tôi đang gặp phải vấn đề tương tự như @ tato.rodrigo đã đề cập trong đó ý định không được xóa nếu hoạt động được mở thông qua thông báo hoặc từ lịch sử hoặc các lý do khác mà anh ấy đã đề cập, vì vậy những gì tôi đã làm sau khi sử dụng thông tin mục đích là đặt lại mục đích như điều này setIntent(new Intent())và nó đang hoạt động tốt.
Shubhral

43

CHỈNH SỬA: Tôi đang chỉnh sửa để đăng giải pháp hoàn chỉnh mà tôi đang sử dụng.

Giải pháp này sẽ hoạt động nếu sự cố là "Không thực thi một số mã khi hoạt động bắt đầu từ Lịch sử (Ứng dụng gần đây)" .

Trước hết, hãy khai báo a booleantrong your Activityđể cho biết liệu cái Intentđã được tiêu thụ chưa:

    private boolean consumedIntent;

Sau đó, lưu trữ và khôi phục giá trị này một cách an toàn bằng cách sử dụng onSaveInstanceStateonCreatecác phương pháp để xử lý các thay đổi cấu hình và các trường hợp mà hệ thống có thể giết chết bạn Activitykhi nó ở chế độ nền.

    private final String SAVED_INSTANCE_STATE_CONSUMED_INTENT = "SAVED_INSTANCE_STATE_CONSUMED_INTENT";

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(SAVED_INSTANCE_STATE_CONSUMED_INTENT, consumedIntent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //set content view ...

        if( savedInstanceState != null ) {
            consumedIntent = savedInstanceState.getBoolean(SAVED_INSTANCE_STATE_CONSUMED_INTENT);
        }

        //other initializations
    }

Bây giờ, hãy kiểm tra xem bạn có thể chạy mã của mình theo onResumephương pháp hay không.

    @Override
    protected void onResume() {
        super.onResume();

        //check if this intent should run your code
        //for example, check the Intent action
        boolean shouldThisIntentTriggerMyCode = [...];
        Intent intent = getIntent();
        boolean launchedFromHistory = intent != null ? (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0 : false;
        if( !launchedFromHistory && shouldThisIntentTriggerMyCode && !consumedIntent ) {
            consumedIntent = true;
            //execute the code that should be executed if the activity was not launched from history
        }
    }

Ngoài ra, nếu của bạn Activityđược định cấu hình thành singleTop, bạn nên đặt lại cờ của mình khi cờ mới Intentđược phân phối.

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        consumedIntent = false;
    }

12
Cảm ơn rất nhiều! Tôi đã giúp mã này (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)nên bây giờ tôi có thể tìm ra thời điểm bắt đầu hoạt động từ lịch sử và tôi có thể bỏ qua các tính năng bổ sung của mình.
Roman Nazarevych

1
@Lemberg Tôi có cùng một vấn đề và tôi đã giải quyết giống như bạn, Nếu bạn sử dụng một số tính năng bổ sung đến từ thông báo đẩy, sẽ có nguy cơ bắt đầu hoạt động của bạn từ lịch sử và luôn sử dụng các tính năng bổ sung của bạn và chuyển hướng đến hành động tương tự như của bạn thông báo đẩy. Các launchedFromHistory cờ có thể giúp bạn biết điều này
Stoycho Andreev

nó sẽ hoạt động ngay cả khi hoạt động bị phá hủy và chúng tôi mở lại nó từ ngăn xếp lịch sử?
25

tuyệt quá! nó có vẻ làm việc ngay cả khi ứng dụng đã bị phá hủy ... nhưng xin @ tato.rodrigo remove boolean shouldThisIntentTriggerMyCode = [...];từ câu trả lời (những gì được sử dụng cho?)
user25

Trong trường hợp của tôi với nhiều thông báo cho người dùng nhất định đó là người dùng tốt hơn consumedIntentStringchứa thông báo Uid. Có thể chỉ cần thêm Uid này vào thông báo ở phần phụ trợ dưới dạng dấu thời gian hiện tại. Ngoài ra, bạn chỉ nên lưu Uid này onSaveInstanceStatekhi Intent đã được hình thành onCreate. Điều này có nghĩa là bạn không nên lưu Uid khỏi onNewIntent.
Konstantin Konopko

22

Câu trả lời của Maks hoạt động để xóa thêm:

    getIntent().removeExtra("key"); 

Một lệnh hữu ích khác là:

    getIntent().setAction("");

Bạn cũng có thể gắn thẻ một ý định bằng cách gọi:

    getIntent().putExtra("used", true);

và sau đó chỉ cần kiểm tra giá trị.


21

Khi chúng tôi khởi chạy ứng dụng Android từ Lịch sử (Ứng dụng gần đây), ứng dụng có thể được khởi chạy với chủ yếu là ba cờ Ý định khác nhau.

  1. FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
    Đây là khi hoạt động đang được khởi chạy từ lịch sử của một ứng dụng đã được thu nhỏ (nhấn và giữ phím home).
    Giá trị hằng số: 1048576 (0x00100000)
  2. FLAG_ACTIVITY_NEW_TASK
    Đây là khi hoạt động được khởi chạy thông qua "nhấp vào biểu tượng ứng dụng" hoặc qua " Bộ lọc ý định ". Ở đây hoạt động sẽ trở thành phần bắt đầu của một nhiệm vụ mới trên ngăn xếp lịch sử này.
    Giá trị không đổi: 268435456 (0x10000000)
  3. FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | FLAG_ACTIVITY_NEW_TASK
    Đây là khi ứng dụng bị thoát bằng cách nhấn nút quay lại và sau đó tiếp tục từ Lịch sử (ứng dụng gần đây).
    Giá trị không đổi: 269484032 (0x10100000)

Giá trị không đổi có thể được truy xuất qua getIntent().getFlags()

Trong trường hợp thứ ba, Android tải lại các giá trị Intent cuối cùng từ bộ nhớ của nó. Vì vậy, ý định của ứng dụng ( getIntent) sẽ có các giá trị từ ý định cuối cùng đã khởi chạy ứng dụng.

Trên thực tế, ứng dụng sẽ hoạt động như thể nó là một lần ra mắt mới, với các giá trị ý định cho một lần ra mắt mới hơn là các giá trị ý định của lần khởi chạy trước đó. Hành vi này có thể được nhìn thấy nếu bạn khởi chạy ứng dụng bằng cách nhấp vào biểu tượng ứng dụng, nó sẽ không bao giờ có các giá trị mục đích cũ. Điều này là do, Android sử dụng bộ lọc ý định sau cho trường hợp này

 <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER"/>
 </intent-filter>

Nhưng trong trường hợp thứ ba (Ứng dụng đã bị thoát, được khởi chạy từ Lịch sử ứng dụng gần đây), hệ điều hành Android sử dụng ý định cuối cùng đã khởi chạy ứng dụng trước khi thoát (thông qua nhấn nút quay lại). Vì vậy, bạn sẽ có các giá trị mục đích cũ và luồng ứng dụng không phù hợp.

Loại bỏ ý định là một cách để giải quyết nó, nhưng nó sẽ không giải quyết được vấn đề hoàn toàn! Do hệ điều hành Android tải lại Ý định từ lần khởi chạy ứng dụng lần cuối chứ không phải trường hợp cuối cùng của ý định khởi chạy.

Một cách rõ ràng để tránh điều này xảy ra, là xử lý nó bằng cách lấy loại Ý định để xác định loại khởi chạy.

Vì vậy, trong LaunchActivity của bạn (Một trong đó có các bộ lọc ý định theo quy định tại manifest), bạn có thể sử dụng đoạn mã sau trong onCreate(), onStart()hoặc onResume()phương pháp.

if(getIntent().getFlags() == (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)) {
    //app is launched from recent apps after it was closed
        normalLaunch();
    } else {
        String intentAction = getIntent().getAction();
        String scheme = getIntent().getScheme();
        //app is launched via other means
        // URL intent scheme, Intent action etc
        if("https".equalsIgnoreCase(scheme)) {
            // URL intent for browser
        } else if("com.example.bb".equalsIgnoreCase(intentAction)) {
            // App launched via package name
        } else {
            // App was launched via Click on App Icon, or other means
            normalLaunch();
        }
    }

Tôi cho rằng normalLaunch(), không nên sử dụng các tham số từ Intent; nếu không, bạn sẽ cần phải tách biệt và tối ưu hóa phương pháp khởi chạy mặc định của mình để không sử dụng thông số Intent.


1
Không phải tất cả các anh hùng đều đội mũ lưỡi trai!
Sdghasemi

Tôi không biết nhưng nó luôn trả về true, getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORYkhông quan trọng nếu tôi bắt đầu hoạt động từ một hoạt động khác (phương thức startActivity) hoặc mở lại nó từ ngăn xếp Lịch sử (ứng dụng gần đây).
25

bạn sẽ phải sử dụng nó kết hợp với các cờ khác, có thể FLAG_ACTIVITY_NEW_TASK
BB

1
Điều này không hoạt động khi hoạt động bị tắt trong nền do cài đặt Dev "Không giữ hoạt động". Trong trường hợp này getIntent () getFlags () giống hệt như khi hoạt động bắt đầu lần đầu tiên.
Malachiasz

đánh giá cao những lời giải thích nhưng nó không như mong đợi
Azlan Jamal

18

Xóa một đối tượng có ý định :

intent.replaceExtras(new Bundle());
intent.setAction("");
intent.setData(null);
intent.setFlags(0);

2
Đây phải là câu trả lời được chấp nhận. Hoạt động thực sự tốt!
Martin Erlic

2
Không làm việc khi "không giữ các hoạt động" được chọn vào tùy chọn nhà phát triển
Jemshit Iskenderov

8

Câu trả lời ngắn gọn là Không thể nào

Câu trả lời dài. Không có cái gọi là ý định "one-shot". Từ thử nghiệm, có thể thấy rằng lịch sử hoạt động gần đây trong Android hiện đại không gì khác hơn là "Lịch sử ý định". Mục đích mới nhất được chuyển cho hoạt động chỉ đơn giản là đăng nhập vào hệ thống và đó là thỏa thuận. Những người ở trên đề nghị sử dụng

setAction("")

Nhưng nó không hoạt động vì ý định đã được ghi lại cho đến thời điểm bạn nhận được nó bên trong phương thức onNewIntent () hoặc onStart ().

Tôi đã giải quyết vấn đề bằng cách tránh sử dụng ý định. Vấn đề của tôi là khác thường với một trong những được đăng bởi tác giả. Tôi đã cố gắng triển khai Global Exit khỏi ứng dụng thông qua điều khiển trong vùng thông báo. Nó sẽ dừng dịch vụ cơ bản và đóng tất cả các hoạt động của ứng dụng. Bạn có thể tìm thấy hành vi tương tự trong ứng dụng Waze.

Thuật toán:

  1. Tạo PendingIntent để kiểm soát thông báo chuyển hành động "Thoát" sang hoạt động. Nhưng đối với hoạt động đặc biệt là một proxy đơn giản.
  2. Mã hoạt động proxy onStart () phân tích cú pháp ý định, kiểm tra hành động và đặt trạng thái của một số mô hình thành "Đã thoát".
  3. Hoạt động proxy mã onStart () xóa mục đích ban đầu bằng cách sử dụng setIntent ("") và sau đó chuyển tiếp nó đến hoạt động "gốc" đích bằng cách gọi startActivity (ý định).
  4. Hoạt động proxy onStart () mã gọi finish ().
  5. Bên trong onStart () và onNewIntent () của mô hình hoạt động đích kiểm tra trạng thái và gọi finish () nếu nó là "Exited" (và cũng gọi stopService () trong trường hợp của tôi).

Tôi hy vọng điều này sẽ giúp ích cho ai đó vì tôi không tìm thấy câu trả lời trên internet.


Tôi thấy đây là câu trả lời chính xác nhất, vì "xóa mục đích" không nhất thiết có nghĩa là "loại bỏ một số bổ sung". Tôi cũng không nghĩ rằng có một cách dễ dàng để làm điều đó.
mdelolmo

5

Hãy chắc chắn rằng bạn đang sử dụng PendingIntent.FLAG_UPDATE_CURRENT cờ cho PendingIntent .

PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, mPutIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Trong trường hợp mPutIntentcủa bạn là Intent.

Hy vọng điều này sẽ giúp bạn.


1
cứu cuộc đời tôi!!
eren130

1
Tôi không hiểu làm thế nào đây không phải là câu trả lời được chấp nhận. Điều hối tiếc duy nhất của tôi là ngoại trừ một: có một sự ủng hộ duy nhất. Chúc mừng.
Andy

2

Gần đây tôi đã gặp sự cố này và tôi đã giải quyết nó bằng cách thêm dấu thời gian làm tham số bổ sung cho ý định:

private void launchActivity(Context context) {
    Intent intent = new Intent(context, MainActivity.class);
    intent.putExtra("KEY_EXTRA_TIMESTAMP", System.currentTimeMillis());
    context.startActivity(intent);
}

Sau đó, lưu dấu thời gian vào các tùy chọn được chia sẻ:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    long time = getIntent().getLongExtra("KEY_EXTRA_TIMESTAMP", -1);
    long previousTime = getPreferences(MODE_PRIVATE).getLong("timestamp", -1);

    //ignore if the timestamp is the same as the previous one  
    if (time != previousTime) {
        handleIntent(getIntent());
        if (time != -1) {
            //save the timestamp
            getPreferences(MODE_PRIVATE).edit().putLong("timestamp", time).apply();
        }
    }
}

1

Tôi gặp chính xác cùng một vấn đề. Giải pháp của tôi là thêm booleanbiến được đặt khi Intentđược 'sử dụng' và ifcâu lệnh dựa trên điều này booleanđể kiểm tra xem bạn có nên sử dụng Intenthay không.


3
điều này có thể không hoạt động, vì các giá trị boolean sẽ được tạo lại (nếu được khai báo toàn cục trong hoạt động) khi hoạt động bị dừng và sau đó khởi động lại. (nhấn vào nút home ví dụ)
tony9099

1

Khi bạn xử lý xong Intent, hãy làm như sau:

setIntent(null);

Bạn sẽ không thấy lại Ý định đã xử lý đó và bạn sẽ không che giấu sự cố bằng cách chỉnh sửa nội dung của Ý định đã xử lý.


1

Tôi không thể tìm thấy cách xóa Intent Extra . Không có câu trả lời nào về việc xóa phần bổ sung khỏi mục đích hoạt động nếu bạn bật "Không giữ hoạt động " từ Tùy chọn nhà phát triển (Bằng cách đó, bạn có thể hủy Hoạt động và quay lại kiểm tra xem phần bổ sung vẫn còn ở đó).

Để giải quyết vấn đề này, tôi đã lưu trữ giá trị boolean trong SharedPreferences sau khi Intent Extras được xử lý. Khi cùng một Ý định được chuyển đến Hoạt động, tôi sẽ kiểm tra giá trị SharedPreference và quyết định xử lý Ý định bổ sung. Trong trường hợp bạn gửi một Intent Extra mới khác cho cùng một Activity, bạn đặt giá trị SharedPreference là false và Activity sẽ xử lý nó. Ví dụ :

// Start Activity with Intent Extras
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra("someData", "my Data");
// Set data as not processed
context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE).edit().putBoolean("myActivityExtraProccessed", false).commit();
context.startActivity(intent);

...

public class MyActivity{

    ...
    public void someMethod(){
        boolean isExtrasProcessed = context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE).getBoolean("myActivityExtraProccessed", false);  
         if (!isExtrasProcessed) {
              // Use Extras

              //Set data as processed
              context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE).edit().putBoolean("myActivityExtraProccessed", true).commit();
         }
    }

}

tùy chọn không có ý nghĩa vì bạn không biết liệu bạn đã bắt đầu hoạt động bằng startActivity hay bạn mở lại từ Ngăn xếp lịch sử ...
25

@ user25 Tôi nghĩ có một cách để phát hiện xem nó có được khởi chạy từ các ứng dụng gần đây hay không. Nhưng nó có quan trọng không, ý định phụ có được tiêu thụ hoặc không, nếu nó được tiêu thụ, bạn biết nó từ pref được chia sẻ. tôi đã sử dụng điều này để tiêu thụ thêm thông báo đẩy và nó không quan trọng hoạt động được mở như thế nào đối với trường hợp của tôi.
Jemshit Iskenderov

0

Ngay cả sau khi xóa các phần bổ sung Intent và Intent theo cách thủ công sau khi chúng đã được phân tích cú pháp, có vẻ như Activity.getIntent () sẽ luôn trả về Intent ban đầu đã bắt đầu Activity.

Để giải quyết vấn đề này, tôi đề xuất một số thứ như sau:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // The Intent provided by getIntent() (and its extras) will persist through a restore
    // via savedInstance.  Because of this, restoring this activity from a
    // an instance that was originally started with extras (deep-link or 
    // pre-defined destination) may cause un-desired behavior
    // (ie...infinite loop of sending the user directly to somewhere else because of a
    // pre-defined alternate destination in the Intent's extras).
    //
    // To get around this, if restoring from savedInstanceState, we explicitly
    // set a new Intent *** to override the original Intent that started the activity.***
    // Note...it is still possible to re-use the original Intent values...simply
    // set them in the savedInstanceState Bundle in onSavedInstanceState.
    if (savedInstanceState != null) {
        // Place savedInstanceState Bundle as the Intent "extras"
        setIntent(new Intent().putExtras(savedInstanceState));
    }

    processIntent(getIntent())
}

private void processIntent(Intent intent) {
    if (getIntent().getExtras() == null) {
        // Protection condition
        return;
    }

    doSomething(intent.getExtras.getString("SOMETHING_I_REALLY_NEED_TO_PERSIST"));

    final String somethingIDontWantToPersist = 
        intent.getExtras.getString("SOMETHING_I_DONT_WANT_TO_PERSIST");

    if(somethingIDontWantToPersist != null) {
        doSomething(somethingIDontWantToPersist);
    }
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save selective extras from original Intent...
    savedInstanceState.putString("SOMETHING_I_REALLY_NEED_TO_PERSIST", "persistedValued");
    super.onSaveInstanceState(savedInstanceState);
}

Bằng cách này, có một cơ chế để loại bỏ Ý định ban đầu trong khi vẫn giữ được khả năng giữ lại một cách rõ ràng các phần nhất định của phần bổ sung Ý định / Ý định ban đầu.

Lưu ý rằng tôi chưa thử nghiệm tất cả các chế độ khởi chạy Hoạt động.


0

Cách đơn giản là tránh gọi getIntent () từ các phương thức khác với onCreate (). Nhưng điều này sẽ gây ra sự cố trong lần khởi chạy tiếp theo nếu người dùng rời khỏi Hoạt động của chúng tôi bằng cách nhấn vào nút Trang chủ. Tôi nghĩ rằng vấn đề này không có một giải pháp đầy đủ chức năng.


0

Tôi đối mặt với cùng một vấn đề và cố gắng sử dụng các phương pháp trên nhưng nó không hiệu quả.

Tôi nghĩ rằng nó có thể là nguyên nhân dẫn đến chế độ khởi chạy của acitvity mà tôi đã sử dụng chế độ SingleTop.

Khi tôi chạy ứng dụng nền và sử dụng RamEater để mô phỏng vấn đề mà ý định đó luôn có thêm ngay cả khi tôi đặt nó là null hoặc xóa khóa.

Vấn đề đã được giải quyết bằng cách sử dụng bộ nhớ ưu tiên trên Android để kiểm tra xem đã được thông qua chưa.


0

Không phải là một thực hành tốt nếu bạn thêm một phần bổ sung khác chỉ để biết liệu phần bổ sung đã được tiêu thụ hay chưa, tại sao không làm điều này ?:

if (intent.hasExtra(EXTRA_NAME) && intent.getBooleanExtra(EXTRA_NAME, false)) {
    // consume extra here after that set it to false
    putExtra(EXTRA_NAME, false)
}   

-1

Còn cái này thì sao? Đặt newIntent làm mục đích.

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}

1
Tôi không nghĩ rằng điều đó hiệu quả. Khi hoạt động được tạo lại từ lịch sử, mục đích vẫn không bị ảnh hưởng.
mdelolmo

-1

Còn khi bạn muốn xóa ý định - thay thế nó bằng một ý định trống?

ví dụ.

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}

@Override 
public void onResume() {
    super.onResume();

    Intent theIntent = getIntent();
    if ("myaction".equals(theIntent.getAction()) {
         handleIntent();
         onNewIntent(new Intent());  // <--- "clear" the intent by setting empty one
    }
}

-1

Điều này hy vọng sẽ giúp ích cho tất cả mọi người. Vì vậy, trước tiên chúng ta có được ý định

//globally
Intent myIntent;

Đặt cái này ở đâu đó onCreate

myIntent = getIntent();
String data = myIntent.getStringExtra("yourdata");
//Your process here

Bây giờ, hãy thiết lập điều này để mỗi khi ứng dụng của chúng tôi bị phá hủy hoặc thoát ra, chúng tôi sẽ xóa dữ liệu

@Override
protected void onDestroy() {
    //TODO: Clear intents
    super.onDestroy();
    myIntent.removeExtra("data");
}
@Override
protected void onBackPressed() {
    //TODO: Clear intents
    super.onBackPressed();
    myIntent.removeExtra("data");
}

Bạn có ý tưởng, nếu điều này là không đủ, chỉ cần tìm thêm các lệnh gọi lại 'trên'


Mục đích chỉ bị xóa khi bạn thoát khỏi ứng dụng, ví dụ: Vuốt phần gần đây.
Pixeldroid Modding

-2

Mặc dù Intent.removeExtra("key")sẽ loại bỏ một khóa cụ thể khỏi phần bổ sung, nhưng cũng có phương thức Intent.replaceExtras (Bundle) , có thể được sử dụng để xóa toàn bộ phần bổ sung khỏi Intent, nếu nullđược chuyển dưới dạng tham số.

Từ các tài liệu:

Thay thế hoàn toàn các tính năng bổ sung trong Ý định bằng Gói tính năng bổ sung đã cho.

Các
tính năng bổ sung của tham số Tập hợp các tính năng bổ sung mới trong Intent, hoặc rỗng để xóa tất cả các tính năng bổ sung.

Bởi vì các phương thức putXXX () khởi tạo các tính năng bổ sung với một Gói mới nếu nó null, điều này không có vấn đề gì.


-3
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
intent.addCategory(Intent.CATEGORY_HOME);  
startActivity(intent);

2
Bạn nên cân nhắc xây dựng câu trả lời của mình bằng cách cung cấp một số chi tiết về những gì bạn đang làm và cách nó trả lời câu hỏi của OP.
forsvarir,

1
@Ramkumar điều này sẽ đưa người dùng về nhà. Điều này rõ ràng chỉ là một trường hợp duy nhất trong số 10000 trường hợp có thể gây ra onPause, onStop hoặc onDestroy được gọi.
tony9099

Đây không phải là thậm chí liên quan từ xa cho câu hỏi
Hossein Shahdoost
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.