2017年7月20日木曜日

色の候補

アプリで使う色でベースカラーは決まってるけど、少し明るい色とか、少し暗い色などベースカラーを基に色を決める時に便利だったサイトをメモ

paletton

http://paletton.com/

色を指定するだけで候補を出してくれるので便利!


2017年7月14日金曜日

チャットっぽいレイアウトのメモ

とあるアプリのいち機能としてコメントの投稿機能を作ろうとしてチャットっぽい画面を作ったのですが、用途に合わずお蔵入り
折角レイアウトを作ったのでメモとして書き残しておきます




チャット部分はRecyclerViewにして、そのAdapterを用意します

ChatAdapter
//重要なところだけで、その他は省略


    @Override
    public ChatAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        switch (i) {
            case VIEW_TYPE_LEFT:
                return new ViewHolder(mInflater.inflate(R.layout.left, viewGroup, false));
            case VIEW_TYPE_RIGHT:
                return new ViewHolder(mInflater.inflate(R.layout.right, viewGroup, false));
            default:
                return new ViewHolder(mInflater.inflate(R.layout.left, viewGroup, false));
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (mItems.get(position).isShowLeft) {
            return VIEW_TYPE_LEFT;
        } else {
            return VIEW_TYPE_RIGHT;
        }
    }

getItemViewTypeで表示の位置を判定して、それに伴ってonCreateViewHolderで使うlayoutファイルを切替えています

left.xmlでは左に寄った表示レイアウト
right.xmlでは右によった表示レイアウト
これらを用意するだけで画像のようなレイアウトになります


left.xml(right.xmlもほぼ同じなので省略)
※XMLをSyntaxHighlighterで表示しようとしたら、崩れてグチャグチャになっちゃったので、そのままコードを貼ってみた

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/user_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="42dp"
        android:text="なまえ"
        android:textColor="@color/lite_gray"
        android:textSize="@dimen/text_small" />

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/user_name"
        android:layout_below="@+id/user_name"
        android:background="@color/lite_gray"
        android:paddingBottom="@dimen/space_small"
        android:paddingLeft="@dimen/space_x_small"
        android:paddingRight="@dimen/space_x_small"
        android:paddingTop="@dimen/space_small"
        android:text="Left message.\nhogehoeg" />


    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/user_image"
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:layout_alignBaseline="@+id/message"
        android:layout_marginLeft="@dimen/space_x_small"
        android:clickable="true"
        android:src="@mipmap/ic_launcher"
        app:civ_border_color="#FFFFFF"
        app:civ_border_width="1dp" />

    <TextView
        android:id="@+id/send_at"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/message"
        android:layout_below="@+id/message"
        android:text="7/2 11:00"
        android:textColor="@color/lite_gray"
        android:textSize="@dimen/text_small" />

</RelativeLayout>

2016年12月27日火曜日

場所を選択するUIで地図を表示する必要があり、DialogFragmentでMapFragmentを設定した際に、1回目の表示の時は問題ないけど、2回目に表示しようするとDuplicate idのエラーが発生した


 Duplicate id 0x7f0e00d9, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.SupportMapFragment


1回目の時にDialogをdismissしてもMapFragmentはクリアされてないらしい
そのため2回目でDuplicateとなってしまっている


結論として、DialogFragmentのdismissをオーバーライドしてmapのFragmentをremoveすることで対応した



<fragment android:id="@+id/map" class="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="250dp" />


@Overridepublic void onDismiss(DialogInterface dialog) {
  super.onDismiss(dialog);
  if (getActivity() != null) {
    FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
    Fragment fragment = fragmentManager.findFragmentById(R.id.map);
    if (fragment != null) {
      getActivity().getSupportFragmentManager().beginTransaction().remove(fragment).commit();
    }
  }
}


同様の問題がDialogFragmentでなくFragmentで起こる場合には、onDestoroyView()の中で同じようにMapFragmentを削除してやれば問題なく動作すると思う

2016年5月6日金曜日

GoogleApiClientでerrorCode=2が出る

お客様の端末を借りてテストをしてみたらGoogleApiClientを使うと位置情報の取得を開始しておらず「あれ?」と思ったらonConnextionFaildに処理が来ててerrorCodeが2になっていました

