初老のボケ防止日記

おっさんのひとりごとだから気にしないようにな。

XperiaのWALKMAN Add-onアプリをつくろう



XperiaWALKMANは再生中の曲に対するAdd-onアプリがいくつかあるんですがどうやって作るんだろうとふと思ったので調べてみたよという話。


オフィシャルの記事が見つかった。

Develop app extensions for the “WALKMAN” Music player infinite button with the new Sony add-on SDK – Developer World

When you press the Infinite button, a list of apps becomes visible in the menu. Information is then sent to the app you select in this list. Xperia™ devices already come with a few pre-installed “WALKMAN” music player extension apps for the Infinite button, such as Wikipedia™ and YouTube™. And with the Music Infinite API, you can make your own app appear in the list. The extensions will be fed the data of the song currently being played as a Uniform Resource Identifier (URI) to the current song.

"Music Infinite API"というのでできるのね。ということで、この記事のリンクを飛んだら

Page not found

なんだとこのやろうばかやろう。

To start developing an app using the Music Infinite API, install the Sony Add-on SDK, then download the Sony Add-on SDK documentation kit, which contains a guide to the Music Infinite API . The Music Infinite API documentation describes how to develop your app extension, as well as how to verify your application using the music player emulator provided in the AndroidSDK manager.

そうか、SDKを入れないとダメなんか…スマンスマン俺が早とちりしてたわー。
ということで、以下を参考に入れてみた。

developer.sony.com

f:id:osa030:20150406182744p:plain

が…それらしいライブラリはない。

f:id:osa030:20150406182756p:plain

インストールされたSDKドキュメントを見ても、最初の記事にでてきた以下のインテントに関する情報はない。

com.sonyericsson.media.infinite.ACTION_GET_DETAILS
com.sonyericsson.media.infinite.ACTION_VIEW_INFINITE

うーん、じゃあどうやって作るんだろうということで、インテント名でぐぐっていたら今御世話になっている「NowPlaying Music Extension」のソースが公開されているのね。素晴らしい。

NowPlaying Music Extension - Google Play の Android アプリ
nowplaying-music-extension - NowPlaying Music Extension - Google Project Hosting

ということで、参考にさせていただきました(というかほぼそのままパクリです)。

開発環境

OS Windows8.1(x64)
Java 1.8.0
IDE Android Studio 1.2 beta
SDK API 19:Android 4.4(KitKat)
実機 SO-02G

サンプルコード

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.osa030.myaddon" >

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="com.sonyericsson.media.permission.INFINITE_ACCESS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <uses-library android:name="com.sonyericsson.media.infinite.extension_1" />
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="com.sonyericsson.media.infinite.ACTION_VIEW_INFINITE" />
                <data android:mimeType="audio/*" />
            </intent-filter>
        </activity>

        <receiver
            android:name=".MyReceiver">
            <intent-filter>
                <action android:name="com.sonyericsson.media.infinite.ACTION_GET_DETAILS" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

公開されているお手本コードにはないけれど、今回Kitkat(4.4)なので外部ストレージの読み取り権限がないとSDカードの保存している楽曲は怒られてしまうので追加した。あと、"uses-library"しているライブラリは開発環境上は無くて問題ない。エミュレータで動作させる場合はわからん。

MyReceiver.java

package com.example.osa030.myaddon;

import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getStringExtra("com.sonyericsson.media.infinite.EXTRA_ACTIVITY_NAME").equals(
                MainActivity.class.getName())) {

            Bundle extras = new Bundle();

            // Build a URI for the string resource for the description text
            String description = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                    .authority(context.getPackageName())
                    .appendPath(Integer.toString(R.string.description)).build().toString();
            extras.putString("com.sonyericsson.media.infinite.EXTRA_DESCRIPTION", description);
            setResultExtras(extras);
        }

    }
}

WALKMANアプリで「infinite」ボタンを押した後にAdd-onアプリの一覧が表示されるんだけど、そこに出現させるために"com.sonyericsson.media.infinite.EXTRA_ACTIVITY_NAME"を受けた時の処理が必要らしい。

strings.xml

<resources>
    <string name="app_name">MyAddOn</string>

    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="description">ほげほげ</string>
</resources>

Add-onアプリ一覧に表示される名称をここで指定している。MyReceiver.javaにベタ書きはだめだったので、お手本に習った。

MainActivity.java

package com.example.osa030.myaddon;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView text = (TextView)findViewById(R.id.text_view);
        text.setText("hogehoge!");

        Intent intent = getIntent();
        Uri trackUri = intent.getData();
        if( trackUri != null ){
            Cursor trackCursor = getContentResolver().query(
                    trackUri,
                    new String[]{
                            MediaStore.Audio.Media.TITLE,
                            MediaStore.Audio.Media.ARTIST,
                            MediaStore.Audio.Media.ALBUM,
                    },
                    null,
                    null,
                    null
            );
            if (trackCursor != null) {
                try {
                    if (trackCursor.moveToFirst()) {

                        String title  = trackCursor.getString(trackCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
                        String artist = trackCursor.getString(trackCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
                        String album  = trackCursor.getString(trackCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
                        text.setText(String.format("TITLE[%s]\nARTIST[%s]\nALBUM[%s]", title, artist, album));
                    }
                }finally {
                    trackCursor.close();
                }
            }
       }
    }
}

メニューから選択されるとActivityが起動される。その時にインテントの引数で現在再生中の曲情報がもらえるので、それをもとに楽曲データを取得する。今回はとりあえずとれたかの確認なので画面上に表示する。

動かしてみる

それでは、実機に転送して動作確認だ。

WALKMANアプリで「Infinite」ボタンを押す

f:id:osa030:20150406184817j:plain

このオジサンは誰なのか。気になる人は"ゴシゴシおじさん"で検索だ。本来は目潰ししてやりたいところだが、今はグッとこらえて"Infinite"を押すんだ。

Add-on一覧から対象のアプリを選択

f:id:osa030:20150406184824j:plain

"ほげほげ"が見えているぜ。アイコンはデフォルトなので気にすんな。因みに"再生中の曲を共有する"がお手本の「NowPlaying Music Extension」様だ

Add-onアプリ起動

f:id:osa030:20150406184832j:plain

ちゃんと再生中の楽曲情報がとれました。因みに「恋の都パリ」は名曲だ。

感想

以外と簡単だった。でもなんで最新版のSDKにはこの機能の説明がないのだろうか。パッケージ名がソニエリだからか?それとももうすぐWALKMAN切り離しかもしれないから?まあどっちでもいいんだけど。せっかくAPIとして使えるならもっと積極的に公開してくれるといいのに。

Android Studioではじめる 簡単Androidアプリ開発

Android Studioではじめる 簡単Androidアプリ開発

ザ・ゴシゴシおじさん

ザ・ゴシゴシおじさん