Category Archive: iPhone

[ANE][iPhone]AIR for iOSにて、スクリーンショットをカメラロールに保存するANEを作ってみた、がiOS6では機能しなかったという悲しい現実

以前書いた記事、Air for iOSにて、スクリーンショットをカメラロールに保存するANEを作ってみた、への追加メモです。

まず結論から、
iOS6では「スクリーンショットをカメラロールに保存するANE」は正常に機能しなくなりました。。
(iOS5では機能します)

そして色々検証してみたところ、
現状AIR for iOS(AIR3.4SDK)ではANE内でスクリーンショット(UIImageとして取得)することは無理じゃね?
という結論に達しました。

以下、無理じゃね?と思う理由が続きマス。
(解決策わかる方がいました教えてください。。)


■Objective-Cでのスクリーンショットを取るコードをiOS6上で動かしてみる

上記aneで使ったこちらのコード
これを使って、Xcodeを使ったObjective-Cプロジェクト(Xcode4.5のOpenGL Gameテンプレートを使用)でOpenGLで描画したもののキャプチャを取ってみようとしましたが、iOS6実機ではキャプチャが正常に取れません。
(Xcodeのシミュレーター上では正常にキャプチャできるんですが、iOS6実機ではキャプチャ画像は真っ白になってしまう)
※iOS5実機ではなんら問題なくキャプチャできます。

あら、そもそもiOS6ではOpenGL描画のキャプチャができなくなったの?
と思いましたが、そういうわけでもありません。


■Apple公式のキャプチャ手順

こちらにOpenGLの描画についてのキャプチャの取り方について記載されているのですが、やり方としては2種類あるようす。

1) Call glReadPixels before calling EAGLContext/-presentRenderbuffer

2) Set the CAEAGLLayer’s retained backing property to true to retain the contents of the layer. However, this can have adverse performance implications so you are cautioned to use this setting only when necessary.

上記2通りのやり方を、まずはObjective-Cプロジェクトを使って実装してみると、どちらを使ってもではOpenGL描画のキャプチャは取れました。

じゃあ、その2通りのどちらかをANE使って実装したらいいじゃん、ってことなんだけどこれがどうやっていいかわからず。

以下、それぞれの無理じゃねって理由です。


■やり方1)について

1) Call glReadPixels before calling EAGLContext/-presentRenderbuffer

これはglReadPixels()は、presentRenderbufferする前に呼んでね、ってことなんだと思います。
glReadPixelsはスクリーンショットを取るときに呼ぶメソッドなので、presentRenderbuffer()を実行する前のタイミングでスクリーンショットを取る処理を実行するようにしたいわけですが、presentRenderbuffer()はOpenGL描画の更新毎に呼ぶメソッドっぽい。
で、AIR for iOSでは描画更新処理というコアな部分の処理が具体的にどうなっているのかわからんのです。
(LLVMが具体的にどのようにコンパイル(AS3→ObjC)してるのかわからんので)

描画処理のコアな部分の処理をANEからオーバーライドなりして、修正することができればいけそうなんですけどね。どういう実装になってるのかわからんのでできません。
というわけで1)の案はANEで実装する方法がわからず。


■やり方2)について

2) Set the CAEAGLLayer’s retained backing property to true to retain the contents of the layer. However, this can have adverse performance implications so you are cautioned to use this setting only when necessary.

これは、CAEAGLLayer.drawablePropertiesにkEAGLDrawablePropertyRetainedBacking:YESを突っ込め、と。
ただそうするとパフォーマンス落ちるかもしれないから必要なときにだけYESにしてね、ということみたい。

CAEAGLLayerはANEからでも取得できました。

//UIWindowの下にCALayerがあってその下にCAEAGLLayerがありました。
UIWindow* win = [UIApplication sharedApplication].keyWindow;
UIView* uv = [[win subviews] objectAtIndex:0];
UIView* uv2 = [[uv subviews] objectAtIndex:0];
CAEAGLLayer* eagllayer = (CAEAGLLayer *) uv2.layer;

CAEAGLLayerが取得できればdrawablePropertiesにkEAGLDrawablePropertyRetainedBacking:YESを上書きするところまではできるのだけど、drawablePropertiesを変更した際にはEAGLContext.renderbufferStorage:fromDrawableを実行しないと反映されない。
で、これにはEAGLContextのインスタンスを取得しないとなのだけど、ここが無理っぽい。
先ほどと同様でLLVM後のコアな部分の処理が具体的にどうなっているのかわからんのです。
CAEAGLLayerをもつUIViewにEAGLContextは使われてると思うけど変数名がわからず、そもそも外部からアクセスできる変数かどうかもわからずです。

というわけで、Apple推奨のふたつの手順がAIR for iOSでは実装できないんじゃないかと思っているわけです。


というか、なんでiOS5ではできていたのかも謎です。
気になったのはTechnical Q&A QA1704 OpenGL ES View Snapshotに書かれたこの文章