調べてみると「SERVICE_VERSION_UPDATE_REQUIRED」とのこと

参考: Google APIs for Android#ConnectionResult


どうやら端末のGooglePlayServicesが古いようですね
GooglePlay開発者サービスをバージョンアップすることで問題解決


こういうのって、利用者にエラー表示すると伝わるんだろ???

「GooglePlay開発者サービスが古いのでバージョンアップしてください」とダイアログでも出せばいいのかな?


「GooglePlay開発者サービスってなに?」ってなりそうだな・・・

2015年3月28日土曜日

Androidで文字の大きさを指定する際はdpではなくspで指定するのは当然なのですが、利用する場所にあわせてdpを使うことも検討しましょう

spを指定した場合、画面の解像度やユーザーのフォントサイズ設定によって文字の大きさが決められます
そのためレイアウトが大きく崩れる場合はdpを使うのも良いと思います
もちろんユーザーの指定にあわせてレイアウトが崩れないようにするのがベストですけどね


今回、驚いたのは父親がスマートフォンに変えたということで電話帳の文字が小さいので大きくしてくれと言われました
そこで、設定からフォントサイズを中→特大に変更したのですが、電話帳の文字は変化することなく小さいままでした
きっとspではなくてdpで指定しているんでしょうね
こういうところはspで指定しないとダメです

使い所に合わせてdpを検討するとしても基本はspなので注意した方がいいですね


2015年1月21日水曜日

製作のお手伝いをさせて頂いたアプリの紹介をした際にGooglePlayからダウンロードする為のリンクを作ろうと探したらGoogleがGeneratorを用意していたので「これは便利だな」と思ったのでご紹介

すでにご存知の方の方が多いと思いますが・・・ 

利用方法


http://developer.android.com/distribute/tools/promote/badges.htmlにアクセス

そうするとGeneratorの画面が表示されます



ボタンを押すとこんなリンクのHTMLが出てくるのでダウンロードボタンを配置したいサイトにコピペするだけ


テスト用の画像も表示されているので、すぐに動作を試せます

とても簡単ですね

以上、ダウンロード画像の作成方法の紹介でした


2014年10月23日木曜日

簡単だと思っていたのに、結構ハマったのでメモとして残しておきます

参考にしたのは、次の2つの記事です




重要なのは2点だけ
  1. GridViewの行になっているレイアウトのbackgroundに?android:attr/activatedBackgroundIndicatorを設定する
  2. activatedBackgroundIndicatorをThemeでオリジナルのものに変更する
ただし、APIレベル11以降のお話です

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="?android:attr/activatedBackgroundIndicator"
>
<TextView
 android:layout_width="fill_parent"
 android:layout_height="40dip"
 android:gravity="center"/>
</LinearLayout>


Theme(style.xml)

<style name="AppTheme" parent="AppBaseTheme">
      <item name="android:activatedBackgroundIndicator">@drawable/grid_background</item>
</style>


grid_background.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_activated="true" android:drawable="@color/green" />
    <item android:state_selected="true" android:drawable="@color/green" />
    <item android:state_pressed="true" android:drawable="@color/green" />
    <item android:state_checked="true" android:drawable="@color/green" />
    <item android:drawable="@color/blue" />
</selector>


これはメモなので、詳細は上にあげたサイトを見るのが良いと思います


2014年6月24日火曜日

AndroidでiBeacon(2)

前回「AndroidでiBeacon(1)」の続きで、今回は検出したBeaconから情報を取得します
取得するのは

  • UUID
  • major
  • minor
  • 電波強度

の4つです

端末を検出したらコールバックされるBluetoothAdapter.LeScanCallbackのonLeScanを変更していきます

onLeScanには3つの引数があり、UUIDなどの情報は第3引数のbyte配列に入っています

その配列は次のようになっています

データ構造


01ブロック目のバイト数
1
フラグ
2
32ブロック目のバイト数
4AD Type
5
会社ID
0x00CがAPPLE
6
7データタイプ0x02がiBeacon
8iBeaconデータのバイト数
9
UUID
16バイト
~
24
25
major
4バイト
26
27
minor
4バイト
28
29電波強度距離計算する際の基準値として利用

データを取得

