Etkinlik bağlamının dışından startActivity () öğesini çağırmak


367

ListViewAndroid uygulamama bir uyguladım . Buna ListViewsınıfın özel bir alt sınıfını kullanarak bağlarım ArrayAdapter. Geçersiz kılınan ArrayAdapter.getView(...)yöntemin içinde bir OnClickListener. In onClickyöntemine OnClickListener, yeni bir aktivite başlatmak istiyorum. İstisnayı anlıyorum:

Calling startActivity() from outside of an Activity  context requires the  
FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Nasıl alabilirim Contextolduğunu ListView(güncel Activity) çalışıyor altından?


1
Sanırım Alex'in cevabı, daha genel bir şekilde bahsettiğiniz hatayı düzelttiği için probleminize 'kabul edilen' çözüm olmalı
devanshu_kaushik

10
"Gerçekten istediğin bu mu?" ... Daha önce "Bir yerde bir yayın alıcısının kaydını silmeyi unutmadığınızdan emin misiniz?" HARİKA! Tüm bu küçük mesajları kimin koyduğuna şapka çıkarmamıza yardım etmek için şapka çıkartın.
Nerdy Bunz

1
Bu konuyla tanıştım. targetSdkVersion'ı 28'e güncellediğimde
illusionJJ

Yanıtlar:


574

ya

  • Bağlam nesnesini bağdaştırıcınızdaki kurucu aracılığıyla önbelleğe alın veya
  • kendi bakış açınızdan alın.

Veya son çare olarak,

  • ekle - niyetinize FLAG_ACTIVITY_NEW_TASK bayrağı:

_

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Düzenle - normal olay ve geçmiş yığını akışını engelleyeceği için bayrakları ayarlamayı önlerim.


6
Sistem tarafından oluşturulan Niyeti (ve dolayısıyla bayrakları) kontrol edemediğim TextView'ın autoLink özelliği ne olacak ?
Alex Semeniuk

75
Böyle bir şey yaptığını ben bu istisna başlamıştı context.startActivity(intent);Sadece değişti contextgelen ApplicationContextetmek Activitytürü. Bu sorunu düzeltti.
Sufian

@AlexSemeniuk hiç bir çözüm buldunuz mu?

@AlexSemeniuk - AutoLink, aktiviteyi bağdaştırıcıya bağlam olarak aktardığınız sürece çalışacaktır
Georges

Context nesnesini yapıcı üzerinden geçtim ama işe yaramadı. ama FLAG_ACTIVITY_NEW_TASK benim için çok iyi çalışıyor teşekkürler.
Hiren

100

Bunun yerine addFlags ile elde edebilirsinizsetFlags

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Belgelere göre :

Amaca ek bayraklar ekleyin (veya mevcut bayraklar değerine sahip).


DÜZENLE

Alex Volovoy'un cevabının söylediği gibi tarih yığınını değiştirdiğiniz bayraklar kullanıyorsanız :

... normal olay akışına ve geçmiş yığınına müdahale edeceğinden bayrakları ayarlamaktan kaçının.


1
Çok benzer bir sorunum var. Geçmiş yığını ile ilgili herhangi bir sorun yaşadınız veya yukarıdaki yanıtlar önerildi mi?
Einar Sundgren