Important: You must call glReadPixels before calling EAGLContext/-presentRenderbuffer: to get defined results unless you’re using a retained back buffer.

iOS6のベータが出回ったころに追記されたとかなら、iOS6で仕様が変わったのだと納得がいくんですけども。


これができないとiOSのTwitterAPIとかfacebookAPIのAPI使ってもアプリのキャプチャ画像添付ができないと思うんですよね。
Flash側で画面をBitmapDataでキャプチャしてそれをaneに送ってane側でBitmapDataをUIViewに変換することができればなんとかなりそうな気もするんですけども、Alternativa3Dで描画してる部分をBitmapDataにキャプチャしようとしたら(Web上ならできたのに)iOS上だとキャプチャとれず。

なんとかなる方法ないかなぁ・・・

p.s
iOS5以上から追加されたDLKViewクラス(CAEAGLLayerをもつUIView系クラス)にはsnapshotってメソッドがあって、これを実行するとUIImageがさくっととれちゃうんですよね。
AIR for iOSはiOS4もサポートしてるからDLKViewは使われてないんでしょうけど。
(ちなみにAIR for iOSではCAEAGLLayerをもつUIView系クラスはCTStageViewというクラスで定義されてるっぽい)
CTStageViewにもsnapshotみたいなAPI仕込まれていないかなぁ。。。

[iPhone][Alternativa3D][AIR]AIR for iOSでシンプルな3Dゲームをリリースしました。

メモ記事を書いてましたが先週やっとiPhoneアプリとしてリリースしました。

Live with the Wind.
support site
itunesStore

初めてFlash:Air for iOS(AIR3.3SDK)で作ってみたよ。
3DエンジンにはAlternativa3D(8.17.0)を使用したよ。

もろもろ苦戦したことは以前公開したStage3D勉強会#2の資料に書いたので興味ある方は読んでみてください。


■実装以外でのゲーム性について
▼気持ちよさの工夫
BGMのBPMに連動するような動きを意識
→風を連続で取ったときの効果音がBPMと連動するようにスピードを調整
→風車の首を降り始めは曲調が変わるタイミング
→あと風車が首を振るときのスピードもBPMと連動するような

▼飽きさせない工夫
上昇気流だけを取り続けて飛ばれるとゲームオーバーになりにくいが緊張感なくなりゲームが単調になる
追い風も取らせて緊張感のあるゲーム展開にしたい
→上昇気流だけを取りつづけた場合は無理ゲーになるような設定に。
 (風車の背がどんどん伸びていく)
→2種類のコンボ要素の追加
 (コンボを続けると風車の背が伸びにくくなるようにしている)
※「上昇気流を取る→風車がのびる」という部分がルール的には判りにくくなってしまったのでヒントの項目に記載したけど理解できてない人も多いかも。。

▼操作性について
iPhoneアプリというと傾きセンサーだけど今回は無しで。
プレイヤーが学習してやりこみ性あるゲームにしたかった。
傾きセンサーでは細かいコントロールができないので運要素が増えてしまう
個人的に思うようにコントロールできないのは嫌い、というのが一番の理由
あと電車でプレイしてる姿も少し恥かしくなるしね。


8月中は無料で9月から170円になりますので是非試してみてくださいまし。

※Flash製なので簡単にWEBおためしプレイ版も用意できますよ。
>FlashPlayer11.0
(音鳴ります)

[ANE][iPhone]Air for iOSにて、スクリーンショットをカメラロールに保存するANEを作ってみた

aneを使ってAir for iOS(AIR3.3SDK)でスクリーンショットを撮るお話。

ありそうでなかった、というかあったけどもうまく動かなかったので作ってみたらちょっとハマりました。


まず、タイトルどおりのaneのコードが公開されてました。
abhisek-mishra / ScreenShot

が、実装してみても想定通りに動作しない。。
Objective-C部分のコードを見てみると、UIGetScreenImage()というapple非公開APIを使用してる。
非公開APIを使うとリジェクト対象だそうでこれは使えないと。


とりあえず下の記事を参考にスタンダードな実装に変更してみる。
iPhoneアプリから画面のキャプチャー画像を取得する2つの方法

aneファイルをビルドしなおして再テスト。
が、画像はカメラロールに保存されたのは真っ白の画像。。

ちなみにObjective-CでiOSプロジェクトを作って、Xib上に適当にボタンとか画像とか配置した状態で上記の方法を実行すればスクリーンショットは問題なく取れるから根本的に間違ってるわけではなさげ。


肝はFlashの描画領域がどこにあるのか、ということ。
上記の記事のコードだと、

[app.keyWindow.layer renderInContext:UIGraphicsGetCurrentContext()];

UIWindowのkeyWindowのレイヤーをキャプチャしてるのだからFlashで言えばStage上のメインタイムラインをキャプチャしてるようなものなはずだから良さげな感じだけども結果は前述したとおりに真っ白。