onLeScanの中身を変更しています


    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            if (scanRecord.length > 30) {
                //このif文でiBeaconかどうかを判別
                if ((scanRecord[5] == (byte) 0x4c) && (scanRecord[6] == (byte) 0x00)
                        && (scanRecord[7] == (byte) 0x02) && (scanRecord[8] == (byte) 0x15)) {
                    String uuid = getScanData(9, 24, scanRecord);
                    String major = getScanData(25, 26, scanRecord);
                    String minor = getScanData(27, 28, scanRecord);
                    String strength = String.valueOf(scanRecord[29]);
                    Log.d("BeaconSample", "-----------------------------");
                    Log.d("BeaconSample", "uuid::" + uuid);
                    Log.d("BeaconSample", "major::" + major);
                    Log.d("BeaconSample", "minor::" + minor);
                    Log.d("BeaconSample", "strength::" + strength);
                    Log.d("BeaconSample", "rssi::" + rssi);
                }
            }
        }
    };

    public String getScanData(int start, int end, byte[] scanRecord) {
        StringBuilder result = new StringBuilder(end - start);
        for (int i = start; i <= end; i++) {
            result.append(convertHex(scanRecord[i] & 0xff));
        }
        return result.toString();
    }

    public String convertHex(int i) {
        char hexArray[] = {
                Character.forDigit((i >> 4) & 0x0f, 16), Character.forDigit(i & 0x0f, 16)
        };
        return new String(hexArray).toUpperCase();
    }

データの取得は以上です

配列の中にある電波強度は基準値なので変化しません
実際の電波強度は第2引数のrssiになります



次回は、Androidで使えるライブラリを探してライブラリを利用方法などを紹介したいと思います

2014年6月23日月曜日

AndroidでiBeacon(1)

Beaconを貸して頂いたので、これら何回かに分けてAndroidでiBeaconを触ってみる記事を書いてみようと思います

iBeaconについては、いろいろと情報があると思いますので説明は省きます
iBeaconって何?という方は、まずGoogleなどで検索してみてください

必要なもの


BLEに対応したAndroid 4.3以上の端末
Beacon(今回はBeacon USBを利用)

Beaconの設定


最初にBeaconの設定をしておきます
設定する情報は、Proximity UUID(以降、UUIDと略),Major, Minorとありますが、どの情報を使って検出したいBeaconを判別するかによりますので、1台だけならUUIDだけでも良いかもしれませんし、1台でもMajorまで設定しておいても良いかもしれません

今回は、UUID,Major,Minorを全て設定しておきます

※今回利用するBeaconUSBに専用のアプリがまだ無いので、HPに記載されている設定マニュアルにあるとおり「BLE Utility」というアプリを使って設定します。このアプリはiOS用なのでAndroid端末しかない場合は、別途BLがで利用できる設定アプリを探してください



Androidアプリを作る


前提条件


BluetoothはONになっていることとする(ONにしたり、利用可否のチェックは省く)

参照


コードは、Androidの公式情報を基にして書いていきます
http://developer.android.com/guide/topics/connectivity/bluetooth-le.html



Permission


BLUETOOTHを利用するための権限を設定します。

<uses-permission android:name="android.permission.BLUETOOTH"/>

アプリの中でBluetoothのON/OFFなど操作を行う場合にはBLUETOOTH_ADMINの権限も必要となります BLUETOOTHの操作も行いたい場合は、以下の2つを設定してください
※あとで検証したら、BLUETOOTH_ADMINを指定しないと端末が検出できないことが判りました。BLUETOOTH_ADMINは必須のようです

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

BLEに対応した端末だけにインストールを許可したい場合には、以下のuses-featureを設定してください

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

BluetoothAdapterを取得する

BluetoothAdapterはBluetoothManagerから取得します
    private BluetoothAdapter mBluetoothAdapter;
public class MainActivity extends Activity {

    private BluetoothAdapter mBluetoothAdapter;

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

        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
    }

}

BLE端末を検出する

BLEを検出する処理を追加します
検出は、BluetoothAdapterのstartLeScanで実行されます
検出が終了するとstartLeScanの引数で指定したコールバックのメソッドが呼び出されます

