/* */ /* */

2013年3月8日金曜日

【Android】mupdfをAndroidに導入してみる【PDF】

最近更新していないや・・・
日記とは何だったのか。。。

今回は、mupdfに関してです。
AndroidでpdfのViewerを作ろうと思ったら一度は見かけるのでは無いでしょうか。

しかし、それでいて導入方法が分かり辛い(笑

今回は取り敢えず、mupdfのソースコードを実際にAndroidで動かす所までを
追って行きたいと思います。

NDKの導入が完了していて、"ndk-build"コマンドが通るように
パスを通してある状態を前提とします。

【1】
ソースの場所
http://mupdf.com/download/
ここから拾って来ませう。現在の最新版は「mupdf-1.2」でした。

archiveから「mupdf-1.2-source.zip」と「mupdf-thirdparty-2012-08-14.zip」をダウンロードしてきます。どちらも解凍します。

【2】
解凍してできた、「mupdf-1.2-source」の直下に「mupdf-thirdparty-2012-08-14」の中身(freetypeやらjbid2decやら)を入れます。

一応、「mupdf-1.2-source」のフォルダ名を「mupdf-1.2」に変更。

【3】
コマンドラインから、
$cd mupdf-1.2
$make
$cd Android
$ndk-build

【なんかエラーが出た場合】
$cd mupdf-1.2/Android/jni
$vi Application.mk
ここの中の
「#NDK_TOOLCHAIN_VERSION=4.4.3」
を
「NDK_TOOLCHAIN_VERSION=4.4.3」
こうしてコメントアウトを取ります。
んでもう一回コマンド試してみてください。

【完了】

こ、これで通るはず。。。
後は、AndroidのプロジェクトをEclipeで読み込んでやるだけ!
ね?簡単でしょ?(2日近く悩んでました)

色々メソッド等の紹介もしたいけど、自分も読み込んでいないので今日はここまで。。。



2012年12月7日金曜日

【Android】Ingressでポータル追加申請の方法【Ingress】

Googleの出したAR技術用いたゲーム「Ingress」

遊びたいのにポータルが全然近くに無いよ!!

って事でポータルの申請方法纏めておきます。


てか公式?にあるんですけどね・・・
ポータル追加方法とかの公式


Google先生にお力を借りて日本語訳


新規ポータルの提出

ポータル候補地の撮影と提出をする事によって、プレイフィールドへの追加の手助けをして下さい。
候補ポータルを送信する手順は次のとおり
  • カメラアプリでのGPSが有効になっていることを確認してください(オープンカメラ > [設定]> [ ストアの場所 > ON、オンにする必要があるかもしれない設定 > 位置情報サービス > 共有ピクチャの場所、利用可能な場合)。
  • 標準のカメラアプリでは、まずAndroid携帯で写真を撮る
  • 写真のオプションで共有を選択、
  • 共有「NIA Super Ops (入口ロゴ付き)」を選択
  • ポータルと提案するタイトルを入力して[OK]を選択。
  • これは、オブジェクトの写真と場所で私たちのアンティックオプスチームに送る電子メールを準備します。
  • 電子メールを送信します。
  • 当社の運用チームは、画像やオブジェクトの位置を確認し、それがポータルのための私達の一般的な基準を満たしている場合、ゲームデータベースに追加します。
一般ポータル基準:
  • 安全と公衆がアクセス可能である必要がある事
  • オブジェクトの例の種類:
    • 像
    • 独自のアーキテクチャ
    • 屋外壁画
    • 歴史的建造物
    • 特別な屋外ビル
    • ユニークな地元企業
ポータルが受け入れられるかどうかの決定は、2〜3週間以内に行われます。
受け入れられた後、2-3週で実際にそのポータルが活用される事を期待します。


・・・こんな感じ?訳は適当なので原文をご参照ください!
自分の場合は、撮った写真を「プレビュー」で開いて、
メニューボタン押して、「共有」から「NIA Super Ops」が選択できました。

実際にやってみると。

 写真を撮って・・・
 共有からNIA Super Opsを選択
 タイトル入力して

メーラーで送信!(実は英語で入力し直しました)













以上、ポータルの追加申請方法でした。

2012年12月5日水曜日

【Android】 Google発、AR技術とGPSを用いたゲーム【Ingress】

Googleから招待コードが届いたため、ちょっとだけプレイしてみました。
※チュートリアルのみですが、思いっきりネタバレ含みます。












Ingressの説明とかできればいいのですが、
自分も全然内容を知らないままやっております。

なんか、リアルなマップ使った陣地取りゲームみたいです。
これからはこういうゲームも増えて来るのかな・・・


右上の「OPS」からオプション開いて、
「MISSION」から各種チュートリアルを開始できます。


ってことでチュートリアル開始。
・・・の筈が。
良くわからないうちに1個目クリアしてしまっていました(笑



"聞こえますか?大事な事を言いますので良く聞いて下さい。"
"堅くなる必要はありません。これは形式的な物です。"
"あなたはゲームだと思ってダウンロードしたのでしょうが、それは違います!"
"根本て的に間違っているのです。"
"私たちの世界に浸透している、起源も意図も不明な未知のエネルギーがあります。"
"それは「エキゾチック物質」として知られています"

う〜ん、誰か英語教えて・・・
取りあえず、いつの間にかクリア(この台詞聞く事がミッションだったのかな?)


ってことで気を取り直して二つ目から・・・

"あなたの周りにある「XM」(エキゾチック物質)を集めて、スキャナを充電してね♪"






なんか、適当に歩いて光るってる奴(多分エキゾチック物質)
をある程度集めるとミッションクリアみたいです。
あまりにもサクッと終わったのでスクリーンショット全然撮ってない(笑
なんか、クリアした時にもメッセージ来てた筈。。。


てことで3つ目のミッション!



"ポータルへ行き、ハックせよ"
ハックは制圧とかそんな感じなのかな?







"ミッション-ポータルを制圧せよ"
"概要"
"-ポータルへ向かえ"
"-ポータルをタップしハックしろ"
(ポータルまで行ってポータルを画面で選択して、
「HACK」ボタン押せ。って事w)


"近くにポータルがあります"
"マップに表示されている円内にポータルが入るようにし"
"マップ上でポータルをタップします"
"HACKを選択してください"
"警告、これは敵対ポータルです"
"ハッキングした後、速やかに範囲外に移動して下さい"




え、離れなきゃ行けなかったのか・・・
SS撮るの夢中で全然読んでなかった(笑

ポータルが近くにあるとこんな感じに表示されます。
後は、近づいてポータル選択してハックすればオーケー!











こんな感じでミッションやっていきます。
一通りチュートリアルクリアしたけど、長くなりそうなんでブログはここまで。
(まだ倍以上SS撮ったけど面倒w)
後は実際にやってみてくださいな

道ばたでAndroidに目を落とす事に成りますので、周りには十分気をつけましょう!
でもって結構面白そうなので興味がありましたら是非!!


そいえば、何か機密文書っぽいのもゲット!






















2012年12月2日日曜日

【iPhone】Invalid Binary で陥った問題【ローカライズ】


Invalid Binaryに至る考えうる問題は一つではないため、
ここでは自分の陥った問題に関して紹介致します。

スプラッシュ画面(Launch Images)をローカライズ(多言語化)させて居たのですが、
それがマズかったようで、Default.pngとかを見つけられないとか言われました。

結論だけを言うと、info.plistファイルから該当する画像の列を削除すれば通りました。
削除した状態でもスプラッシュ画面は表示されるようです。
削除するのはinfo.plistの
Iconfilesの中とIconfiles(iOS5)->PrimaryIcon->iconfilesの中
にあるDefault.pngとDefault@2x.pngでした。

2カ所にある事に注意して下さい。


以下は、InvalidBinaryの段階でAppleから来たメールです。
Dear developer,
We have discovered one or more issues with your recent delivery for "DotToDot by Puzzles' Plaza". To process your delivery, the following issues must be corrected:
Invalid Image Path - No image found at the path referenced under key "CFBundleIcons": Default.png
Invalid Image Path - No image found at the path referenced under key "CFBundleIcons": Default@2x.png
Once these issues have been corrected, go to the Version Details page and click "Ready to Upload Binary." Continue through the submission process until the app status is "Waiting for Upload." You can then deliver the corrected binary.
Regards,
The App Store team

【Android】カラーコード一覧をxmlに纏めてみた【レイアウト】

12月に入り、アドベントカレンダーが始動しはじめたようです。

自分も参加したかったのですが、どうもマトモなネタをやっている時間が取れそうに無い・・・
でも悔しい
取りあえず12月中はブログの更新頻度を出来るだけ上げてアドベントカレンダーに対抗する事を目標にしようかと思います。


さて、そんなこんなで本題です。

Androidでレイアウトを弄ってる際「こんな感じの色が良いなぁ」
とか思い浮かべるかと思います。

そして、16進数で色を作って行く訳ですがコレが何かと面倒で・・・
サイトのカラーコード表を見ながらああでもないこうでもないと・・・

って事で、何番煎じか分かりませんが纏めてみました。

参考サイトは原色大辞典さんです。

githubに載せてあるのでどぞです。
https://github.com/Shift-Kumagai/AndroidLayoutColorXML

2012年11月26日月曜日

【iPhoe】価格の多言語対応について【StoreKit】

またもやiPhoneの話題です。
いい加減Androidに触りたいです。Rubyでも遊びたいです。


さて、今回の話題はiPhoneでの多言語対応、特に課金処理部分で私が躓いた点です。

課金処理の入ったiPhoneアプリで多言語対応にする際、
問題となるのは金額の表記だと思います。

日本の人には円表記で、海外の人には米ドル表記にしたい!となった時にどうするかなのですが、
公式のリファレンスそのままでオーケーです。


- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)responseの中で


NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale:product.priceLocale];
NSString *formattedString = [numberFormatter stringFromNumber:product.price];


この様にするだけで、自動で価格の表記が変わってくれます。

さて、ここで問題なのが”何に合わせて”表記が変化するのかです。
自分は最初、他の部分のローカライズと同じで、iPhone本体の言語設定から拾ってくれるのだろうと考えておりました。
実際は、”最後にログインしたAppleアカウントに紐付いている国”の表記がされます。
多分、請求とかでややこしくなるのを避ける措置なのかなと思います。

なので、本体設定を英語にして、表記をUSに設定しても、円単位の数字が返って来る事があります。
テストする時は他の国に設定したアカウントでログインする様にしてください。
ホント面倒です・・・


【iPhone】課金処理が勝手に走る状態の防止【StoreKit】

※この記事の内容はどう考えても推奨されません。その場しのぎです。
 実装しちゃって課金処理で不利益出ても何も出来ません。

※iOS7、iOS8で再度組み直してみたのですが、今コレ使えないみたいです。
 ダイアログ出る前にSKPaymentTransactionStatePurchasingが
 飛んできませんでした。

何やらiPhoneの課金処理に関する掲示板などを見ていると、
「アプリを起動すると何故か課金処理が走ってしまう」
というのを時々見かけます。

取りあえずその場しのぎの策に行き着いたので書き残します。

iPhoneアプリを起動して、特に操作をしていないのに、
課金のダイアログが出て、IDとパスワードを求められる事があります。
これは、前回何かしらのアプリを起動して、課金処理に入り、
課金処理が正常に終了しないままアプリが落ちるとなります。
次回起動した後、特定のタイミング(StoreKitさんが要らん親切で通知してくれます。)でダイアログが呼び出されます。

本当に厄介!!

この問題に突き当たるという事は、公式のプログラミングガイド通りに、
アプリ起動直後にオブザーバー(何か課金処理を管理してるっぽい奴)の登録をしているのだと思われます。
そすると、最初に登録したオブザーバーさんが律儀に途中で終わっちゃってるトランザクションを拾って来てくれるみたいです。(しかもストアキットさんの任意のタイミングで・・・)

なので。。。

これ破棄すればオーケー

「ちゃん再処理しろよ」という白い林檎からのプレッシャーを感じますが取り合えず無視
 だっていきなりダイアログ出てくるとか不審過ぎるし、タイミング取得できる様な仕組みも見当たらないし・・・


本題です。
ここではNonCondensableな課金を例として挙げております。


AppDelegate.h

@interface AppDelegate : UIResponder 


AppDelegate.m
//未完トランザクション用

-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{

    for (SKPaymentTransaction *transaction in transactions) {

        switch (transaction.transactionState) {

    

            case SKPaymentTransactionStatePurchasing: {// 購入中

                [queue finishTransaction:transaction];

                //アイテムID取得したいならこの部分

                break;

            }

            case SKPaymentTransactionStatePurchased: {// 購入成功

                [queue finishTransaction:transaction];

                break;

            }

            case SKPaymentTransactionStateFailed: { //購入失敗/中断

                [queue finishTransaction:transaction];

                break;

            }

            case SKPaymentTransactionStateRestored: {// 購入履歴復元

                [queue finishTransaction:transaction];

                break;

            }

        }

    }

}


//オブザーバーの削除(NSNotificationCenterで呼ばれる)


-(void)removeTransaction {

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

}

//オブザーバーの登録(NSNotificationCenterで呼ばれる)

-(void)addTransaction {

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

}


//なんか、スプラッシュ画面で呼ばれてる部分


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    〜〜〜〜〜〜〜

    //何か色んな処理 

    〜〜〜〜〜〜〜


    //オブザーバーの登録

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

    

    // 通知センターに登録

    //オブザーバーの破棄をするメソッド

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeTransaction) name:@"remove" object:nil];

    //オブザーバーの登録をするメソッド

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addTransaction) name:@"addtran" object:nil];

}
という具合に、アプリ起動時に未完トランザクション用のオブザーバーの登録を済ませてしまいます。
未完トランザクションがあった場合、-(void)paymentQueueホニャララが呼ばれますので取りあえずfinishTransactionを呼んじゃいます。
ダイアログが表示されるのは、1回目に
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
に入った後(1回目は購入中に入ります)なので、そこで終了させてしまえば
ダイアログは出ないみたいです。
「任意のタイミングで処理したい」ならば、「//購入中」の部分で
アイテムIDを適当なArrayにでも突っ込んで、
お好きなタイミングで課金処理を走らせると良いかと思います。
取りあえず破棄完了!!
でもこのままだと、未完じゃない新規のトランザクションまで破棄されちゃいます。
なので、別に実際の課金処理を用意してやります。
MyStoreObserver.h
#import 
@interface MyStoreObserver : NSObject
@end
MyStoreObserver.m
@implementation MyStoreObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    NSLog(@"paymentQueue:updatedTransactions");
    for (SKPaymentTransaction *transaction in transactions)
    {
        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchasing:
            {
                // 購入処理中
                break;
            }
            case SKPaymentTransactionStatePurchased:
            {
                [queue finishTransaction:transaction];
                // 購入処理成功時の処理
                break;
            }
            case SKPaymentTransactionStateFailed:
            {
                [queue finishTransaction:transaction];
                // 購入処理エラー。ユーザが購入処理をキャンセルした場合もここにくる
                // エラーが発生したことをユーザに知らせる
                // [self failedTransaction:transaction];
                if (transaction.error.code != SKErrorPaymentCancelled){
                    //エラーの場合
                } else {
                    //ユーザーがキャンセルした場合
                }
                break;
            }
            case SKPaymentTransactionStateRestored:
            {
                [queue finishTransaction:transaction];
                // リストア処理
                [self restoreTransaction:transaction];
                break;
            }
        }    
    }
}
// 全てのリストア処理が終了(その後、「購入処理の終了」が呼ばれる)
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue 
{
     //何かの処理   
}
// リストアの失敗(cancel時も呼ばれる)(その後、「購入処理の終了」は呼ばれない)
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
    //何かの処理
}
// 購入処理の終了
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions 
{    
    //南下の処理
}
@end