1
Ne aradığınızdan tam olarak emin değilim ama böyle bir geçmişi olmayan bir etkinliğe başlayabilirsiniz: Intent intent = new Intent (Intent.ACTION_VIEW, "http: \\ www.google.com")); niyet. addFlags (Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity (niyet);
Bruno Bieri

Burada addFlags eklemeniz neden önerilmez? Normal olay ve geçmiş yığınına müdahale etmek ne kadar kritiktir?
Jason Krs

@JasonKrs addFlags kullanabilirsiniz. Eklediğiniz bayrağa bağlı olarak geçmiş yığınını değiştirebileceğinizi unutmayın. FLAG_ACTIVITY_NEW_TASK bu durumda kullanılabilir. Daha fazla ayrıntı için okuyun: developer.android.com/reference/android/content/…
Bruno Bieri


40

Aşağıdaki gibi chooser oluşturma nedeniyle hata aldıysanız:

Intent sharingIntent = new Intent(Intent.ACTION_VIEW);
sharingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sharingIntent.setData(Uri.parse("http://google.com"));
startActivity(Intent.createChooser(sharingIntent, "Open With"));

Seçici oluşturmak için bayrağı şu şekilde ayarlayın:

Intent sharingIntent = new Intent(Intent.ACTION_VIEW);
sharingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sharingIntent.setData(Uri.parse("http://google.com"));

Intent chooserIntent = Intent.createChooser(sharingIntent, "Open With");
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(chooserIntent);

4
Çok faydalıydı. Kesinlikle seçici niyet bu bayrak olmalı!
Mehdi

2
Bu doğru çözümdür ve tam olarak ne yapmalı, new_task in intent.chooser
Rafael Guimarães

15

Ayrıca: liste görünümünde bağlantıları parça halinde gösterirseniz , bunu böyle oluşturmayın

adapter = new ListAdapter(getActivity().getApplicationContext(),mStrings);

onun yerine ara

adapter = new ListAdapter(getActivity(),mStrings);

bağdaştırıcı her iki durumda da iyi çalışır, ancak bağlantılar yalnızca sonuncusunda çalışır.


@ user2676468: Bu benim için otomatik bağlantı sorununu çözdü.
Kafa Geek

Bu kabul edilmiş bir cevap olmalı, bayrakları kullanmak yerine bu daha iyi !!
Gastón Saillén

@ GastónSaillén, getApplicationContext()(uygulama başlatma hariç) kullanmıyorum , ancak bu istisnayı yakaladım. Yani durumlar farklı olabilir.
CoolMind

Bu benim sorunum, bağlam için getApplicationContext () kullandım. thisBağlam olarak ayarlamak , geçerli etkinlikle ilgili olduğu için çalışır.
Brlja

14

Sanırım OnClickListener'ı yanlış yere uyguluyorsunuz - genellikle Aktivitenize bir OnItemClickListener uygulamanız ve bunun yerine ListView'a ayarlamanız gerekir, yoksa etkinliklerinizle ilgili sorunlar yaşarsınız ...


2
Beni çözüme götürüyorsun. ListView için atanan bir OnItemClickListener kullanmak gerekiyordu. İşte herkes için bazı bağlantılar: developer.android.com/reference/android/widget/… androidpeople.com/… Yardımınız için teşekkürler.
Sako73

Lütfen genel cevaplar sağlayın. Alex Volovoy'un aşağıdaki cevabı sorunu genel bir şekilde çözmektedir.
devanshu_kaushik

Posterity için: Bir bileşen üzerinde doğrudan setListener (new Listener) olarak tanımlarsanız, Bağlam gerektirir, tüm aktiviteye inanmadığınız gibi bellek sızdıracak örtük bir başvuru oluşturursunuz. Bu, statik bir iç sınıf dinleyicisi yapılarak veya birden fazla kaynaktan gelen girdileri işleyebilmesi gerekiyorsa dinleyiciyi ayrı bir sınıfa taşıyarak atlatılabilir.
G_V

9
CustomAdapter mAdapter = new CustomAdapter( getApplicationContext(), yourlist);

veya

Context mContext = getAppliactionContext();
CustomAdapter mAdapter = new CustomAdapter( mContext, yourlist);

aşağıya değiştir

CustomAdapter mAdapter = new CustomAdapter( this, yourlist);

8

at Android 28(Android P)startActivity

if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
        && (targetSdkVersion < Build.VERSION_CODES.N
                || targetSdkVersion >= Build.VERSION_CODES.P)
        && (options == null
                || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
    throw new AndroidRuntimeException(
            "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
}

Bu yüzden en iyi yol FLAG_ACTIVITY_NEW_TASK

Intent intent = new Intent(context, XXXActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);

Bu, 28 ve üstü cihazlar için gereklidir.
Md Mohsin

7

Bakın, bazı yöntemlerde bir listeleyici içinde bir amaç oluşturuyorsanız

override onClick (View v).

ardından bu görünüm üzerinden bağlamı da çağırın:

v.getContext ()

SetFlags'a bile gerek kalmayacak ...


Peki yanlış durum neydi? v.getApplicationContext ()?
CoolMind

3

Aktiviteden StartActivity çağrıldığında bile bunu Xamarin.Android (MonoDroid) üzerinde alan herkes için - bu aslında yeni ART çalışma süresine sahip Xamarin hatasıdır, bkz. Https://bugzilla.xamarin.com/show_bug.cgi?id=17630


Evet, yukarıda açıklandığı gibi yapmanız gerekiyor, ancak ifadeler değişti ... intent.SetFlags (ActivityFlags.NewTask);
Luke Alderton

3

Alex Volovoy'un cevabını biraz daha detaylandırarak -

u bu sorunu fragmanlarla alıyorsanız, bağlamı elde etmek için getActivity () iyi çalışır

Diğer Durumlarda:

Kullanmak istemiyorsanız

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//not recommend

OutsideClass'ınızda böyle bir işlev yapın -

public void gettingContext(Context context){
    real_context = context;//where real_context is a global variable of type Context
}

Şimdi, ana etkinliğinizde yeni bir OutsideClass yaptığınızda, OutsideClass'ı etkinliğin bağlamını bağımsız değişken olarak tanımladıktan hemen sonra yukarıdaki yöntemi çağırın. Ayrıca ana faaliyetinizde bir işlev

public void startNewActivity(final String activity_to_start) {
    if(activity_to_start.equals("ACTIVITY_KEY"));
    //ACTIVITY_KEY-is a custom key,just to
    //differentiate different activities
    Intent i = new Intent(MainActivity.this, ActivityToStartName.class);
    activity_context.startActivity(i);      
}//you can make a if-else ladder or use switch-case

şimdi OutsideClass'ınıza geri dönün ve yeni etkinliklere başlamak için böyle bir şey yapın-

@Override
public void onClick(View v) {
........
case R.id.any_button:

            MainActivity mainAct = (MainActivity) real_context;             
            mainAct.startNewActivity("ACTIVITY_KEY");                   

        break;
    }
........
}

Bu şekilde bayraklarla uğraşmadan farklı OutsideClass'tan farklı aktiviteler başlatabileceksiniz.

Not-Bağlam nesnesini parça için yapıcı aracılığıyla önbelleğe almamaya çalışın (bağdaştırıcıyla, para cezası ile).

aramayı unutma

OutsideClass.gettingContext(Context context);

onResume () işlevinde de kullanılabilir.


3

Bu hata, startactivity'nin faaliyetinin hangisi olduğunu bilmediği zaman gider. Bu nedenle startActivity () işleminden önce etkinlik eklemelisiniz

ayarlamalısın

context.startActivity(yourIntent);

Eğer ararsanız startActivitygelen Fragment, bir arayan çoğu zaman bir parça değil, bir etkinlik olabilir.
CoolMind

2

Bence, startActivity()sadece sizin kodunu yöntemini kullanmak daha iyidir Activity.class. Bunu Adaptersınıfta veya başka bir sınıfta kullanırsanız, bununla sonuçlanır.


2

Ben de aynı problemi yaşadım. Geçtiğiniz tüm içeriği kontrol edin. ' Bağlantılar ' için Uygulama bağlamı değil, Etkinlik Bağlamı gerekir .

Burası kontrol etmeniz gereken yer:

1.) LayoutInflater kullandıysanız, hangi bağlamı geçtiğinizi kontrol edin.