で、結論。
上記の方法は使えないみたい。
app.xmlでのrenderMode要素をdirectを指定する場合はObjective-C側ではOpenGLESでのスクリーンショットを撮るような処理をしないといけないっぽい。
具体的なコードはここに書かれてるものを参考にしました。
GLPaint save image

このコードで取得したUIImageをキャプチャすることでとスクリーンショットを撮ることができました。


では、renderModeをcpu指定にすれば最初のコードでもスクリーンショットは撮れるのではないか?と思いましたが結果は否。
renderMode:cpuでは、上述のどちらのコードでもスクリーンショットを撮ることはできませんでした。
謎。。。
まぁrenderModeをcpuにする理由なんてない気もするのでまぁいいか。


各コードの詳細はQuiitaにあげてあります。
Qiita:AIR for iOSでスクリーンショットをカメラロールに保存するANEを作ってみたけど真っ白な画面しか取れない
(コメント欄で自己解決してます)

p.s.
ちなみに今回スクリーンショットを撮るのが最終目的ではなく、iOS5からのネイティブなTwitterAPIを使ってのスクリーンショットつきのTweet機能を実装したかったのでした。
これも無事にうまく実装できたので、また後で記事を書きます。

[iPhone][AIR]FlashDevelopにてaneを含んだiPhoneアプリのビルド方法

FlashDevelop(以下FD)のAIR Mobile AS3 AppプロジェクトにてANE(Native Extension for AIR)ファイルを含んでのipaファイルが書き出せたので手順をメモしておきます。


aneファイルはSTICKSPORTSさんが公開されてるANE-Silent-SwitchとANE-Game-Centerの二つを使ってみます。
どちらもDLしたサンプル一式の中にテスト用のドキュメントクラスが入っていますので、それを組み合わせてふたつの機能を持ったipaを作ってみます。

SilentSwitchはいわゆるマナーモードスイッチのこと。
ハードウェアスイッチのオンオフでサウンドのオンオフをする機能です。
(AIR for iOSだけではこの機能を使えない)
GameCenterはオンラインランキング等の機能が使えます。

この二つでとりあえずユーザーフレンドリーな簡単なゲームが作れますよね。


以下、必要なもの

  1. Windows環境(FlashDevelop使うので)
  2. FlashDevelop 4.0.3(現状での最新)
    http://www.flashdevelop.org/
  3. Flex 4.6 SD(現状での最新)
    http://www.adobe.com/devnet/flex/flex-sdk-download.html
  4. AIR 3.3 SDK(現状での最新)
    http://www.adobe.com/devnet/air/air-sdk-download.html
  5. aneファイル
    ANE-SilentSwitch
    ANE-Game-Center
    (テスト用ドキュメントクラスも含む)
  6. iOS 5.1 SDK
    (Xcode4.3からフォルダ抽出:macが無いと無理かも)
  7. iPhoneアプリ証明書ファイル(.p12)
  8. プロビジョニングファイル(.mobileprovision)

※5,6,7はiOS DevCenterより入手(要iOS developper登録)


手順

0.AIR 3.3 SDK対応のFlex 4.6 SDKを作る
DLしたAIR SDKをFlex SDKのフォルダに上書きコピー
(Flex SDKのフォルダ名をflex_sdk_4.6_air3.3としました)


1.FDで新規プロジェクト(AIR Mobile AS3 App)を作る


2.aneファイルとswcファイルをlibフォルダに格納し[ライブラリに追加]
・aneファイル2つとswcファイル1つ

  • StickSports-ANE-Silent-Switch-b70e35b\bin\SilentSwitch.ane
  • StickSports-ANE-Game-Center-a2d0263\bin\GameCenter.ane
  • StickSports-ANE-Silent-Switch-b70e35b\test\libs\sounds.swc

(aneファイルが入ってるフォルダ内のswcは使いません)


3.テスト用ドキュメントクラスをsrcフォルダに格納
(GameCenterExtensionTest.asをドキュメントクラスに)

  • StickSports-ANE-Silent-Switch-b70e35b\test\src\SilentSwitchExtensionTest.as
  • StickSports-ANE-Game-Center-a2d0263\test\src\GameCenterExtensionTest.as

4.GameCenterExtensionTest.asを修正

public function GameCenterExtensionTest()
{
	shape = new Shape();
	shape.graphics.beginFill( 0x666666 );
	shape.graphics.drawCircle( 0, 0, 100 );
	shape.graphics.endFill();
	shape.x = 0;
	shape.y = 240;
	addChild( shape );
	
	feedback = new TextField();
	var format : TextFormat = new TextFormat();
	format.font = "_sans";
	format.size = 16;
	format.color = 0xFFFFFF;
	feedback.defaultTextFormat = format;
	feedback.width = 320;
	feedback.height = 260;
	feedback.x = 10;
	feedback.y = 210;
	feedback.multiline = true;
	feedback.wordWrap = true;
	feedback.text = "Hello";
	addChild( feedback );
	
	addEventListener( Event.ENTER_FRAME, animate );

	GameCenter.init();
	createButtons();
	
	//以下の2行を追加
	var silentSwitch:SilentSwitchExtensionTest =  new SilentSwitchExtensionTest();
	addChild(silentSwitch).y = 230;
}

