2012年12月2日日曜日

夢次元の芸術家(ロック画面の壁紙をアプリから変更する)

 一年ほど前に、WP7でAdventCalenderというイベント記事を書きました。今年もWP8でAdventCalenderイベントがありましたので、参加しております。まだ国内未発売ということもあって、参加者は多くないです。まぁここ最近のネガティブニュース続きでは、中々WP8に手を出してみようとは思えませんものね、仕方ありません。
 ですが将来的にはWP8国内発売の可能性も十分に見込めるので、ボチボチさわりはじめていきましょうか。


 というわけで、2日目担当の僕のお題は
「ロック画面の壁紙をアプリから変更出来るようになったよ!やったねタ○ちゃん!」
 で行きます。(



---------------------------------------

 個人的に予てからずっと要望していた機能の一つが「アプリからロック画面の壁紙を変更する機能」でした。この機能がついに、WP8から正式に実装されております。
 用途としてはいろいろ考えられますが、例えば何かしらのイベントにあわせて壁紙を自動で更新していく(例:日替わり画像や時間帯による画像、また天気の画像など)機能もアリですね。あと仕事時とプライベート時で壁紙を変えたい場合なんかもありますので、それ用のショートカットにも出来ます。
 それでは早速、その機能の使い方を見ていきましょう。


1.ソリューション作成
 普通にVisualStudio2012 for WindowsPhoneを立ち上げて、新規ソリューションを作ります。アプリケーションの対象OSバージョンを聞いてくるので、WP8を選択します。
 尚、今回は事前に画像などは用意しておきましたので、「wallpaper」フォルダを作成してその中に突っ込んでおきます。


2.XAML編集
 お試しレベルなので、適当にソイヤッセイヤッとボタン配置しただけです。



3.コードを弄る前に、マニフェストへの追記を行う
 「WMAppManifest.xml」を開いて、Extensionsを追加します。ただし普通にダブルクリックで開くとGUIツールで開かれてしまい、ここではExtensions要素の追加が出来ませんので注意してください。コードエディターで開きましょう。
 開いたら「Extensions」要素を探しましょう。はい、ありません。Extensionsは標準では持たない要素なので、自分で追記してやる必要があります。Tokensの後ろ辺りにでも、以下のように追記しましょう。
(諸事情により、<>を全角で記載しています)


<Extensions>
  <Extension ExtensionName="LockScreen_Background"

                       ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}"
                       TaskID="_default"
 />
</Extensions>

 尚、ExtensionNameとConsumerIDは固定値です。これを変更すると動きませんので注意しましょう。


4.お待ちどう!C#で壁紙変更のコードを書き書きする
 さて、前準備は整いましたので早速コードを書いていきましょう。
 まず最初に行うべきこととして、「現在このアプリが壁紙変更を行う権限があるのかどうか」を確認します。というのも、壁紙変更可能なアプリとして設定できるのは1つだけなので、自分自身がそれに設定されていないと、UnauthorizedAccessExceptionが発生します。

 ではどうやって確認するのか? 「Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication」の戻り値から判定します。今後もしばらく使うので「using Windows.Phone.System.UserProfile;」あたりを宣言しておいてください。以後は、using句が記述されているものとして話を進めます。
 このIsProvidedByCurrentApplicationはbool値を返します。falseが返ってきたら、権限無しと判断します。
 もし権限が無い場合は、OSの「設定」画面からアプリを選んでおいてもらう必要があります。面倒くさいです。しかしコードで「今、こいつを設定しちゃっていい?」と聞くことが可能なので、アプリ内から呼び出してあげるのが親切でしょう。
 設定するかどうかを尋ねるには「LockScreenManager.RequestAccessAsync()」を使用します。尚、このメソッドはawaitで呼び出さないと使用できませんのでご注意ください。
 ではここまででどんなコードになるか、ちょっと確認してみましょう。