BLEの検出は何度も繰り返し行われるため、ハードウェア的に問題となるため1秒たったらスキャンを停止する(stopLeScan)ようになっています
※コールバック用のメソッドは後述
    @Override
    protected void onResume() {
        super.onResume();
        scanLeDevice(true);
    }

    private void scanLeDevice(final boolean enable) {
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                }
            }, SCAN_PERIOD);

            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }



BLEの検出結果を処理する


BLEの検出が終わるとstartLeScanで指定したコールバックのメソッドが呼び出されますので、その中で検出結果を解析します
今回はデバイスの名前とアドレスをログに出力してみます

    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            Log.d("BeaconSample", "name::" + device.getName());
            Log.d("BeaconSample", "address::" + device.getAddress());
            Log.d("BeaconSample", "------------------------------");
        }
    };

スキャンの停止


 アプリが停止しているときは、スキャンを停止するようにしましょう
    @Override
    protected void onPause() {
        super.onPause();
        scanLeDevice(false);
    }


今回はここまで。
次回は、結果からUUIDなどの情報を取得して、本当に情報を取得したい機器の詳細情報を見てみたいと思います


※もう少し詳しくコードを知りたい方は、Android SDKの中にあるsamplesに参考となるコードがありますので、そちらを参照ください
samples/android-18/legacy/BluetoothLeGatt/src/com/example/bluetooth/le

2014年5月28日水曜日

AndroidのFused Locationでの精度調査

仕事の関係で調査が必要でしたので、AndroidのFused LocationにてGPS、Wi-Fi、携帯ネットワークを使った場合に精度がどのようになるのか検証してみました

以下の条件での検証です
  • Priorityは「LocationRequest.PRIORITY_HIGH_ACCURACY」
  • permissionは「android.permission.ACCESS_FINE_LOCATION」
  • 仕事場近くの道端にて同じ場所に留まった状態で計測
  • Wi-Fiにはe-mobileのPocket Wi-Fi(GL06P)を使用
  • 携帯回線はDocomo
  • 計測は、それぞれの条件で7回(画像の2枚めの前半は重複した情報です)

GPS + Wi-Fi + 携帯ネットワーク


精度は25m~63mくらいでした

複数のプロバイダーを利用しているのでgetProviderの値が[fused]になるのかと思っていましたが、あとの携帯ネットワークだけの時も同じ値となります。そのためFused Locationの場合getProviderは常に[fused]を返すようですね




GPS + 携帯ネットワーク


次はGPS + 携帯ネットワークです
33m~50mと、最初の Wi-Fiも利用したときとあまり変わりませんね
Wi-Fiは精度に影響がなく、携帯ネットワークがあれば、そこそこ精度が出るのかもしれません




 Wi-Fi + 携帯ネットワーク

次に検証したのがWi-Fi + 携帯ネットワークです

精度は60m以上の精度で上の2つと比較すると精度は良くないですが、利用用途によっては十分に利用可能と思います





携帯ネットワークのみ


最後は携帯ネットワークのみの結果です
このデータだけ計測しながら移動しています
最初の3件目のデータまでは、その場所に留まっていたのですが、4件目は仕事場に向かって歩いています
そして、5件目のデータで仕事場のマンションの通路に入った所で精度が一気に悪くなりました
3km近い誤差が出ています
その後、仕事場の部屋に戻ると精度が33mになっているので、場所によって大きく誤差がでるようですね
誤差が大きくでた場所はGPSも反応しない場所なので、この場所で精度を出すのは現状では難しいと思われます




まとめ


以上の結果からは、Fused Locationを使った計測は精度が高いように思われます
今回の検証ではデータが少なすぎて答えは出せませんが、精度を判定して大きな誤差が出そうなデータは捨てていけば、それなりに高い精度で位置測定できそうです
しかし、状況によっては数kmの誤差もありえます

精度は良くても20mくらい。状況によっては精度がもう少し良くなるかもしれませんがピンポイントでの位置特定に利用することは出来ませんね
ピンポイントでの位置特定にはBeaconや音波などなど他の技術と組み合わせて精度を高めることで実現できるかもしれませんが、それはまた別の機会に調査してみたいと思います

以上、せっかく調査してみたのでブログに記事としてまとめてみました

2014年5月12日月曜日

Remote TestKit Webを試してみた