んでもって、後は実際課金走らせる部分で
○○○.m
//上の方で宣言しておく
MyStoreObserver *mySKObserver;
~~~~~
~~~~~
//ここでダミー破棄の通知
NSNotification *n = [NSNotification notificationWithName:@"remove" object:self];
[[NSNotificationCenter defaultCenter] postNotification:n];
//重複すると怖いので一応破棄。多分無くても大丈夫
[[SKPaymentQueue defaultQueue] removeTransactionObserver:mySKObserver];
//実際に走らせるオブザーバーを登録
[[SKPaymentQueue defaultQueue] addTransactionObserver:mySKObserver];
~~~~~~~~~~
~~~~~~~~~~
-(void)viewWillDisappear:(BOOL)animated{
    //使い終わったオブザーバーをここで削除
    [[SKPaymentQueue defaultQueue]removeTransactionObserver:mySKObserver];
    //ノーティフィケーションも削除
    [[NSNotificationCenter defaultCenter]removeObserver:self];
    
    //一応もう一回ダミーを立てるべきだろうか・・・
    //NSNotification *n = [NSNotification notificationWithName:@"remove" object:self];
}

という感じで、ダミーのオブザーバーと実際に課金走らせるオブザーバーを交換して上げる。
取りあえずはこれで動いてる感じ!!
参考サイト様一覧
【なんてこったいブログ】
http://nantekottai.com/2011/10/28/storekit/
【アルデンテ】
http://d.hatena.ne.jp/kozy_twt/20110401/1301680959
【In-App Purchaseプログラミングガイド】
https://developer.apple.com/jp/devcenter/ios/library/documentation/StoreKitGuide.pdf