kojiko-android’s blog

開発中にハマった時の解決策や、忘れがちなことを残しておきます。

【日記】電卓アプリ製作中・・・【進捗状況】

私も電卓アプリでポルシェを買いたい!と思って電卓アプリを作っています笑

といってもなかなかダウンロードは伸びず、ポルシェを買えるようになるには100年はかかりそうですね。

そのまえにキーストアの有効期限の25年を過ぎそう・・・


でも電卓って、基本的な機能を抑えてプラスアルファの機能を付けたり、デザインで勝負したり、

付加価値を生み出せれば、それにヒットする方には使って頂けそう。


そういう意味では夢があるテーマではあると思うのである。


ではどうするか。

まずはターゲティング?

万人受けにするか、ニッチな感じにするか。

既に10万ダウンロード以上されているアプリを見ても、

シンプルなもの、実物のようにリアルなもの、単位変換なども計算できる多機能なもの、

関数電卓・・・これは、層が狭そうだし、私には到底作れない。

あとは、キャラものだったり、テーマが豊富なものだったり。

ただ、どれも自分にはしっくり来ないんですよね。


なんかで読んだ、ターゲティングはアバウトにしないで、

現実世界の一人にまで絞る(もしくは、実在するかのごとく詳細まで設定する)といいらしい。

じゃあ、ターゲットを自分にして、自分が最も使いたい電卓を作ろうと思う。

これってありなのかな?

自分だと客観的になれないとか、

なんか作ったけど、既製品とは違う手作り感がでてしまう。

ボタンの余白とか、色とか、既製品は全てうまいことまとまっている感があるが、

自作のだとどこか不安定な感じがするのですが。


いや、それより大元の部分をしっかりするべきなのか。

電卓という、それでできることはほぼ一緒という、

なにか感動を与えるものではないということがネックになっている気がします。

誰もが使ったことのある、ごく身近なツールの一つなので、

使い慣れた電卓(電卓アプリ)から乗り換えてくれるような、

もしくはダウンロード済みのアプリに並べてインストールしてもいいよってくらいの

クオリティと、狭い意味でのポテンシャルがないと厳しいのかな。


ターゲティング自分だと完壁主義に陥りなかなか完成しなさそうなので、

ターゲットは身近な家族にします笑

プレゼントするつもりで作ってみます。



今日はメモリー機能を付けました。

頑張ります。

Viewを指に追従させる方法

ボタン等のViewをタッチし、そのまま指をスライドさせたときに、
指にくっついて来るようにViewを動かす方法です。

サンプルでは横移動のみに制限し、指を離すとゴムのように元の位置に戻る動きをします。
iOSの”スライドでロック解除”のイメージ)

Viewのタッチリスナーに以下のように記述します。

movableButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        v.setTag(event.getX());
                        break;
                    case MotionEvent.ACTION_MOVE:
                        float f = event.getRawX();
                        v.setTranslationX(f - (float)v.getTag());
                        break;
                    case MotionEvent.ACTION_UP:
                        ObjectAnimator.ofFloat(v, "translationX", v.getTranslationX(), 0f)
                                .setDuration(100l)
                                .start();

                }
                
                return false;
            }

        });


getRawX()では、スマホの画面に対する絶対位置を取得できます。
getX()は、Viewに対する相対的な位置を取得するので、
指を動かしたときにViewを移動させると、その都度、相対位置が変わってしまいます。


アクションダウンで、移動開始時のX値を取得しておきます。
フィールドを使わずシンプルにするため、Viewのタグを利用しました。
v.setTag(event.getX());


アクションムーブで移動量を求め、
その値の分だけViewを移動します。

float f = event.getRawX();
v.setTranslationX(f - (float)v.getTag());


指を離したときに、元の位置に戻るアニメーションです。
移動後の現在位置から元々設置されていた位置まで戻る動きをします。

Ollieを導入する

簡単にデータベースを扱うことができるOllieの導入方法です。
build.gradle(app)に、以下の青色文字の部分を追加します。


apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'


dependencies {

  ・・・

compile 'com.michaelpardo:ollie:0.3.1'
provided 'com.michaelpardo:ollie-compiler:0.3.1'

}