5.証明書ファイルとプロビジョニングファイルをcertフォルダへ格納
必要ファイルのプロジェクトへの設置はこれで完了
↓のようになりました


6.bat/SetupSDK.batを修正
4行目に手順0で作ったFlexSDKのパスを記述

:: Path to Flex SDK
:: 例
set FLEX_SDK=E:\00_flash\flex_sdk_4.6_air3.3

7.bat/SetupApplication.batを修正
18~22行目のiOSに関する部分を設定

:: iOS packaging
set IOS_DIST_CERT_FILE=
set IOS_DEV_CERT_FILE=cert\hoge.p12
:: ↓証明書を書き出す際に設定したパスワード
set IOS_DEV_CERT_PASS=certification_no_passward
set IOS_PROVISION=cert\fortest.mobileprovision
set IOS_ICONS=icons/ios

35行目のapplication IDを設定

:: Your application ID (must match <id> of Application descriptor)
:: ↓プロビジョニングファイルに紐付けたApp ID
set APP_ID=bz.393.forTest

8.Run.batを修正
6~11行目あたりのtarget項目を修正

:target
::↓ここをコメントアウトする
::goto desktop
::goto android-debug
::goto android-test
::goto ios-debug
::↓ここのコメントアウトを解除
goto ios-test

14~18行目あたりのdesktop項目を修正

:desktop
:: http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-6fa6d7e0128cca93d31-8000.html
:: ↓をコメントアウト
:: set SCREEN_SIZE=NexusOne
:: ↓をコメントアウト解除
set SCREEN_SIZE=iPhoneRetina

9.application.xmlを修正

<?xml version="1.0" encoding="utf-8" ?> 
<application xmlns="http://ns.adobe.com/air/application/3.1">
	
	<!-- プロビジョニングファイルに紐付けたApp ID -->
	<id>bz.393.forTest</id>
	<versionNumber>0.1</versionNumber>
	<supportedProfiles>mobileDevice</supportedProfiles>
	<filename>SilentSwitchGameCenter</filename>
	
	<name>SilentSwitch-GameCenter</name>
	<description></description>
	<copyright></copyright>
	
	<android>
		<manifestAdditions><![CDATA[
			
			<manifest android:installLocation="auto">
				<uses-permission android:name="android.permission.INTERNET"/>
				<uses-feature android:required="true" android:name="android.hardware.touchscreen.multitouch"/>
			</manifest>
			
		]]></manifestAdditions>
	</android>
    <iPhone> 
        <InfoAdditions><![CDATA[ 
		
			<key>UIStatusBarStyle</key> 
			<string>UIStatusBarStyleBlackOpaque</string> 
			<key>UIRequiresPersistentWiFi</key> 
			<string>NO</string>
			<key>UIPrerenderedIcon</key>  
			<true/>
			<key>UIApplicationExitsOnSuspend</key>
			<true/>
			
			<key>UIDeviceFamily</key>
			<array>
				<!-- iPhone support -->
				<string>1</string> 
				<!-- iPad support -->
				<!--<string>2</string>-->
			</array>
				
        ]]></InfoAdditions> 
		<requestedDisplayResolution>high</requestedDisplayResolution>
    </iPhone> 
	
	<initialWindow>
		<title>SilentSwitch-GameCenter</title>
		<content>SilentSwitchGameCenter.swf</content>
		<visible>true</visible>
		<fullScreen>true</fullScreen>
		<!--<autoOrients>false</autoOrients>-->
		<!--<aspectRatio>landscape</aspectRatio>-->
		<renderMode>direct</renderMode>
	</initialWindow>
	
	<icon>
		<image48x48>icons/icon_48.png</image48x48>
		<image57x57>icons/icon_57.png</image57x57>
		<image72x72>icons/icon_72.png</image72x72>
		<image114x114>icons/icon_114.png</image114x114>
		<image512x512>icons/icon_512.png</image512x512>
	</icon>
	
	<!-- extensions要素を追加(ane内のクラスを指定するってことかな?) -->
	<extensions>
		<extensionID>com.sticksports.nativeExtensions.SilentSwitch</extensionID>
		<extensionID>com.sticksports.nativeExtensions.GameCenter</extensionID>
	</extensions>
	
	<!-- 
	AIR options:
	http://livedocs.adobe.com/flex/3/html/File_formats_1.html#1043413
	
	AIR mobile options:
	http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-5d0f4f25128cc9cd0cb-7ffe.html
	
	Android manifest documentation:
	http://developer.android.com/guide/topics/manifest/manifest-intro.html
	-->
</application>

