5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

はじめに

この記事ではAndroidアプリをアシスタントアプリとして登録したい時に設定するコードについて紹介します。

例としてコードを掲載していますが、まだ開発途中であるため、一部機能が使用できず、また強制停止が頻発します。あくまで参考程度でお使いください。

Androidスマホのショートカット機能

Androidスマホには、画面の右下から中央下に指をスライドしたり、ホームボタンを長押しするとアシスタントアプリが起動するショートカットが実装されています。また、端末によっては、アシスタントキー(SHARP AQUOS)や、Googleアシスタントボタン(SONY Xperia)などの、アシスタントアプリを起動するためのボタンが存在します。

しかし、あまり使わないんですよね。この機能。
じゃあ別のアプリを割り当てたい。

でも残念なことに、これらのショートカットは、アシスタントアプリとして登録されているアプリでないと、起動させられないんです。

アシスタントアプリを作れば良いじゃない

ショートカット機能で起動できるアプリはアシスタントアプリだけ。つまりアシスタントアプリなら起動できるということ。

Androidには、アプリがどういう役割を果たすのかをOS側に伝えるコードがあります。例えば

AndroidManifest.xml
<action android:name="android.intent.action.BROWSER"/>

というコードがアプリのAndroidManifest.xmlに存在した場合、Androidはブラウザアプリとして扱います。

ではアシスタントアプリの場合は何を入力すれば良いのか…?調べてみると、ありました。

AndroidManifest.xml
 <action android:name="android.intent.action.ASSIST"/>

ブラウザの場合はBROWSRだった部分がアシスタントの場合はASSISTになるんですね。

つまり、android.intent.action.ASSISTを指定したアプリから、ショートカットしたい別のアプリを開けば、実質的に、ショートカットボタンから好きなアプリを開くことができます。

動作を考える

ショートカットからある特定のアプリを開く機能だけが欲しい、というのであれば、実装は楽です。
例えばChromeであれば、コード自体にChromeを開くコードを埋め込んでしまい、作ったアプリを起動した瞬間にChromeを起動する仕様にしてやれば、簡単です。

しかし、時間が経てば、起動させたいアプリは変わるかもしれません。その度にアプリをビルドし直すのは面倒です。

できればアプリ内から、起動するアプリを選べたら便利ですよね。アプリ一覧を表示して、ユーザーに選択してもらい、そのアプリのパッケージを取得し、保存、使用することで、様々なアプリに対応できるようになります。

ただし、今の私にはそんな動作を実現できる実力が無いため、LINEを起動するコードを書きたいと思います。

開きたいアプリを開く画面と、開きたいアプリを選択する画面をどうやって分けるか

ランチャーでアプリのアイコンを長押しした時に表示することができる、ウィジェット機能を使っています。

コード

まだ作成途中ですが一応公開します
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.preference.PreferenceManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onStart() {
        super.onStart();
        PackageManager pm = getPackageManager();
        Intent intent = pm.getLaunchIntentForPackage("jp.naver.line.android");
        try {
            startActivity(intent);
        } catch (Exception e) {
            Toast.makeText(this, "対象のアプリがありません", Toast.LENGTH_SHORT).show();
        }
    }
}
SettingActivity.java
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class SettingActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button saveButton = (Button)findViewById(R.id.SaveButton);
        saveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                saveButtonClick();
            }
        });
    }

    public void saveButtonClick() {
        EditText editText = (EditText)findViewById(R.id.editText);
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        sp.edit().putString("SaveString", editText.getText().toString()).commit();
    }
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
        tools:ignore="QueryAllPackagesPermission" />
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        tools:targetApi="31"        >
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.ASSIST" />
                <action android:name="android.intent.action.SEARCH_LONG_PRESS" />
                <category android:name="android.intent.category.DEFAULT" />
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:value=""
                android:name="android.app.shortcuts"
                android:resource="@xml/shortcuts"/>
        </activity>

        <activity
            android:name=".SettingActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

            </intent-filter>

            <meta-data
                android:name="android.app.shortcuts"
                android:resource="@xml/shortcuts"/>
        </activity>
    </application>

</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.223" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="243dp"
        android:layout_height="53dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="@string/editText"
        tools:ignore="LabelFor,MissingConstraints"
        tools:layout_editor_absoluteX="84dp"
        tools:layout_editor_absoluteY="225dp"
        android:autofillHints="" />

    <Button
        android:id="@+id/SaveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/buttonname"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText"
        app:layout_constraintVertical_bias="0.132" />

</androidx.constraintlayout.widget.ConstraintLayout>
string.xml
<resources>
    <string name="app_name">OpenApp</string>
    <string name="text">Please write package name</string>
    <string name="buttonname">Save</string>
    <string name="shortcutShortLabel">shortcutShortLabel</string>
    <string name="shortcutLongLabel">shortcutLongLabel</string>
    <string name="editText">jp.naver.line.android</string>
</resources>

まとめ

アシスタントアプリを作ろうという人があまりいないのか、AndroidManifest.xmlに記述するコードを調べるのに手間取りました。早くアプリを完成させたいです。

最後まで読んでいただきありがとうございました。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?