활동 컨텍스트 외부에서 startActivity () 호출


367

ListView내 Android 응용 프로그램에서을 구현했습니다 . ListView클래스의 커스텀 서브 클래스를 사용하여 이것에 바인딩합니다 ArrayAdapter. 재정의 된 ArrayAdapter.getView(...)메서드 내에서을 할당합니다 OnClickListener. 의 onClick방법 OnClickListener에서 새로운 활동을 시작하고 싶습니다. 나는 예외를 얻는다 :

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

(현재 )가 작동 하고 Context있다는 것을 어떻게 알 수 있습니까?ListViewActivity


1
당신이 더 일반적인 방식에서 설명한 오류 정류 이후로는 알렉스의 대답이 문제에 대한 '인정'솔루션을해야한다고 생각
— devanshu_kaushik

10
나는 "이것이 정말로 당신이 원하는 것입니까?" ... 이전에 "어딘가에 방송 수신기를 등록 취소하는 것을 잊지 않았습니까?"라는 메시지가 나타났습니다. 대박! 이 작은 메시지를 모두 넣은 사람이 우리를 막을 수 있도록 도와주십시오.
— Nerdy Bunz

1
나는이 문제를 만났다. targetSdkVersion을 28로 업데이트했을 때.
— illusionJJ

답변:


574

어느 한 쪽

  • 어댑터의 생성자를 통해 Context 객체를 캐시하거나
  • 당신의 관점에서 그것을 얻을.

또는 최후의 수단으로

  • FLAG_ACTIVITY_NEW_TASK 플래그를 의도에 추가하십시오.

_

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

편집-이벤트 및 기록 스택의 정상적인 흐름을 방해하므로 플래그 설정을 피하십시오.


6
시스템에 의해 생성 된 의도 (및 플래그)를 제어 할 수없는 TextView 의 자동 링크 기능은 어떻습니까?
— Alex Semeniuk

75
나는이 같은 일을 할 때 나는이 예외를 얻고 있었다 context.startActivity(intent);난 그냥 변경 context에서 ApplicationContext하는 Activity유형입니다. 문제가 해결되었습니다.
— Sufian

@AlexSemeniuk는 해결책을 찾은 적이 있습니까?

@AlexSemeniuk-autoLink는 활동을 어댑터에 컨텍스트로 전달하는 한 작동합니다
— Georges

생성자를 통해 Context 객체를 전달했지만 작동하지 않습니다. 하지만 FLAG_ACTIVITY_NEW_TASK는 매우 잘 작동합니다.
— Hiren

100

대신 addFlags를 사용 하여 달성 할 수 있습니다.setFlags

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

설명서 에 따르면 다음과 같습니다.

의도에 (또는 기존 플래그 값으로) 추가 플래그를 추가하십시오.


편집하다

Alex Volovoy의 답변에서 알 수 있듯이 기록 스택을 변경하는 플래그를 사용하고 있는지 확인하십시오 .

... 이벤트 및 히스토리 스택의 정상적인 흐름을 방해하므로 플래그를 설정하지 마십시오.


1
나는 비슷한 문제가 있습니다. 히스토리 스택에 문제가 있거나 위의 답변이 제안한 다른 문제가 있습니까?
— Einar Sundgren