10.bat/Packager.batを修正
34~47のstart項目内の44行目を修正

if not exist "%CERT_FILE%" goto certificate
:: Output file
set FILE_OR_DIR=%FILE_OR_DIR% -C "%ICONS%" .
if not exist "%DIST_PATH%" md "%DIST_PATH%"
set OUTPUT=%DIST_PATH%\%DIST_NAME%%TARGET%.%DIST_EXT%
:: Package
echo Packaging: %OUTPUT%
echo using certificate: %CERT_FILE%...
echo.
:: aneファイルの入っているフォルダとiOS SDKのフォルダを指定する
:: (相対パスで指定する場合はプロジェクトのルートが基準)
call adt -package -target %TYPE%%TARGET% %OPTIONS% %SIGNING_OPTIONS% "%OUTPUT%" "%APP_XML%" %FILE_OR_DIR% -extdir lib/ -platformsdk E:/iPhoneOS51/
echo.
if errorlevel 1 goto failed
goto end

以上で準備完了です。


ctrl + Eneterでコマンドプロンプトが立ち上がり、大量のwarningが出ますが、distフォルダにipaファイルが書き出されます。
ipaの実機に転送がうまくいけばこんな画面が確認できます。

画面中央より上がGameCenter、下がSilentSwitchの操作となります。


動作確認の例として、[playSound1]を押すと音が鳴り始めます。
そのままiPhoneのサイレントスイッチ(いわゆるマナーモードのスイッチ)をオンオフしても音は鳴り続けますが、[silentSwitch]ボタンを押すとiPhoneのサイレントスイッチを切り替えることで音のオンオフが制御できるようになります。


GameCenterの確認方法は、iTunes Connect側での設定も必要です。
GameCenterExtensionTest.as内のleaderboardNameがiTunes Connectで設定したLeaderBoard IDと紐付けられますとなります。
achievementNameが、Achievement IDとなります。

これでFlashを使ってランキング機能付きのゲームも簡単に作れそうですね。


※その他、補足
aneファイルによってはiOS SDKの指定をせずともビルドできる場合があります。
その際、変更となるのは、手順10で以下のようになります

if not exist "%CERT_FILE%" goto certificate
:: Output file
set FILE_OR_DIR=%FILE_OR_DIR% -C "%ICONS%" .
if not exist "%DIST_PATH%" md "%DIST_PATH%"
set OUTPUT=%DIST_PATH%\%DIST_NAME%%TARGET%.%DIST_EXT%
:: Package
echo Packaging: %OUTPUT%
echo using certificate: %CERT_FILE%...
echo.
:: aneファイルの入っているフォルダのみを指定
:: (相対パスで指定する場合はプロジェクトのルートが基準)
call adt -package -target %TYPE%%TARGET% %OPTIONS% %SIGNING_OPTIONS% "%OUTPUT%" "%APP_XML%" %FILE_OR_DIR% -extdir lib/
echo.
if errorlevel 1 goto failed
goto end

aneファイルを作る際に使ったiOS SDKのバージョンに依存するみたい。
FlexSDKかAIR SDKのデフォルトで用意されてるiOS SDKがiOS4.2らしく、それでビルドされたaneファイルならiOS SDKを指定しなくてよいみたいです。
(最新のiOS SDKを指定しておけば下位互換があるかは試してません。。)

ちなみに現状Windows版のFlashCS6ではiOS SDKの指定ができないっぽいので上記2つのaneを実装したipaを作ることってできないんですよね。
WindowsでのiOS SDK指定が可能になったのはAIR3.3SDKからだからみたいです。

[iPhone]契約2年を迎えたときに、2年契約(キャンペーン)を更新する or しない のメリットとデメリット

iPhone(3GS)を契約して丸2年になったこともあり、softbaknkの窓口でタイトルどおりの質問をしてきたのでメモしとく。


まず、「2年契約(キャンペーン)」とは
たぶん最初にsoftbankに契約したときに入ることになるいわゆる2年縛りの契約。
この2年がたたないうちに契約を解除すると違約金を1万円くらい払わなきゃいけない。
これは、どこの携帯電話会社でもあるよね。


で、このまま何もしないと3年目からも「2年契約(キャンペーン)」に加入することになり、また2年縛りが始まり途中解約では違約金が発生する、ということ。

これが「2年契約(キャンペーン)」を更新したときのデメリットとなります。
「2年契約(キャンペーン)」に加入してるときは、2年契約(キャンペーン)の更新可能月以外はsoftbank解約時に違約金を払う必要があるので好きなときに解約しずらいということ。
ちなみに「2年契約(キャンペーン)」の更新可能月は、契約月+12,13,14の3ヶ月間。
たとえばボクの場合は2009年8月にiPhone持ったので、更新可能月は2011年の8,9,10月ということ。


では「2年契約(キャンペーン)」のメリット
パケットの上限が4410円になります。
ちなみに2年契約(キャンペーン)に加入してない場合の上限は5980円