var isProvider = LockScreenManager.IsProvidedByCurrentApplication;
if (!isProvider)
{
    var _UserSelect = await LockScreenManager.RequestAccessAsync();
    isProvider = _UserSelect == LockScreenRequestResult.Granted;

}

  こんな感じです。LockScreenManager.RequestAccessAsyncを実行すると、↓の画像みたいなメッセージが出てきます。


 はいが押されたのかいいえが押されたのか、を「_UserSelect == LockScreenRequestResult.Granted」で確認しているだけですね。
 


 では肝心の、壁紙変更そのもののロジックはどう書くのか?
 これもさほど難しくありません。権限がある状態で、画像のUriを渡してやるだけです。ね、簡単でしょう?
 ただしUri指定時には一点注意が必要です。それは画像の場所です。
 画像がXAPに含まれている場合と、アプリ固有のデータ領域(要はストレージ領域)を使う場合で、指定方法が若干異なります。具体的には、場所に応じて以下の文字列を頭に付けておかねばなりません。
 XAPに含まれる場合 :ms-appx:///
 データ領域を使う場合:ms-appdata:///Local
 今回はXAPの中に画像を直接突っ込んでいるので、「ms-appx:///」を使います。ではコードです。

var _FileUri = new Uri("ms-appx:///" + _aFileNameStr);  //_aFileNameStr = wallpaper/wallpaper.jpg
LockScreen.SetImageUri(_FileUri);


 これだけです。ね、簡単でしょう?
 ではここで一度、コードをおさらいしておきましょう。今回、私は画像ファイル名を引数として受け取るメソッドを1つ用意し、その中に上記コードを記載しておきました。各ボタンは押されたときに画像ファイル名をそのメソッドに渡すだけです。

//using Windows.Phone.System.UserProfile
//await を使うので、 async Task型
private async Task Call_SetLocScreenImage(string _aFileNameStr)
{
    //このアプリが、ロックスクリーンのアプリとして設定されてるかどうか
    var isProvider = LockScreenManager.IsProvidedByCurrentApplication;
    if (!isProvider)
    {
        var _UserSelect = await LockScreenManager.RequestAccessAsync();
        isProvider = _UserSelect == LockScreenRequestResult.Granted;
    }


    if (isProvider)
    {
        var _FileUri = new Uri("ms-appx:///" + _aFileNameStr);
        LockScreen.SetImageUri(_FileUri);
    }
}



5.実行結果の確認
 では早速、結果を確認していきましょう。
 今回私は、以下3つのファイルを用意しました。
・768*1280の画像(画像は コチラ からお借りしました)

・720*1280の画像(画像は コチラ からお借りしました)

・600*600の画像(画像はPixivの コチラ からお借りしました)




 エミュレータはWXGA(768*1280)のものを起動します。そして、それぞれの実行結果のキャプチャ画像を以下に提示します。
 
 
 


(画像のチョイスに特別な意図はありません)
 という感じで、簡単に実装出来ました。
 また、600*600の画像のように、端末解像度と画像サイズが合っていない場合は、自動的にセンタリングされるということもこの結果からわかります。必要に応じて画像の範囲切り取りなどを事前に行っておいたほうが無難といえるでしょう。

---------------------------------------

 というわけで、2日目担当OD-10Zでした。いかがでしたか?
 既にこの解説記事が複数出ているうえに私自身も田中さんのblog「銀の光と碧い空
 の記事を元にしています。去年同様パk……インスパイアされてお題を決めました。

 ここからは余談ですが、本当ならば追加として「LockScreen.GetImageUri」についてもこのあとに続けて書く予定でした。が、この記事編集開始した段階でちょっと弄ってみたところ、どうも想定していたものとは違う動きをしたので、ここまでで切ることにしました。いやぁちゃんと前もって予習しておかないとダメですね。申し訳ないです。
(想定していた動き:変更前にGetImageUriをしておいて画像を保持しておいて、後からワンタッチで戻せるようにする、など
 実際の動き:アプリ自身がSetしてある場合じゃないとUnauthorizedAccessExceptionになる……(例:OSのPictureHubで壁紙設定してから、アプリに移動してGetImageUriすると落ちる))


 それでは今度こそ終了です。次回があればちゃんと予習してから書くことにします!(当たり前だ
 では3日目担当のmasakさん、よろしくお願いします。


彼は手練の技を熟知している。

0 件のコメント:

コメントを投稿