1
정확히 무엇을 찾고 있는지 확실하지 않지만 다음과 같은 기록없이 활동을 시작할 수 있습니다. 의도 의도 = new Intent (Intent.ACTION_VIEW, "http : \\ www.google.com")); 의도. addFlags (Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity (의도);
— Bruno Bieri

왜 여기에 플래그를 추가하지 않는 것이 좋습니까? 정상적인 이벤트 흐름과 기록 스택을 방해하는 것이 얼마나 중요합니까?
— Jason Krs

@JasonKrs addFlags를 사용할 수 있습니다. 추가 한 플래그에 따라 히스토리 스택을 변경할 수 있습니다. 이 상황에서는 FLAG_ACTIVITY_NEW_TASK를 사용할 수 있습니다. 자세한 내용은 developer.android.com/reference/android/content/…
— Bruno Bieri


40

아래와 같이 create chooser를 사용하여 오류가 발생한 경우 :

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"));

다음과 같이 선택기를 작성하도록 플래그를 설정하십시오.

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
매우 유용했습니다. 정확히 선택 자의 의도에는이 플래그가 있어야합니다!
— Mahdi

2
이것은 올바른 해결책이며, 정확히 무엇을해야 하는가 intent.chooser의 new_task
— Rafael Guimarães

15

또한 : fragment의 listview에 링크를 표시하는 경우 다음 과 같이 만들지 마십시오

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

대신에 전화

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

어댑터는 두 경우 모두 잘 작동하지만 링크는 마지막 경우에만 작동합니다.


@ user2676468 : 이것은 나를 위해 자동 링크 문제를 해결했습니다.
— 헤드 eek

이것은 플래그를 사용하는 대신 허용되는 답변이어야합니다.
— Gastón Saillén

@ GastónSaillén, getApplicationContext()(응용 프로그램 초기화 제외)를 사용하지 않지만 이 예외가 발생했습니다. 따라서 상황이 다를 수 있습니다.
— CoolMind

이것은 내 문제 였고 컨텍스트에 getApplicationContext ()를 사용했습니다. this컨텍스트로 설정 하면 현재 활동과 관련이 있습니다.
— Brlja

14

아마도 잘못된 위치에 OnClickListener를 구현하고 있다고 생각합니다. 보통 Activity에서 OnItemClickListener를 구현하고 대신 ListView에 설정해야합니다. 그렇지 않으면 이벤트에 문제가 발생합니다 ...


2
당신은 나를 해결책으로 인도합니다. ListView에 할당 된 OnItemClickListener를 사용해야했습니다. 다음은 다른 사람을위한 몇 가지 링크입니다. developer.android.com/reference/android/widget/… androidpeople.com/… 도움을 주셔서 감사합니다.
— Sako73

일반적인 답변을 제공하십시오. Alex Volovoy의 답변은 일반적인 방식으로 문제를 해결합니다.
— devanshu_kaushik

후손의 경우 : 구성 요소에서 setListener (new Listener)로 직접 정의하려면 컨텍스트가 필요합니다. 믿지 않는 것처럼 메모리가 누출되는 전체 활동에 대한 암시 적 참조를 작성하십시오. 정적 내부 클래스 리스너를 만들거나 둘 이상의 원점에서 입력을 처리 할 수 ​​있어야하는 경우 리스너를 별도의 클래스로 이동하면이 문제를 피할 수 있습니다.
— G_V

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

또는

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

아래로 변경

CustomAdapter mAdapter = new CustomAdapter( this, yourlist);

8

상기 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?");
}

가장 좋은 방법은 추가입니다 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);

이것은 28 이상의 장치에 필요합니다.
— Md Mohsin

7

일부 방법으로 listiner 내에서 의도를 작성하는 경우 참조

override onClick (View v).

그런 다음이보기를 통해 컨텍스트를 호출하십시오.

v.getContext ()

SetFlags도 필요하지 않습니다 ...


그리고 무엇이 잘못 되었습니까? v.getApplicationContext ()?
— CoolMind


3

Alex Volovoy의 답변을 조금 더 정교하게-

조각 으로이 문제가 발생하는 경우 getActivity ()가 컨텍스트를 가져 오기 위해 잘 작동합니다.

다른 경우 :

사용하지 않으려는 경우

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

그런 다음 OutsideClass에서 이와 같은 함수를 만듭니다.

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

이제 주 활동에서 새 OutsideClass를 작성할 때 활동의 컨텍스트를 인수로 제공하는 OutsideClass를 정의한 후 즉시 위의 메소드를 호출하십시오. 또한 주요 활동에서 기능을 수행하십시오.

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