下限はいずれも1029円なので、具体的には

  • 2年契約(キャンペーン)アリ:1029~4410円
  • 2年契約(キャンペーン)ナシ:1029~5980円

という料金形態になります。


こうなると毎月パケット上限まで使い切ってる人(つまりボク)は「2年契約(キャンペーン)」をナシにすると毎月の支払い額が増えてしまって微妙だなぁと思ったら、「パケットし放題フラット」というサービスもあると。
こちらに加入するとパケット使っても使わなくても毎月定額4410円のパケット代になると。


まとめると、
毎月パケットを上限まで使い切ってる人は、契約2年を迎えたときに迷わず「2年契約(キャンペーン)」の更新をとめる。
これで、3年目以降はsoftbank解約時に違約金を払わなくてすむので安心。
そして「パケットし放題フラット」に加入すれば月々の支払いは今までどおり。

毎月パケットを上限まで使い切ったり使い切らなかったりとムラが激しい人で、softbankから解約することはないって人は「2年契約(キャンペーン)」を更新してもいいんじゃないかな。

softbankの前はau使ってたのだけど、auは何年使っても契約月以外での解約は違約金払わされるシステムだった気がする。
そう考えると、softbankは良心的なんじゃないかと思った。


>2011.10.6追記


どうやらsoftbankの2年縛りには2種類あるらしい。

■1つは上にかいた「2年契約(キャンペーン)」
■もうひとつは、2010年4月27日から改定された「ホワイトプラン」(基本料金のプラン)

ボクの場合は2010年4月27日以前(「2年契約(キャンペーン)」に加入してる人はこうなるはず)にホワイトプランを契約してるので、上記に書いたとおり、「2年契約(キャンペーン)」を解除すれば2年縛りの呪縛から解除されて、いつ解約してもよくなるのだけど、2010年4月27日以降に契約した人は「ホワイトプラン」(iPhoneの基本料金プランなので必ず入ってるはず)に2年縛りの条項が追加されたので、2年縛りからの呪縛からは逃れる方法はないみたい。

詳細>>ソフトバンクの新ホワイトプランが“改悪”にしか見えない理由

全然良心的じゃないな。
あとよくよく考えたらauのときは端末代無料で2年縛り的なことがまかりとおってた時代だった。
端末代一括で払ったとしても2年縛りがつきまとう、依然よりも環境悪化した気がする。

[iPhone]UISliderにてvalue値固定でmaximumValueを変更した際にはUISliderの見た目が変化しないみたい。そんなときの無理やりな対処の仕方。

UISliderの挙動に悩みました。

やりたかったこと。
たとえば、UISliderが二つあって(sliderA,sliderBとする)、
初期値はこんな感じで、

sliderA.maximumValue = 200;
sliderA.minimumValue = 100;
sliderA.value = 150;
sliderB.maximumValue = 100;
sliderA.minimumValue = 0;
sliderA.value = 50;

sliderAのvalue値をsliderBのmaximumValueに対応させたい

//sliderAに対するValue changedなメソッド
-(IBAction) changeSliderAValue:(UISlider* )slider
{
    sliderB.maximumValue= sliderA.value;
}

sliderBはmaximumValueは変化するがvalueは変化しない。
この状態でsliderBの見た目(つまみの位置)が相対的に変化して欲しい。
が、変化しない。。

sliderBのvalueを変数で保持しておいて、明示的にsilderB.valueに代入してみてもだめ。

float sliderBValue;
//sliderAに対するValue changedなメソッド
-(IBAction) changeSliderAValue:(UISlider* )slider
{
    sliderB.maximumValue= sliderA.value;
    sliderB.value = _sliderBValue;
}
//sliderBに対するValue changedなメソッド
-(IBAction) changeSliderBValue:(UISlider* )slider
{
    _sliderBValue = sliderB.value;
}

どうも挙動を確認してみるとslider.valueには現在地と同じ値を明示的に代入しても見た目の変化は起きないようだった。
現在地と違う値を入れてあげれば、maximumValueに対応した見た目の変化も発生する。

で、考えた苦肉の策はこちら

float sliderBValue;
//sliderAに対するValue changedなメソッド
-(IBAction) changeSliderAValue:(UISlider* )slider
{
    sliderB.maximumValue= sliderA.value;
    //わざとランダムな数値を一度代入することで現在値を更新する
   sliderB.value =  arc4random() % 100;
    //改めて_sliderBValueを代入することで正しい見た目にする
    sliderB.value = _sliderBValue;
}
//sliderBに対するValue changedなメソッド
-(IBAction) changeSliderBValue:(UISlider* )slider
{
    _sliderBValue = sliderB.value;
}

もっといい方法がありましたら、教えてくださいませ。。

[AS][iPhone]FlashBuilder4.5のActionScriptモバイルプロジェクトで横向き固定の設定をした場合のステージサイズを正しく取得する方法