build.gradle(プロジェクト)に、以下の青色文字の部分を追加します。



buildscript {
repositories {
・・・
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

}
}

以上備忘録。

Androidアプリ終了に広告を出すとポリシー違反になる!?

ポリシー違反の回避と、長く使ってもらうアプリにするための考察

 アプリ終了時にインタースティシャルなどの広告を表示するのは、
Googleデベロッパーポリシー違反にあたります。
Androidに慣れ親しんでいるユーザーは、端末のバックボタンを押したら、
一つ前に見ていた画面に戻るということを、経験則から予測しています。
新しい端末に買い換えたときでも、Androidであればすぐに不自由なく操作ができるわけですが、
この一貫性を損なうような振る舞いをしてはいけません。

 ユーザーの期待する動作を妨げてはいけません。
時間がない時、すぐに終電を調べたいのに、アプリを切り替える時に突然広告が出てきたらとても困ります。
テレビCMのように、ある程度予測できるタイミングにする必要があります。
「このアプリの機能を無料で提供するので、ちょっとだけ広告を見て頂けませんか?」というくらいの気持ちで、
極力ストレスにならないようなタイミングで表示するべき。
よく言われていますが、緊張が解けたタイミングが、ベストだと思います。

ユーザーの事を考えてみる

 普段、無料のアプリを利用するユーザーは、
開発者たちがどのようにして収益を得ているかを知っているとは限りません。

 アプリとユーザーで、WIN-WINの関係が保てることが大切です。
広告に対して不快な思いが強くなってしまえば、WINーLOSEとなり、
アプリがアンインストールされてしまうと、
結局LOSEーLOSEになってしまいます。
当たり前のようですが、長く使ってもらうにはユーザーの気持ちになって考えることが大切であると思います。

対策案

1.ネイティブ広告に変える

 アプリのデザインに溶け込むデザインの広告を使うと、視覚的なわずらわしさを解消できます。
広告というのは意識を向けさせるために、色鮮やかだったり、点滅したりしているが、
色数を抑えられた落ち着いたものにするだけでも効果的。
アプリにはあまり多くの色を使わないほうが良い。
不快ではないから「そのまま無視で問題ナシ」と思われるのか
収益的にはあまり良くなかった。
それでも、前途のLOSEになることは防げるのではないでしょうか。

2.インストール時に位置情報などのパーミッションを要求する

 インストール時に、ユーザーの質をふるいにかけます。
「電卓アプリなのに、なぜ位置情報?」と懐疑心を抱くユーザーは、
広告に対しても消極的でしょう。
逆にあまり疑わずにインストールする人は、
広告に対しても警戒心が低いかもしれません。
結局広告に興味を持ち、クリックしてもらわないことには収益に繋がらないので、
意地でも広告をクリックしないという人には初めからインストールをご遠慮いただくというのもひとつの方法です。
予算に余裕がある場合は別ですが。
インストールしてくれたユーザーには、
位置情報からより適切な広告を表示することができます。

「位置情報は疑問だったが、どうしてもこのアプリの機能を使いたくて」インストールした方のために、
個人情報保護方針(プライバシーポリシー)を明記します。
なぜ、このアプリは位置情報を取得したのか。

「このアプリには○○、○○などの第三者の広告事業者による広告が表示されることがありますが、
お客様を特定しない範囲での情報(電話番号を含まない端末情報、性別、現在の位置情報など)を
利用することで、より適した広告を表示することができます。」
というように、透明性をアピールすることで、
納得でき、アプリと、広告に対して信頼感も得られるかもしれません。

Googleでは、機密情報を取得するアプリには、アプリ内と、アプリストアの目立つところに、
プライバシーポリシー(へのリンク)を記載するように示唆していますので、
いずれにしても、プライバシーポリシー記載は必要です。
play.google.com

3.ビデオ広告を見てくれたら、バナー広告を非表示にします