以前(Remote TestKitで実機の動作テスト)で紹介したRemote TestKitがブラウザだけで利用できるようになったので実際に試してみました

まず、ログインすると端末の選択画面がでてきます
専用ソフトの時とだいたいおんなじ感じですね




さっそく、無料でレンタルできる端末の中から「Samsung Galaxy S4」をレンタルしてみます
一覧の右端にある[レンタル]というボタンを押すと、確認ダイアログが表示されます
ダイアログにある[レンタル]を押すとすぐにブラウザ上に端末の動作画面がでてきます




リモート端末にアプリをインストールするには、画面右のメニューから[ファイルを選択]でapkファイルを選択して、[アプリをインストール]のボタンを実行するだけです

今回はApiDemos.apkをインストールして動かしてみました

1.9MBほどあるApiDemos.apkのインストールが完了して動作するまで20秒くらいで、思っていた以上に素早くインストールできました

ドラッグや選択などの動作はリモートなのでそこそこの遅延はあります
試しにApiDemoにあるOpenGL ESのサンプルを動かしてみましたが、少し遅いかな?と感じますが問題なく動作しました




ブラウザを使ってWebサイトを閲覧することもできるのでスマートフォン用のHTML検証にも使えそうです


試しに自分のところのホームページを表示させてみました


これまで専用ソフトをインストールして利用する必要がありましたが、これからはブラウザだけで手軽に複数端末でのテストが行えるのは非常に助かります

スマートフォンのアプリやサイトを開発をされている方はぜひチェックしてみてください!

ちなみに、iPhoneもレンタル可能です


■Remote TestKit Web Browser Version
https://webapp.appkitbox.com/

■Remote TestKit
http://appkitbox.com/testkit/

2014年4月21日月曜日

ThemeをDialogにしてDialogっぽくしたActivityで枠外をタップした際に画面を閉じるには次のような処理を追加すれば良い

@Override  
public boolean dispatchTouchEvent(MotionEvent event) {  
    Rect dialogRect = new Rect();  
    getWindow().getDecorView().getHitRect(dialogRect);  
  
    if (dialogRect.contains((int) event.getX(), (int) event.getY()) == false) {  
        finish();  
    }  
    return super.dispatchTouchEvent(event);  
}  

2014年1月20日月曜日

今日、打ちあわせの際にMS Officeのファイルを見る必要があったんだけど、Nexu7に入れてあったQuickOfficeでは遅くて表示ができないということがありました


そんな時に今回紹介するAndrOpen Officeを教えてもらったので、紹介しようと思います

AndrOpen OfficeはAndroidで利用できるOpen Officeで、パソコンで使うOpenOfficeと同じような表示になっています
Open Officeを使ったことが無い方はOffice 2003みたいな見た目と思ってください
(下に画像を載せています)

パソコンと同じような画面なので、すごくメニューとか操作するボタンが小さいです
最初は画面をタッチすることで操作しようとしていて「使い難いな」と思っていたのですが、操作メニューを出すと非常に使いやすくなりました



操作メニューは画面右下にあるディスプレイのマークを押す表示されます




今回は見るだけの利用だったので、編集とかの操作性についてはわかりませんが、表示だけならかなり良さそうです

※右クリックで表示されるメニューは画面を長押しする表示されます

利用できるのは
・文書ドキュメント
・表計算ドキュメント
・プレゼンテーション
・図形描画
・データベース
・数式
となっています

メニューバーとかのサイズが小さいのですが、これは変更することができないようです(たぶん)


設定としては出来るのは以下の3つだけです
・倍率(Default:100%)
・カスタムフォント(Default:設定なし)
・フレームレート(Default:5fps)

表示がカクカクする場合はフレームレートを上げると良いと思います

万能で安定している。と、いう訳ではないですがMS Officeを表示しないとマズイ場面になった時にでも思い出してみてください




Cover art


AndrOpen Office(andropenoffice.com)

無料

https://play.google.com/store/apps/developer?id=andropenoffice.com&hl=ja




2013年11月21日木曜日

スライドするメニューを作る

Googleのアプリでよくある画面の横端をスワイプもしくはメニューボタンを押すことで画面端から出てくるメニューをアプリに組み込んでみました

Goggleのサービスと同じようなタイプのメニューであればSupport Libraryにある「Navigation Drawer」を組み込む事で簡単に実装できます