前の記事の続き、
FlashBuilder4.5のActionScriptモバイルプロジェクトでの設定のお話。

まず横向き固定にする方向は、hoge-app.xmlに

<!-- hoge-app.xml内のinitialWindow要素に指定 -->
<aspectRatio>landscape</aspectRatio> 

を設定するだけでOK。
これでデバッグプレビューすると確かに横向きでプレビューされる。
が、stage.stageWidthは320、stage.stageHeightは480と変更されていない。
(ちなみにFlexモバイルプロジェクトの場合はstage.stageWidthは480、stage.stageHeightは320となり問題ないようす)

ではどうしたらいいか、
結論としては、ドキュメントクラスのコンストラクタに以下の一行を追加
stage.setAspectRatio(StageAspectRatio.PORTRAIT);

//前提で、hoge-app.xmlに<aspectRatio>landscape</aspectRatio>と設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.PORTRAIT);
trace(stage.stageWidth, stage.stageHeight); //出力:480,320

解せないのが、なぜPORTRAITなのか。
通常はPORTRAITは縦、LANDSCAPEは横をあらわすので、stage.setAspectRatio(StageAspectRatio.LANDSCAPE);と設定すればいいと思ったのだけど、これだとstage.stageWidthは320、stage.stageHeightは480のままとなった。

//前提で、hoge-app.xmlに<aspectRatio>landscape</aspectRatio>と設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
trace(stage.stageWidth, stage.stageHeight); //出力:320,480

解せぬ。


※2011.8.15追記
上記設定だと実機転送した際に横方向にはならない様子。。。
やはりsetAspectRatio()にはStageAspectRatio.LANDSCAPEを設定しないと横向き固定にはなりませんでした。
上に書いたLANDSCAPE設定での懸念されるステージサイズは、
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
となっているようで実機起動上では特に問題なさげ。
ステージサイズがちゃんと取れないのはデバッグプレビューだけでのバグってことなのか!?

※2011.8.18追記
コメント欄にて教えていただきました。
stage.setOrientation(StageOrientation.DEFAULT)を設定することで想定したstageサイズを取得することができました。

//前提で、hoge-app.xmlに<aspectRatio>landscape</aspectRatio>と設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
stage.setOrientation(StageOrientation.DEFAULT);
trace(stage.stageWidth, stage.stageHeight); //出力:480,320

[AS][iPhone]FlashBuilder4.5のActionSclriptモバイルプロジェクトにて、iOSでプレビューした際のステージサイズが正常に取れない場合

だいぶはまってネットに情報が見当たらなかったのでメモ。

FlashBuilder4.5でiPhone、Androind等のアプリを作るため、以下2つのプロジェクトが用意されました。

  1. Flexモバイルプロジェクト
  2. ActionScriptモバイルプロジェクト

1.はMXMLベースのプロジェクトで2はASだけで作れるプロジェクト。
ボクはMXMLはさっぱりなのでASだけで作れる2.を選択。
普通のFlashコンテンツを作ると同様にドキュメントクラスからゴリゴリ書いていけばOKですが、
iOS用の書き出しをした際にステージサイズの参照値おかしなことになりました。

こちらの想定は、シミュレートデバイスが、iPhone3GSなら320 × 480、
iPhone4設定なら、640 × 960となってほしいところですが、
stage.stageWidth,stage.stageHeightのtrace結果は常に、500, 375

なんぞこれ、と思えどステージサイズの設定する箇所は見当たらず。
ためしにapp.xmlのwidthとheightに直接値(320 480)を入れてみるも変化無し。
さらにドキュメントクラスにSWFのembedタグを書いてみるも変化無し。


FlashBuilderのHelpを観てみるとこんなページに行き着きました。
http://www.randytroppmann.com/2011/04/12/pure-as3-workflow-with-flex-builder-4-5/

そこに書かれていた見慣れぬ1行を追加してみると。。。

stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;

これを入れることでstage.stageWidth,stageHeightが想定通りの値となりました。
(シミュレートデバイスを変えることにより値も変化する)
とりあえず、よくわからんけど、上記一行は必須らしい。


P.S.
Retina対応もできるらしいけど、3G/3GSとRetinaの混合設定がよくわからん。。
highを書くだけで、Objective-Cみたいに自動でいい感じに変換してくれるのか、それとも2種類の画角を分けて作らないのいけないのか。。
Retinaの実機がないから検証できんのよね。。

[iPhone]UISliderのつまみ(thumb)を独自の画像に変更するときの注意

簡単にできたようで出来てなくてちょっとはまったのでメモ

基本的にはメソッドが用意されます。

//setThumbImage
//使用例
//speedLevelSliderというUISliderが宣言してあって、Resourceに"sliderThumb.pngがあるとして
//sliderThumb.pngはwidth:100px,height:100pxとする
//通常状態
[speedLevelSlider setThumbImage:[UIImage imageNamed:@"sliderThumb.png"] forState:UIControlStateNormal];
//つまみをタッチ状態も登録しておかないとデフォルトが表示されちゃう
[speedLevelSlider setThumbImage:[UIImage imageNamed:@"sliderThumb2.png"] forState:UIControlStateHighlighted];

