본문 바로가기
Android

[Android][Shortcut] 바로 가기 위젯 만드는 법

by 준그래머 2023. 10. 23.
반응형

개요

회사 업무 중 Android 9에서 바로 가기 위젯이 workspace에 추가되지 않는 현상이 발생했는데, android12에서는 바로가기가 추가되는지 확인하기 위해 예제 프로젝트를 만들어 각 각 OS에서 테스트하게 되었다. 이 글은 테스트해보기 위해 만든 프로젝트를 정리한 글이다.

일단 바로 가기는 Widget이 아닌 Shortcut으로 분류가 된다.

 

App shortcuts overview  |  Android Developers

Learn how to add shortcuts to specific actions within your app.

developer.android.com

따라서 AppWidgetProvider는 필요하지 않지만 대신 res/xml에 shortcuts.xml 을 정의해줘야 한다.

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    <shortcut
        android:shortcutId="compose"
        android:enabled="true"
        android:icon="@drawable/ic_android_black_24dp"
        android:shortcutShortLabel="@string/app_name"
        android:shortcutLongLabel="@string/app_name"
        android:shortcutDisabledMessage="@string/app_name">
        <intent
            android:action="android.intent.action.VIEW"
            android:targetPackage="com.ctb.android9javatest"
            android:targetClass="com.ctb.android9javatest.MainActivity" />
        <!-- If your shortcut is associated with multiple intents, include them
             here. The last intent in the list determines what the user sees when
             they launch this shortcut. -->
<!--        <categories android:name="android.shortcut.conversation" />-->
<!--        <capability-binding android:key="actions.intent.CREATE_MESSAGE" />-->
    </shortcut>
    <!-- Specify more shortcuts here. -->
</shortcuts>

각 각의 속성은 Android Developer에서 확인하도록 한다. 아무튼 이렇게 xml을 생성해준 뒤 AndroidManifest.xml에 다음과 같이permission을 추가해주고

<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<application
    ...>
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <meta-data
            android:name="android.app.lib_name"
            android:value="" />
        <meta-data android:name="android.app.shortcuts"
            android:resource="@xml/shortcuts" />
    </activity>

    <activity-alias
        android:name=".ShortcutActivity"
        android:targetActivity=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.CREATE_SHORTCUT" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity-alias>
</application>

이런 식으로 바로 가기로 사용할 Activity 안에 위에서 선언한 xml 데이터를 넣어 준다.

또 해당 Activity로 접근할 activity-alias를 선언 해줄건데, 이 alias의 name을 통해 추후에 어떤 바로 가기에서 접근했는지 구분할 수 있다.

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "jypark";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        String action = getIntent().getAction();

        if(action.contentEquals(Intent.ACTION_CREATE_SHORTCUT)){
            String componentName = getIntent().getComponent().getClassName();

            if(componentName.contains("ShortcutActivity")){
                ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);

                if(shortcutManager.isRequestPinShortcutSupported()){
                    Intent shortcutIntent = new Intent(getApplicationContext(), MainActivity.class);
                    ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(this, "shortcut_id")
                            .setShortLabel("Shortcut Label")
                            .setLongLabel("Long Label")
                            .setIcon(Icon.createWithResource(getApplicationContext(), R.drawable.ic_android_black_24dp))
                            .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("<https://www.mysite.example.com/>")))
                            .build();

                    ExecutorService executors = Executors.newSingleThreadExecutor();
                    executors.submit(new Runnable() {
                        @Override
                        public void run() {
                            shortcutManager.requestPinShortcut(shortcutInfo, null);
                        }
                    });
                }
            }
        }
    }
}
반응형