3日間などの期限を決めて広告を非表示にする代わりに、高単価のリワード広告を視聴してもらうというもの。
WIN-WINな取引のようであるが、広告に焦点が当たりすぎているので、少々胡散臭さが出てしまうかもしれません。
ユーザーに選択肢を与えるという意味では良いかもしれないが、ユーザーにとってメリットが薄い。
いままでマイナスだったものがゼロになる程度のもので、
私のアプリの場合、実装後数回再生されたものの、しばらくしたらほとんど再生されなくなった。
一度試して期限が終了したら、今後は他の広告くらい我慢できてしまう。
ゲームで劇的な効果を上げるアイテムとの取引なら応じてくれるかもしれないが、
私はゲームは作らないので検証できず。
ツール系アプリなら、便利な機能の開放など、大きなメリットを提示しないと難しそうです。
ツール系は長くつかってもらいたいので、信頼度を下げないように注意したい。

結果

あくまで個人開発者目線ですが、
最も効果が高かったのが、以下の実装方法でした。
具体的に、

キッチンタイマーのアプリで、普段よく計測する時間をリスト表示する画面の、
下部に設置したダブルサイズのバナー広告

ネイティブではなく普通のバナー広告です。
おそらく前途の、ユーザーにうっとおしさを与えないという意味で、
適切な場所なのだと思います。
ダブルサイズでも、「広告が邪魔」といった内容のレビューもありません。

結局のところ、良いアプリをユーザーの気持ちになって、
丁寧に作っていくのことがなにより大切なのかもしれません。

ViewSwitcherの任意のページに飛ぶ

ViewSwitcherは2つのビューを切り替えることができますが、
切り替えるメソッドがshowPrevious()かshowNext()しかないため、
「進む」「戻る」しができず、
ページを指定して切り替えることができません。

そこで、getDisplayedChild()を呼び出すと、現在表示されているページが0か、1かを取得できるので、
その値に応じて処理を分岐することで、任意のページを表示することができます。

最初のページに飛ぶサンプル
private void jumpToPage1(){
    if (yourViewSwitcher.getDisplayedChild() == 1){
        yourViewSwitcher.showPrevious();
    } 
}

アニメーションを付加する際は、求める挙動にあわせて「進む」か「戻る」を設定します。

端末の音量をコードから変更する

端末の音量を設定するには、AudioManagerを介して行います。
各ストリームごとの、音量を設定、現在の音量を取得、最大値を知る等のことができます。
最大値は端末によって違い、7だったり15だったりするので、
独自にシークバーなどを実装するときは、最大値を知っておく必要があります。
ですが、最大値以上(100など)をセットしても、最大値に設定されます。


AudioManagerを取得する

private AudioManager mAudioManager;
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);


各ストリームの最大音量を取得する(以下、アラームのストリームの例)

int maxVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);

現在の音量を取得する

int nowVol = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);

設定を変更する

int value = 3;
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM,value,AudioManager.FLAG_SHOW_UI);

第3引数のフラグ

AudioManager.FLAG_SHOW_UI は、端末上部にシークバーが表示され、ユーザーは操作ができます。
AudioManager.FLAG_PLAY_SOUND は、上記に加えて、現在の音量で「ピッ」と鳴る。
0を指定した場合は、設定変更されるが、なにも表示されません。

NumberPickerの5つ刻みなどに変更する

デフォルトでは1ずつ刻みのNumberPickerを、5つ刻みなどに変更する方法です。

f:id:kentaro198477:20170208233759p:plain

私の場合、どうもうまく行かなくて、以下のような回りくどいやり方にしたら
思ったように実行できました。


ナンバーピッカーを拡張して、カスタムナンバーピッカーを作り、
以下のメソッドを追加しました。

public void setValues(int min ,int max, int step){
        
    setMinValue(min);
    setMaxValue((max / step));

    String string = "";
    for (int i = min; i <= max; i += step) {
        string += i;
        if (i != max) {
            string += ",";
        }
    }

    setDisplayedValues(string.split(","));

}

ちょっと変なやり方です(笑)。
文字列に”,”(カンマ)を使う場合はsplitで分割する目印を変えて下さい。

ナンバーピッカーのインスタンスを作り、setValues()を呼びます。
0~55までの5刻みの場合は、
yourNumberPicker.setValues(0,55,5);
とすると、5刻みの表示になります。

値を取得するときは、表示されている値ではなくポジションとして返ってくるので、
またstep分だけ掛ける必要があります。