これだけで指定した画像につまみが変更される。
が、UISliderをInterfaceBuilderで配置した場合にはこれだけではうまくいかない場合がある。
デフォルトのUISliderのheightは23になるのだけど、自分で用意したつまみ画像の高さが23を超える場合は、はみ出した部分はタッチ領域にならない。
上記の例だとつまみの高さは100pxなので見た目はでかいつまみになっているけど、実機でタッチできる領域は中心の23px分しか反応しないことになる。
InterfaceBuilder上からheightを修正してあげればいいかと思うと、Hの領域だけグレイアウトされていて修正ができない.

なのでframeプロパティを修正して描画領域を書き換えてあげないといけないのでした。

//変更前
//Sliderのx,y座標やwidthはInterfaceBuilderから確認
speedLevelSlider.frame = CGRectMake( 10, 200, 200, 23);
//変更後
//(実際は左上基準なので、つまみが大きくなった分、y座標も修正する必要あります)
speedLevelSlider.frame = CGRectMake( 10, 200, 200, 100);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
というようなことが下記のブログには、しっかり書かれていましたのですが、、
スライダーバー(UISlider)のカスタマイズ的:いまログ
細かいところが理解できずに結構はまってしまった。。。

[iPhone]Packager for iPhoneで書き出したipaファイルを実機転送すると署名が有効ではないと怒られる場合

FlashCS5の目玉機能iPhoneアプリの書き出し。
これの実機転送ができずに半年くらい途方にくれてましたが本日ようやく解決。

Windowsじゃできないんじゃないとの疑惑さえ沸いてましたがなんてことはなく、手順が悪かっただけでした。
ちなみに実機への転送は、Appleのデベロッパー登録が必要です。
(年間10800円 )

やり方はAdobeの提供してるPDFファイルを読めばできるはずなのだけども、ボクのケースでは一箇所だけ書いてある手順でできなくて、そこで勘違いしてずーっとハマってました。

ハマった項目、それは開発証明書ファイル( 拡張子 .p12 ) の設定です。
上記PDFには、

Mac OS での iPhone 開発用証明書の P12 ファイルへの変換
Apple iPhone 証明書を Apple からダウンロードしたら、P12 証明書形式に書き出します。Mac® OS でこれを行う手順は次
のとおりです。
1 アプリケーション/ ユーティリティフォルダー内にあるキーチェーンアクセスアプリケーションを開きます。
2 証明書をキーチェーンにまだ追加していない場合は、ファイル/読み込みを選択します。次に、Apple から取得した証
明書ファイル(.cer ファイル)に移動します。
3 キーチェーンアクセスの「分類」で「鍵」を選択します。
4 使用している iPhone 開発用証明書に関連付けられている秘密鍵を選択します。
秘密鍵は、ペアになっている iPhone Developer: [ 名] [ 姓] 公開証明書によって識別されます。
5 ファイル/書き出すを選択します。

6 .p12(Personal Information Exchange)ファイル形式で鍵を保存します。
7 この鍵を別のコンピューターに読み込むときに使用するパスワードを作成するよう指示があります。

とありますが、僕のmacの環境にはこれがありませんでした。
( iPhone Distribution しかない。。)

仕方ないので、 iPhone Distributionの証明書を書き出して、それを使ってFlashCS5でiPhoneアプリ形式での書き出しを行ったわけです。
これはエラーもなく、ipa形式のファイルを作ってくれます。
が、正規の手順どおりにiTunesから実機に同期しようとすると、つぎのようなエラーがでるのです。
署名者が有効でないため ~ インストールできませんでした。

わけわからんですよ。
そこでAdobeの指示は無視して、keychainの分類で、ではなく、証明書の項目を見てみます。
するとiPhone Developperというそれっぽい項目がありました。

結論としては、ここでの証明書の項目(上記画像で選択されている部分)を.p12形式で書き出せば上手くいきます。

・・・ここでは罠があります。
秘密鍵の項目(上記画像で選択されている部分の一つしたの部分 )を.p12形式で書き出すこともできるのです。
この.p12ファイルを使っても、FlashCS5からはipa形式のファイルを書き出すことができます。
が、iTunesの同期で上に書いたようなエラーがでるのです。
(これでずーっとはまってた)

結論としては、書き出すファイルは、秘密鍵ではなく、証明書なんですよね。
AdobeのPDFではそのへんが明確に書いてないのでよくわからんのですよ。

でも、ググっても困ってる人の情報はぜんぜんないのですよね・・・
皆一発でできてるのかしら・・・
単に私がアンポンタンなだけなのかしら・・・
とにかく、この記事が同じ悩みがある人の助けになれれば幸いです。

P.S.
そして、書き出したアプリは予想以上に重かったw