[TIP] Activity 활성화 및 비활성화.
우선 AndroidManifest.xml 에서 액티비티를 설정할 때, 속성값으로 액티비티 활성화/비활성화 값을 줄 수 있다. 만약 액티비티 비활성화를 한다면, Context 내의 startActivity 메소드를 이용하여 비활성화 된 액티비티를 호출시 앱은 ActivityNotFoundException 을 발생시키고 크래쉬가 발생하게 된다. 또 런처에서 실행시키기 위하여 <activity> 내부의 설정 앨리먼트 <intent-filter> 로 <action android:name="android.intent.action.MAIN"/> 과 <category android:name="android.intent.category.LAUNCHER"/> 옵션을 지정해줬다고 해도 런처내에 액티비티의 아이콘이 표시되지 않는다.
그리고, 이 것을 Manifest 파일에서만이 아닌 코드상에서도 PackageManager 의 setComponentEnabledSetting 으로 제어할 수 있다.
사용법은 무지 간단한데, 만약 Activity 내부에서 호출한다면 다음과 같은 코드를 사용하면 된다.
액티비티 비활성화:
PackageManager pm = getPackageManager(); pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), HiddenActivity.class), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
만약 두 번째 인자를 COMPONENT_ENABLED_STATE_ENABLED 로 준다면 비활성화된 액티비티는 다시 활성화가 된다.
세 번째 인자를 0으로 준다면 이 설정이 종료된 시점에서 액티비티가 강제 종료되게 되는데, 만약 이 인자값을 PackageManager.DONT_KILL_APP 를 주게 된다면 앱은 종료되지 않은 상태로 설정값만 바뀌게 된다. 다만 어떻게 동작할지 모르니 주의하여 사용하여야 한다. (안드로이드 API 레퍼런스 바로가기 링크) 또 한가지 주의할 점은, 만약 setComponentEnabledSetting 메소드의 세 번째 인자값을 0으로 줬을 때 이 메소드의 호출이 종료되는 시점에 앱이 종료된다는 것이다.
이 메소드를 통하여 설정한 액티비티의 활성화/비활성화 속성은 저장되어, 앱을 강제종료하거나 재부팅을 하여도 계속 유지된다.
다음 예제를 통하여 어떻게 동작하는지 한 번 살펴보자.
우선 액티비티를 두 개를 만들고, 액티비티에 서로 다른 아이콘을 붙여놓았다.
우측의 아이콘 이름은 ic_launcher_2 |
AndroidManifest.xml:
... 생략
<activity android:name="MainActivity" android:icon="@drawable/ic_launcher_1"> <intent-filter > <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name="HiddenActivity" android:icon="@drawable/ic_launcher_2" android:label="Hidden" android:enabled="false"> <intent-filter > <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>
HiddenActivity.java:
public class HiddenActivity extends MainActivity{ }
MainActivity.java:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 프레임 레이아웃을 만들고, // 여기에 버튼을 하나 생성한다. // 그리고 프레임 레이아웃을 Context View 로 정의한다. FrameLayout layout = new FrameLayout(getApplicationContext()); Button buttonHiddenActivityEnable = new Button(this); buttonHiddenActivityEnable.setText(isThisHiddenActivity()?"Disable this Activity":"Enable HiddenActivity"); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); params.gravity = Gravity.CENTER; buttonHiddenActivityEnable.setLayoutParams(params); layout.addView(buttonHiddenActivityEnable); buttonHiddenActivityEnable.setOnClickListener(mOnClickListener); setContentView(layout); setTitle((isThisHiddenActivity()?"Hidden Activity":"Main Activity")); } private OnClickListener mOnClickListener = new OnClickListener() { @Override public void onClick(View v) { finish(); PackageManager pm = getPackageManager(); pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), HiddenActivity.class), (isThisHiddenActivity()?PackageManager.COMPONENT_ENABLED_STATE_DISABLED:PackageManager.COMPONENT_ENABLED_STATE_ENABLED), 0); } }; private boolean isThisHiddenActivity() { return this instanceof HiddenActivity; } }
좀 귀찮아서 하나의 액티비티에 구현 코드를 몰아넣었다. 어쨌든 액티비티는 두개다.
이 코드를 실행하면 액티비티 실행 아이콘이 하나만 존재한다.
매니페스트 파일에서 android:enable 값을 false 로 준 HiddenActivity 는 런처에 아이콘조차 표시되지 않는다.
만약 앱을 실행시켜서 다음 스샷에 있는 버튼을 누른다면 앱이 완전히 종료되고, HiddenActivity 를 띄울수 있는 아이콘이 표시된다.
이 버튼은 누르면 앱이 종료되고, HiddenActivity 를 띄울 수 있게 된다.
이제 HiddenActivity 를 띄워서 버튼을 누르면 다시 HiddenActivity 는 disabled 되고 버튼은 감춰진다.
(다시 enable 하기전 까지는 사용할 수 없게 된다.)