이제 OutsideClass로 돌아와서 새로운 활동을 시작하려면 다음과 같이하십시오.

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

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

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

이렇게하면 플래그를 엉망으로 만들지 않고 다른 OutsideClass에서 호출 된 다양한 활동을 시작할 수 있습니다.

참고-조각에 대한 생성자를 통해 컨텍스트 객체를 캐시하지 마십시오 (어댑터, 괜찮음). 조각에는 빈 생성자가 있어야합니다. 그렇지 않으면 일부 시나리오에서 응용 프로그램이 중단됩니다.

전화를 기억

OutsideClass.gettingContext(Context context);

onResume () 함수에서도.


3

startactivity가 자신의 활동을 모르는 경우이 오류가 발생합니다. 따라서 startActivity () 전에 활동을 추가해야합니다

당신은 설정해야합니다

context.startActivity(yourIntent);

startActivity에서 전화 를 Fragment걸면 발신자가 활동이 아닌 조각 일 수 있습니다.
— CoolMind

2

내 의견으로는, startActivity()코드에서의 방법을 사용하는 것이 좋습니다 Activity.class. 당신이에서 그것을 사용하는 경우 Adapter또는 다른 클래스, 그 발생합니다.


2

나도 같은 문제가 있었다. 전달한 모든 컨텍스트를 확인하십시오. ' 링크 '의 경우 애플리케이션 컨텍스트가 아닌 활동 컨텍스트가 필요합니다 .

다음을 확인해야합니다.

1.) LayoutInflater 를 사용한 경우 전달한 컨텍스트를 확인하십시오.

2.) 어댑터를 사용하는 경우 전달한 컨텍스트를 확인하십시오.


2

나는 같은 문제가 있었다. 문제는 맥락에 있습니다. 링크를 열려면 (예 : 선택기를 통해 링크 공유) 응용 프로그램 컨텍스트가 아닌 활동 컨텍스트를 전달하십시오.

활동 중이 myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)아닌 경우 추가 하는 것을 잊지 마십시오.


2

Adapter_Activity에서이 코드를 사용 context.startActivity(intent_Object)하고intent_Object.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

이처럼 :

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

효과가있다....


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

이것이 효과가 있기를 바랍니다.


1

같은 문제에 직면 한 다음 구현

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

문제를 해결했습니다.

목록보기 어댑터와 관련된 다른 이유가있을 수 있습니다. 이 블로그를 잘
살펴 보았습니다 .


유용한 블로그, 감사합니다. :)
— Rucha Bhatt Joshi

1

이 코드를 사용하십시오. 나를 위해 잘 작동합니다. 활동 외에서 무언가 공유하기 :

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);

플래그를 설정하면 스택 추적 기록이 엉망
— Ezio

1

추가 플래그는 영향 때문에 event_flow그리고 stack_history당신이 다음과 같은 방법으로 활동 클래스를 호출 할 필요가있는 곳에서 비 활동으로 '애플리케이션 컨텍스트'를 통과하는 것이 좋습니다 :

"ActivityClassName.this"(이 방식으로 컨텍스트를 전달하는 동안 비 활동 시나리오에서 활동을 호출하는 데 필요한 모든 세부 사항 및 정보가 포함됨)

따라서 플래그를 설정하거나 추가 할 필요가 없으며, 모든 경우에 잘 작동합니다.


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

0

Cordova 플러그인 공유 의도를 호출하는 경우 플래그를 설정해도 도움이되지 않습니다. 대신 이것을 사용하십시오-

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

0

내 상황은 조금 달랐습니다. 사용하여 응용 프로그램을 테스트 하고 있으며 계측에서 ( Espresso내가 아닌) 내 활동을 시작해야했습니다 .ActivityTestRuleContextActivity

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

플래그를 변경하고 or비트 단위 ( |Java로)를 추가해야했습니다.Intent.FLAG_ACTIVITY_NEW_TASK

결과는 다음과 같습니다.

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

0

코 틀린 버전

val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.