2.) Herhangi bir Bağdaştırıcı kullanıyorsanız hangi bağlamı geçtiğinizi kontrol edin.


2

Ben de aynı problemi yaşadım. Sorun bağlamdadır. Herhangi bir bağlantıyı açmak istiyorsanız (örneğin, herhangi bir bağlantıyı seçici aracılığıyla paylaşın) uygulama bağlamını değil, etkinlik bağlamını geçirin.

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)Etkinliğinizde değilseniz eklemeyi unutmayın .


2

Adapter_Activity'de bu kodu kullanın context.startActivity(intent_Object)veintent_Object.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Bunun gibi:

Intent n_act = new Intent(context, N_Activity.class);
n_act.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(n_act);

İşe yarıyor....


1
Intent viewIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);    
viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    
startActivity(viewIntent);   

umarım bu işe yarar.


1

Aynı sorunla karşılaştıktan sonra uygulandı

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

ve sorunu çözdüm.

Liste görünümü bağdaştırıcısıyla ilgili başka bir neden olabilir. Bu blogu çok iyi açıkladığını
görebilirsiniz .


yardımcı blog, teşekkür ederim. :)
Rucha Bhatt Joshi

1

Bu kodu kullanın. Benim için iyi çalışıyor. Bir Faaliyetin Dışındaki Bir Şeyi Paylaşın:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");

// Append Text
String Text = "Your Text Here"

intent.putExtra(Intent.EXTRA_TEXT, Text);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Intent shareIntent = Intent.createChooser(intent,"Share . . . ");
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
G.context.getApplicationContext().startActivity(shareIntent);

Bayrakların ayarlanması Stacktrace tarihini karıştırıyor
Ezio

1

Bayrak ekleme işlemi etkilediğinden event_flowve stack_history'uygulama bağlamını' bir etkinlik sınıfını aşağıdaki şekilde çağırmanız gereken yerden etkinlik dışı duruma geçirmek daha iyidir:

"ActivityClassName.this" (İçeriği bu şekilde iletirken, etkinlik dışı bir senaryodan bir Etkinlik çağırmak için ihtiyacınız olan tüm ayrıntı ve bilgileri içerecektir)

Bu yüzden bayrak ayarlamanıza veya eklemenize gerek yoktur, bu her durumda iyi çalışır.


0
Intent i= new Intent(context, NextActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

0

Cordova eklentisinde paylaşım Niyetini çağırıyorsanız, Bayrak'ı ayarlamak yardımcı olmaz. Bunun yerine bunu kullanın -

cordova.getActivity().startActivity(Intent.createChooser(shareIntent, "title"));

0

Durumum biraz farklıydı, uygulamamı kullanarak test ediyorum Espressove Etkinliğimi ActivityTestRuleenstrümantasyondan başlatmak zorunda kaldım Context(ki bu bir gelen değil Activity).

fun intent(context: Context) = 
    Intent(context, HomeActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

Ben bayrakları değiştirmek ve or( |Java ile) bir bitwise eklemek zorunda kaldıIntent.FLAG_ACTIVITY_NEW_TASK

Sonuç:

fun intent(context: Context) = 
    Intent(context, HomeActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)

0

Kotlin versiyonu

val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.