■Android Developers Creating Navigation Drawer
http://developer.android.com/training/implementing-navigation/nav-drawer.html


Navigation Drawerを使うと、画面左端(右端にも設定できる)からスワイプすればメニューがニュッと出てきて、コンテンツの上に表示されます

これでも良いのですがNavigation Drawerはカスタマイズ可能なオプションが少なく、コードの改変なしには細かな要望に応えるのが難しいです

顧客が「Facebookのように、コンテンツの方がスライドしてメニューが下から出てくるようなメニューにしたい」といった場合には対処ができません


Facebookのようなメニュー表示


そこで利用したいのが「SlidingMenu」です
SlidingMenuはGithubにてソースコードが公開されているます

■SlidingMenu
https://github.com/jfeinstein10/SlidingMenu

使い方も非常に簡単です
使い方については上記に記載したサイトの方に記載がありますの割愛します

どんな事ができるの?
と、動きが気になる方はデモアプリがGoogle Playで公開されているので、そちらをインストールしてご覧ください

○SlidingMenu デモ
https://play.google.com/store/apps/details?id=com.slidingmenu.example


カスタマイズも色々できて、メニューを開いた時にコンテンツ部分をどの程度残して表示するかや影のつけ方など指定できます
詳細については上記に紹介したサイトをご覧いただくか、Githubよりソースコードを取得するとデモアプリのコードも入っているので、それをみても分かると思います


こういうライブラリを公開してくれている人がいるのは開発者としては非常にありがたいですよね
いつもライブラリを利用させてもらってるばかりなので、何か自分でも作って貢献しなければ!




2013年9月26日木曜日

Remote TestKitで実機の動作テスト

世の中にいったい何種類の端末があるの?ほんと困るよー
という状況のAndroidアプリ開発の現場ですが、便利なサービスも増えてきて助かりますね


今回は「Remote TestKit」というサービスを使って実機検証をしてみましたので、その使用感などを書いてみたいと思います

Remote TestKitとは?


サイトの文書をそのまま引用すると、次のように記載されています

Remote TestKitはスマートフォンの「リモート・レンタル・サービス」です。
コレだけ読むと、「端末を郵送で送ってくれて、それを使うのかな?」と思うのですが、続きがあります

増加する様々なスマートフォン端末に、インターネットを経由して「リモートアクセス」。
一般的な実機レンタルとは一線を画す、利便性の高い検証環境を実現します。

専用ソフトからインターネット経由で端末をリモートアクセスできるサービスなんですね
他にも同じようなサービスがあった気がしますが、他は使った事がないので比較する事はできませんが便利そうです!

Androidだけじゃなくて、iOS端末もあります



何ができる?

アプリをインストールして動作させることができます
その為のサービスなので、当然ですね。。。

動作中のログを見ることができます。しかしステップ実行はできません(たぶん)

操作中の画面を録画したりスクリーンショットを取ることができるので、ドキュメント作成の時にも使えそうですね

詳しくはサイトの機能一覧を見て貰うと良いと思います



費用は?


利用はチケット制になっていて、端末を30分(3チケット)から利用できます
6チケット(1時間分)で945円なので、どうしても特定の端末でテストしたいときには非常に助かります

その他にも10時間分のチケットで9,450円のPro10や50時間分のPro50などのプランもあります
費用はPayPalや請求書での支払いなどに対応しています
PayPalでさっと支払してスグに使えるのが良いです!!

詳しくはサイトのご利用料金をみてください



どんな端末が利用できるの?


2013年9月26日に確認したところ・・・たくさんあります。。。
サイトで確認してもらったほうが早いですね



どうやって利用するの?


まずは、専用ソフトをダウンロードする必要があります
動作環境は次の通りのようです

・windows XP SP2以降、Vista、7、8(32bit/64bit)
・MacOS Ⅹ(10.7、10.8)
・Port 443に直接つながることが可能なインターネット環境

まず、ソフトをインストールしてアカウントを作成します
アカウントの作成にはメールアドレスが必要です

アカウントを作ると、登録したメールアドレスに確認コードが送られてきます
その確認コードを入力しないと利用はできません


