[Android TV] recommendation の背景background imageについて

1月 17th, 2015

2015/1/29 追記
背景画像のファイルサイズが大きいとタイムアウトして背景表示に失敗します。
recommendationを作成するときに、事前にダウンロードしてディスクキャッシュしました。ContentProvider では、キッシュをチェックして表示することで解決しました。
キャッシュにはDiskLruCacheを使用しました。

Android TV の recommendationで背景を表示する方法が、ほぼ情報無し状態です。
仕様変更があったようで、sdk付属のサンプルコードも背景取得できないありさま。
そんなわけで、ググったりしつつで解決したのでメモしておきます。
背景画像は、http:// で取得して表示する方法です。

https://plus.google.com/100427843958963974912/posts/D22DJZkKhDo
がとても参考になりました。Thanks!!

まず、ContentProvider を用意します。openFile()のみ必要であとは空っぽで大丈夫です。
url.openStream()を渡すところはこれで良いのか?と思ったけど、まあ動いてます 😀

public class RecommendationContentProvider extends ContentProvider {
	
	public static String AUTHORITY = "your unique authority here";
	public static String CONTENT_URI = "content://" + AUTHORITY + "/";
	
	@Override
	public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
		ParcelFileDescriptor[] pipe = null;
		String path = uri.getPath();
		try {
			String decodedUrl = URLDecoder.decode(path.replaceFirst("/", ""), HTTP.UTF_8);
			pipe = ParcelFileDescriptor.createPipe();
			URL url = new URL(decodedUrl);
			new TransferThread(url.openStream(),
				new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1])).start();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return pipe[0];
	}
	
	static class TransferThread extends Thread {
		InputStream in;
		OutputStream out;
		
		public TransferThread(InputStream in, OutputStream out) {
			this.in = in;
			this.out = out;
		}
		
		@Override
		public void run() {
			byte[] buf = new byte[8192];
			int len;
			
			try {
				while ((len = in.read(buf)) > 0) {
					out.write(buf, 0, len);
				}
				in.close();
				out.flush();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	@Override
	public boolean onCreate() {
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection,
			String selection, String[] selectionArgs, String sortOrder) {
		return null;
	}

	@Override
	public String getType(Uri uri) {
		return "image/*";
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		return null;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		return 0;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
		return 0;
	}
}

ContentProviderは、AndroidManifest.xml に記載する必要があります。

	<application>
		...snip...
		<provider
			android:name="packagename.RecommendationContentProvider"
			android:authorities="your unique authority here"
			android:exported="true">
		</provider>

あとは、Notificationの作成だけです。

	Bundle extras = new Bundle();
	extras.putString(
		Notification.EXTRA_BACKGROUND_IMAGE_URI,
		RecommendationContentProvider.CONTENT_URI + URLEncoder.encode(data.getBgImageUrl(), HTTP.UTF_8));

	Notification notification = new NotificationCompat.BigPictureStyle(
			new NotificationCompat.Builder(context)
			.setContentTitle(data.getTitle())
			.setContentText(data.getBody())
			...snip...
			.setExtras(extras)
	).build();

以上


Flash Builder 4.7 で AIR SDK を最新にする

6月 2nd, 2014

Flash Builder 4.7で、プロジェクトを新規作成するとき、AIR SDKを変更できないし、「アップデートの有無をチェック…」しても変えられない。

そんなとき下記の方法見つけました。

[Flash Builder 4.7でAIR SDKをアップグレードする方法]
http://www.happytrap.jp/blogs/2013/04/08/10420/

無事に、AIR SDK 13.0 になりました。
もっと気軽に切り替えられると良いのですが。。。


ActionScritp3 multipart/form-dataでデータのアップロード

7月 31st, 2013

モバイルAIRでカメラ撮影した写真をmultipart/form-dataでWebにアップする流れのメモ。
写真がbitmapDataという段階からスタート。

// Jpeg 変換
var byteArray:ByteArray = new ByteArray();
bitmapData.encode(bitmapData.rect, new flash.display.JPEGEncoderOptions(), byteArray);

// Base64 変換
var base64Encoder:Base64Encoder = new mx.utils.Base64Encoder();
base64Encoder.encodeBytes(byteArray);

// POSTデータ作成
var formBuilder:MultipartFormDataBuilder = new jp.psyark.net.MultipartFormDataBuilder("207542376適当");
formBuilder.addPart("apiKey", "123456ホゲ");
formBuilder.addPart("inputFile", byteArray, "dummyName.jpg", true);

var urlRequest:URLRequest = new URLRequest(url);
formBuilder.configure(urlRequest);

var urlLoader:URLLoader = new URLLoader();
// ここらでイベントリスナーの追加処理。
urlLoader.load(urlRequest);

問題はPOSTデータの作成のところ。
http://www.libspark.org/wiki/psyark/MultipartFormDataBuilder
にあるMultipartFormDataBuilderを利用しましたが、うまくいきませんでした。
そんなとき、[AS3] PHPとAS3の連携 multipart/form-dataでデータのアップロード http://www.kuma-de.com/blog/2010-10-07/2352 が大変参考になりました。

ただ、このサイトのMultipartFormDataBuilder.asでもまだ動きませんでした。結論としては、追記にある最後のバウンダリの問題が原因でした。そこで、addPartの第4引数 last を追加して、バウンダリの最後に「–」が追加されるように修正しました。受け取り側をphpで実装した場合は、必要なかったです。javaのtomcatだと最後の「–」が必要でした。

理想的な修正は、configure()実行時に「–」を追加することかな。最後かどうかはコード側で勝手に判断してくれれば十分ですね。あと、Content-Type:もベタ書きも直さないと思いつつそのままw

package jp.psyark.net {
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.utils.ByteArray;
	
	/**
	 * multipart/form-dataのリクエストを作成するための簡単なクラスです。
	 */
	public class MultipartFormDataBuilder {
		protected var _boundary:String;
		protected var byteArray:ByteArray;
		
		/**
		 * コンストラクタです。
		 * 
		 * @param boundary バウンダリ(境界線)文字列です。送信する他のデータ中に出現しない文字列である必要があります。
		 */
		public function MultipartFormDataBuilder(boundary:String) {
			_boundary = boundary;
			byteArray = new ByteArray();
			addBoundary();
		}
		
		/**
		 * パート(部分)を追加します。
		 * 
		 * @param name このパートの名前です。content-dispositionヘッダのname属性に使われます。
		 * @param data このパートのデータです。ByteArray以外の値は文字列として評価されます。
		 * @param filename このパートのファイル名です。null以外の値を渡した場合、content-dispositionヘッダのfilename属性に使われます。
		 * @param last 最後のパートの時だけtrueにする。バウンダリに最後を意味する--を追加する。
		 */
		public function addPart(name:String, data:*, filename:String=null, last:Boolean = false):void {
			byteArray.writeUTFBytes('Content-disposition: form-data; name="' + name + '"');
			if (filename != null) {
				byteArray.writeUTFBytes('; filename="' + filename + '"');
				byteArray.writeUTFBytes("\r\n");
				byteArray.writeUTFBytes("Content-Type: image/jpeg"); //JPEG用
			}
			byteArray.writeUTFBytes("\r\n\r\n");
			if (data is ByteArray) {
				byteArray.writeBytes(data);
			} else {
				byteArray.writeUTFBytes(data);
			}
			byteArray.writeUTFBytes("\r\n");
			addBoundary(last);
		}
		
		/**
		 * multipart/form-dataのリクエストとして使えるように、URLRequestを設定します。
		 */
		public function configure(request:URLRequest):void {
			request.method = URLRequestMethod.POST;
			request.data = byteArray;
			request.contentType = "multipart/form-data; boundary=" + _boundary;
		}
		
		private function addBoundary(last:Boolean = false):void {
			if (last) {
				byteArray.writeUTFBytes("--" + _boundary + "--\r\n");
			} else {
				byteArray.writeUTFBytes("--" + _boundary + "\r\n");
			}
		}
	}
}

ActionScript3 BitmapDataをJpegやPNGに変換する

7月 30th, 2013

Flash Player 11.3 以降、BitmapDataにencodeメソッドが追加されました。
これを利用したBitmapDataのJpegやPNGへの変換方法をメモ。

var bitmapData:BitmapData = new BitmapData(100, 100, false, 0xED1A3D);
var byteArray:ByteArray = new ByteArray();
bitmapData.encode(bitmapData.rect, new flash.display.PNGEncoderOptions(), byteArray);

これで、byteArrayに変換後のデータが入ります。

bitmapData.encode()の第2引数を変えることによって、JPEGやJPEGXRにもできます。
以下の3種類

  • PNGEncoderOptions
  • JPEGEncoderOptions
  • JPEGXREncoderOptions

以下、wonderflにFlash Player 11.3以前のやり方のサンプルがあったので、forkして追加してみました。

BitmapDataのPNG, Jpeg, JpegXRへの変換 – wonderfl build flash online

// forked from kihon's flash on 2010-4-24
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.FileReference;
    import flash.utils.ByteArray;
    import mx.graphics.codec.PNGEncoder;
    import mx.graphics.codec.JPEGEncoder;
    import com.bit101.components.PushButton;
    
    public class Main extends Sprite
    {    
        private var canvas:BitmapData;

        public function Main()
        {
            canvas = new BitmapData(100, 100, false, 0xED1A3D);
            var bitmap:Bitmap = new Bitmap(canvas);
            addChild(bitmap);
            bitmap.x = 182;
            bitmap.y = 182;
            
            new PushButton(this, 182, 282, "旧方式 save(PNG)", onMouseClick);
            new PushButton(this, 182, 302, "旧方式 save(JPEG)", onMouseClick2);
            new PushButton(this, 182, 322, "FP11.3以降 save(PNG)", onMouseClick3);
            new PushButton(this, 182, 342, "FP11.3以降 save(JPEG)", onMouseClick4);
            new PushButton(this, 182, 362, "FP11.3以降 save(JPEGXR)", onMouseClick5);
        }

        private function onMouseClick(event:Event):void 
        {
            var ba:ByteArray = new PNGEncoder().encode(canvas);
            new FileReference().save(ba, "t.png");
        }
        
        private function onMouseClick2(event:Event):void 
        {
            var ba:ByteArray = new JPEGEncoder().encode(canvas);
            new FileReference().save(ba, "t.jpeg");
        }
        
        private function onMouseClick3(event:Event):void {
            var ba:ByteArray = new ByteArray();
            canvas.encode(canvas.rect, new flash.display.PNGEncoderOptions(), ba);
            new FileReference().save(ba, "t2.png");
        }
        private function onMouseClick4(event:Event):void {
            var ba:ByteArray = new ByteArray();
            canvas.encode(canvas.rect, new flash.display.JPEGEncoderOptions(), ba);
            new FileReference().save(ba, "t2.jpeg");
        }
        private function onMouseClick5(event:Event):void {
            var ba:ByteArray = new ByteArray();
            canvas.encode(canvas.rect, new flash.display.JPEGXREncoderOptions(), ba);
            new FileReference().save(ba, "t2.jxr");
        }
    }
}

SharedObject に Vector.<T> を保存するときのメモ

12月 27th, 2012

ActionScript 3.0

Vector.<String> 型を SharedObject に入れて取り出したとき躓いたのでメモ。

入れるときはそのまま入れます。

var hoges:Vector.<String> = new Vector.<String>();
...
var sharedObject:SharedObject = SharedObject.getLocal(SHARED_NAME);
sharedObject.data.hoges = hoges;

取り出すとき、そのままだとエラーとなります。

var hoges:Vector.<String>;
var sharedObject:SharedObject = SharedObject.getLocal(SHARED_NAME);
hoges = sharedObject.data.hoges;

TypeError: Error #1034: 強制型変換に失敗しました。
__AS3__.vec::Vector.<Object>@715f611 を 
__AS3__.vec.Vector.<String> に変換できません。

これは、Vector.<Object> として受け取るからですね。

そこで、キャストしてあげます。

var hoges:Vector.<String>;
var sharedObject:SharedObject = SharedObject.getLocal(SHARED_NAME);
hoges = Vector.<String>(sharedObject.data.hoges);

これで無事解決。


NetBeansで、PHPマニュアルを日本語版にする

8月 2nd, 2012

PHPのコーディングにNetBeans7.2を利用してます。

Ctrl+Shift+Spaceで表示されるポップアップのマニュアルリンクが英語版のため日本語に変更しました。

[インストールフォルダNetBeans 7.2]\php\phpstubs\phpruntime 以下を一括置換。

(置換前に、phpruntimeフォルダをバックアップしておきましょう)

‘http://php.net/manual/en’を
‘http://php.net/manual/ja’に置換。

一括置換は、適当にソフト使いましょう。
僕は、普段利用しているxyzzyエディタ標準の機能で一括置換しました。


[CityVille]攻略メモ

4月 8th, 2012

 facebook のゲーム「CityVille」がレベル100を超えたので、一区切りとして自分なりの攻略をまとめてみました。今年1月頭から始めたのでほぼ3ヵ月になります。無課金で遊んでいます。
 色んな遊び方があるかと思います。こういう遊び方(進め方)もあるんだなと参考にして頂ければ幸いです。

経験値

バケーション用飛行機

 バケーション用飛行機のウォール投稿をクリックすると、10経験値もらえます。このウォール投稿は、お隣さんだけでなく、他人のウォール投稿からでも経験値がもらえます。
 友達の友達をたどってウォール投稿をクリックしていく方法も考えられます。しかし、かなり手間がかかります。そこで、ウォールの共有サイトでクリックするのがお勧めです。

[CityVille Link Exchange]
http://gamersunite.coolchaser.com/games/cityville/link_exchange

[Cityville Exchange]
http://www.cityvilleexchange.com/

[CityVille Link Exchange]
http://www.cityvillelinkexchange.com/

 バケーション用飛行機関連(Vacation)の投稿をクリックします。
 クリックすると大半が「もうこの報酬を受け取っているようです!」の表示がでます。これは先着5名にしかもらえない仕様だからです。諦めずに新しい投稿をクリックしましょう。clicked times が5を超えているものは無視です。5以下でももらえないことが大半です。くじけない・・・ ;-(

 この先着5名というのは、きちんと調査したものではなく私の予想です。いずれにせよ、時間とクリック回数で、制限があると思います。

 あとは、コツコツクリックするだけで経験値がたくさんもらえます。


サマンサ空挺部隊w

12×12拡張

 拡張許可書も上記「経験値」の手法で同様に集めることができます。「Zoning Permit」をコツコツクリックします。

 拡張するときは、人口を必要条件ギリギリにします。必要条件以上の人口があると、その人口を基準に次の必要条件が決まるため、どんどん辛くなります。住宅を倉庫にしまって調整します。

 最大人口と人口の増加方法については後述

コイン

 1つの店をデコレーションで囲います。このときの考え方として、お店の面積が大きいほどデコレーションの影響を多く受けることができます。3×3より4×4の面積がボーナスを伸ばしやすいです。

 また1グッズあたりでもらえるコイン量がお店毎に違います。下の一覧が参考になります。

[Coins Per Good]
http://cityville.wikia.com/wiki/Coins_Per_Good
「Mega Nail Salon 3」でコインを稼ぐ人が多い理由が分かりますね

 テーマパークだと、こんな感じになります。9エナジー消費、11200個グッズ消費、1,365,840コイン獲得(フラメンコダンサーってもっと増やせます)。なお、9エナジー消費しても、得られる経験値は1か2です。このため、テーマパークの中身を減らして、消費エナジーを軽減するのもありです。面積10×10のため、ボーナスを増やしやすいです(注意・バラ園はテーマパークには効きません)。

 スペイン大使館でもらえる、フラメンコダンサーが1×1マスで収入+12%。強力です。

アイテム

 1日1回だけ出来るお隣さんへのアイテムリクエストは、リクエスト画面を同時に開くことで、複数個のリクエストを送ることができます。

同時にリクエスト画面を開くには下記のようなアイテムリンク集を利用して新規タブで開きます。

[CityVille Ultimate Material Links]
http://www.sierra-concepts.com/2011/07/cityville-material-links/

[City Ville 7 Sky]
http://cityville7sky.blogspot.jp/search/label/Request%20Material?&max-results=5

 動作が重く数を増やせない場合、複数の種類のブラウザ(IE, Firefox, Chromeなど)を同時起動してタブを増やしてみてください。別のPCが有ればそちらでも増やすことで同時に数十件リクエストを1人に送ることができます。

 なお、多数リクエストは、事前に了解を取った知人にだけやることをお勧めします。

エナジー

溶岩島

 12時間に1回エナジー3を得られます(1消費して4獲得)。また、島は完成したあとに重ねることができます。最大人口2500、人口2000も増えます。一押し。


21個の溶岩島があるため、半日毎に63エナジー回復します。

Zynga Bar

 ブラウザに Zynga Bar を入れると8時間毎に5エナジーもらえるようになります。

[Zynga Bar]
http://toolbar.zynga.com/

最大人口と人口

公共施設

 (追記 2012/4/28 プロディジースタジオは建設メニューから無くなりました)
 最大人口を増やすだけなら、公共施設「プロディジースタジオ」の乱立が楽です。
12人のスタッフが建設条件。5000人増えます。アップグレード無し。
(時間制限の施設のため、そのうち建設メニューから消えると思います)

 完成した島は、重ねることができる仕様のため、溶岩島、またはアロハ島の乱立もお勧めです。アロハ島は最大人口5000、人口4000増えます。溶岩島は、最大人口2500、人口2000と少ないですが、エナジーを半日に3回復できるため有利です。島は、建設のためのエナジーを消費しない点も魅力です。

住宅

 コインがある場合「スローンの住宅」が2650-4850人、3×3マス、家賃収入5分毎のため、人口を増やしやすくお気に入りです。ただし5,750,000コインします。

 (追記 2012/4/28 「ミラーハイツ」も道路との隣接が必須となりました)
 コインに余裕が無い場合「ミラーハイツ」が良いと思います。ミラーハイツは道路に隣接しなくても良いため、画面隅に乱立させやすいです。アイテム集めが大変なのが辛いところ。

引退者の確認

 以前の記事をご参考ください。

[「CityVille」お隣さんの引退者を把握する Greasemonkey スクリプト]
http://morishige.jp/blog/archives/211

最後に

こんな方法もあるよーって情報、ぜひ教えてください。


「CityVille」各種シャムロックを集める Greasemonkey スクリプト

3月 20th, 2012

もうやだ。
各種Shamrock集めに辟易しました。

そこで、CityVilleのウォール投稿共有サイトでコツコツとクリック。
もうやだ。

なんかこれにも辟易したので、欲しいアイテム名にマッチしたものだけ自動でクリックするようにGreasemonkey Script 書いた。
放置してたら、虹完成した。
今は反省している。

スクリプトの利用には修正が必要となるので、プログラムが分かる方向けです。
Google Chrome でしか動作確認していません。

https://github.com/morishige/CityVille/blob/master/ExchangeCityVilleAutoLink.user.js

targetsで指定した物を自動でクリックします。開いたwindowは、サイズなどを確認して自動で閉じます。ウォールは、経験的に5回クリックされるとアイテムがもらえなくなる??ようなので、5回以上クリックされたものは無視しています。

CityVilleウォールの共有サイト
http://gamersunite.coolchaser.com/games/cityville/link_exchange


「CityVille」お隣さんの引退者を把握する Greasemonkey スクリプト

3月 11th, 2012

Zynga社のブラウザゲーム「CityVille」で、引退したと思われるお隣さんを把握するためのGreasemonkeyスクリプトを作ってみました。

Firefox と Google Chrome で動作します。
Firefox で動かすには、Greasemonkey アドオン必要です。

http://morishige.jp/lab/CityVille/CityVille_CheckActiveUser.user.js
MIT license

*追記
githubに登録しました。
https://github.com/morishige/CityVille

Install

Firefox でクリックすると、Greasemonkey インストール画面が表示されます。「インストール」ボタンを押します。
(インストール画面が出ない場合、Greasemonkey アドオン のインストールを先にしてください)

Google Chrome でクリックすると、下部に
「拡張機能、アプリケーション、テーマはパソコンに悪影響を与える可能性があります。処理を続けてもよろしいですか? 続行 / 破棄」と表示されます。
「続行」を押すとインストールの確認画面が表示されます。「インストール」ボタンを押します。

Uninstall

Firefoxからのアンインストールは、「アドオン」→「ユーザスクリプト」で、CityVille_CheckActiveUser を「削除」します。

Google Chromeからのアンインストールは、「オプション」→「拡張機能」で、CityVille_CheckActiveUser を「削除」します。

使い方


お隣さんを開きます。
初回は、データの記憶のみとなり、画面の変化はありません。
開いたあと、再度「お隣さん」を開いてください。


経験値の横に、前回の記録日より変動がない場合「灰色」で最後の記録日。1週間以上変動がないと、赤文字で記録日。変動があった場合 (up 変動値 前回の記録日) が表示されます。

とりあえず、作ったばかりなので、暫くベータテストです。

追記

1週間、経験値に変動がないと、日付の色が変わります。引退と判断するには期間が短いかと思います。あくまでも目安としてご利用ください。アイテムリクエストの時の目安にもなると思います。

追記(を修正したました)

Mac でも動作報告いただきました。
Mac OS 10.7.3
Chrome 17.0.963.79

追記

同姓同名の方がいると、その方々については正しく判定できません。


Adobe Flash Builder 4 Plug-in で、sdk 4.5.1、Flash Player 11.1 を利用する

11月 13th, 2011

Eclipse の Plug-in として利用しているためか、ネットで公開されているやり方では一部上手く行かなかったためメモメモ。
既存のファイルを置き換える手法のため、かなり強引です。
(Eclipse は、日本語化していません。Flash Builder 4 Plug-in は日本語のため、混在してます)

http://clockmaker.jp/blog/2011/02/incubator/
こちらの手法などが上手くいかなかった時ようのメモです。

まず、sdk 4.5.1 をダウンロード
http://www.adobe.com/cfusion/entitlement/index.cfm?e=flexsdk

Plugin-in のインストール先のフォルダ直下にある「sdks」を開き、解凍したフォルダを「4.5.1」という名前で保存する。
Program Files (x86)\Adobe\Adobe Flash Builder 4 Plug-in\sdks

sdks\4.5.1\frameworks\libs\player
を開き「10.2」フォルダを「10.2_orig」としてリネーム。
新たに「10.2」を作成し、
http://www.adobe.com/jp/support/flashplayer/downloads.html
から、playerglobal11_0.swc をダウンロード。playerglobal.swc にリネームして、新規作成した10.2に設置する。

Adobe Flash Builder 4 Plug-in\player\win
を開き、「10.1」フォルダを「10.1_orig」としてリネーム。
新たに「10.1」を作成し、
http://www.adobe.com/jp/support/flashplayer/downloads.html
から、flashplayer_11_sa_debug_32bit.exe をダウンロード。FlashPlayerDebugger.exe にリネームして、新規作成した10.1に設置する。

Flex Builder 4 を起動し、Windows -> Preferences -> Flash Builder -> インストールされている Flex SDK を開きます。
「追加」ボタンから、Flex 4.5 として、 Adobe Flash Builder 4 Plug-in\sdks\4.5.1 の場所を指定。

プロジェクトを作成、または既存のプロジェクトにて、Properties を開きます。
ActionScript コンパイラー を開き、Flex SDK のバージョンが 4.5 であることを確認します。
追加コンパイラー引数に、-swf-version=13 を追記します。
-locale ja_JP -swf-version=13

11の新機能である、graphics.cubicCurveTo(…) を試してみる。
graphics.lineStyle(1, 0x000000);
graphics.moveTo(0, 0);
graphics.cubicCurveTo(100, 50, 100, 200, 200, 200);
が実行出来れば完了。