활동 컨텍스트 외부에서 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.