起動すると、次のように現在利用できる空き端末の一覧が表示されます
この中から、利用したい端末を選択します
無料のお試し端末があるので、まずはお試しの端末を使ってみるといいです
ただし、無料の端末を他のユーザーが利用している場合は一覧に出てきませんのでしばらく待つ必要があります


端末を選択して、[レンタル]を選択すると端末の画面が表示されます
あとは、いろいろ触ってみてください

カメラとかGPSとかは利用できるの?

利用制限があります
GPSはセキュリティの問題で利用できないようです
カメラは撮影はできますが、カバーがされているので、何も写りません
実際に試してみたら、真黒ではなくうっすら光が写ってるなーという画像が撮影できました

利用制限については、いろいろ変更もあるかもしれないので常に最新情報を!
と、いうわけでサイトを参照してください
http://appkitbox.com/support/faq#02-02

その他の情報はFAQを見ると良いと思います
http://appkitbox.com/support/faq


使ってみた感想

 いままで、顧客から●●の端末で表示が・・・などの連絡を頂いても対応が出来なかったのですが、このサービスで利用可能な端末であれば動作確認できるので重宝しそうです
(検証できる機能に限るけど)

ちょっとだけ表示確認したいのに、30分単位でしかレンタルできないのが少し不満ですね
10分(1チケット)単位で利用できると、もっと便利に使えそうです
ただ、利用後にファクトリーリセットをしてると思われるので、10分毎だと効率が悪いんでしょうね


実機検証に困っている開発者の方は、一度利用してみることをおすすめします


2013年6月30日日曜日

課金処理も終りアプリを公開
課金がちゃんと動くかな?と見てみると下の画像の表示なっていました




「これはテスト用の注文です。課金は発生しません。」


え?と、思い調べてみると
アクセスした端末のアカウントがテスト用のアカウントとして登録してある場合にこのような表示になるようです

テスト用アカウントだということが分かりやすくて良いですが、ちょっとビックリしますね

2013年6月28日金曜日

In-App Billing Version 3を使ってみました

同じように困っている人がいるかもしれないので、メモの意味もかねてブログに書いておきます

テストで行った課金処理がクリアできない


アプリ内課金でテスト用に用意されている「android.test.purchased」というアイテムで購入処理の動作を確認する訳ですが、一度購入すると2回目からは既に購入済みとなってテストが出来ない
そこで購入情報のクリア方法をググってみるとGoogle Playのキャッシュを削除するといいという情報があった

[設定]→[アプリ]からGoogle Playを探して「キャッシュを消去」をしました

しかし、購入情報がクリアされません

ならば!と「データを消去」の方を実行したところ購入情報がクリアされました

検証端末:Android 4.2.2 のGalaxy Nexus

「キャッシュを消去」で上手くいかない人は「データを消去」を試してみてください


課金処理後のonActivityResultが呼び出されない


In-App Billing Version 3ではstartIntentSenderForResult (IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) を使って購入処理が実行されて、購入処理後に結果がonActivityResult (int requestCode, int resultCode, Intent data)に返ってきます
アプリ側ではonActivityResult (int requestCode, int resultCode, Intent data)で返却を待って購入後の処理(たとえば購入ボタンを非表示にするなど)を行えば良い訳です

しかし、あるページでは上手く動作するのにあるページでは上手く動かないという現象が発生しました

yanzmさんのブログ「Y.A.M の 雑記帳」にある「In-app billing V3 は singleInstance な Activity では使えない」
をみて、ひょっとしてsingleInstanceにしてたっけ?
と見てみましたが違いました

もっと単純でした

課金処理はスーパークラスに記載して、サブクラスから購入処理を実行したのですが、このサブクラスにonActivityResult (int requestCode, int resultCode, Intent data)がありオーバーライドしていた事が原因でした
ですので
super.onActivityResult (int requestCode, int resultCode, Intent data)
を追加したら上手く動きました

単純なミスですが見つけにくかった・・・


ほかにもあったような気がしますが思い出したら追記することにします

しかし、In-App BillingがVersion 3になって簡単になりましたね
簡単といってもお金が関わる所なので慎重なテストが必要となるで作業としては大変ですね

2013年6月26日水曜日

AndroidのProguardで次のようなエラーがでて数時間格闘していた


No server options fields detected.  To suppress this message either add a field with the @Parameter annotation, or override the load() method

このエラーの後にAdMobのメディエーションでカスタムイベントの呼び出しの際にClass.forNameで呼び出すクラスのnameがnullで広告が表示されないという問題が出ていた


これを解決するために以下を追加した
-keepattributes *Annotation*
これをつけることによってアノテーションが削除されなくなる

アノテーションが削除されて正しい動作をしていなかったようですね

上記の設定でメディエーションは動作するようになったのですが、次はGoogleDrivが動作しません
どうやらSignatureも必要なようですね
併せてSignature,InnerClassも付けて次のようにしておきました
-keepattributes *Annotation*,Exception,Signature,InnerClass


■参考にさせて頂いたサイト

NO_NAME 
Proguardでコードの圧縮・最適化・難読化を行う

とあるプログラマのしらべごと
アプリにProguardを適用する

2013年1月21日月曜日

パチ帳スロ帳のお手伝い

Androidアプリ「パチ帳スロ帳」の開発のお手伝いをさせて頂きました


(画像はGoogle Playより)

このアプリは、パチンコやパチスロの収支を管理する為のアプリでホール毎や機種ごとに収支を管理して、「どのお店」「どの機種」で勝率が高いかを確認することができます

パチンコ、パチスロをされる方は、ぜひ一度利用してみてください


【パチ帳スロ帳】
アプリ名:パチ帳スロ帳
デベロッパー:KINY PRODUCTS
料金:無料




2012年11月30日金曜日

Amazonのアプリストア

Amazonのアプリストアが日本でも開始されましたね


で、さっそく利用しようとしたのですが、利用には若干の不安がありますね

Google Playのストアからダウンロードするのではない


そのためには「提供元不明のアプリのインストールを許可する」にチェックを入れて貰う必要があります
Androidではセキュリティの問題でGoogle Playストア以外からのアプリインストールに制限がかかっていますので、提供元不明のアプリ・・・にチェックが必要となります

何に使うか分からないパーミッション


Amazonのストアアプリは次のパーミッションを利用するようです
  • プライバシー
    • 端末のステータスとIDの読み取り
    • USBストレージのコンテンツの変更または削除
    • アカウントの作成とパスワードの設定
    • アカウントの追加と削除
    • この端末上のアカウントの検索
    • この端末上のアカウントの使用


  • 端末アクセス
    • ネットワークのフルアクセス
    • ネットワーク接続の表示
    • Wi-FI接続の表示
    • 実行中のアプリの取得
    • 端末のスリープを無効にする
    • 保護されたストレージへのテストアクセス

気になるものだけ以下に取り上げています


●端末のステータスとIDの読み取り


アプリの管理に利用するものと思われますが、端末のID何に利用するのか明示されていないので、少し不安になりますね
仮にアプリの管理に端末のIDを利用するのであれば、端末を変えたらインストールしたアプリは利用できなくなるのでしょうか?
それともAmazonのアカウントで管理するのかな?
このあたり、実際にアプリを使ってみるまで分からないという所も不安の要素ですね

※実際にインストールすると、Amazonのアカウントでログインしますので、アプリの管理はAmazonアカウントで行なって、統計データとして端末のステータスやIDを利用すると思います。想像ですが・・・


●保護されたストレージへのテストアクセス


ちょっと見慣れない権限なのですね
android.permission.READ_EXTERNAL_STORAGEが指定されているようです
Android4.1から追加されたものなので、これまでお目にかかる事がありませんでしたが、今後はSDカードにアクセスするアプリでは見かける事が増えると思います
説明をみると「今後追加する端末で使用できるUSBストレージの権限のテストをアプリに許可します。」とありますので、危険性はないようです

気になったのは以上の2つだけです

権限以外には、Amazonがどこまで情報を収集するのかは少し気になりますが、情報を収集したとしても、ユーザーがどんなアプリをどのくらい利用しているかといった情報くらいだと思います
実際にそんな情報を収集しているかどうかは分かりませんが、気になるようならインストールしないようにしましょう

とりあえず、私はAmazonのアプリストアの状況も知りたいので利用してみようと思います
利用した感想など何か気になる事があれば、また記事にしたいと思います


[Amazonアプリストア]