Androidのアプリ開発関連のブログ

またブログエディターの更新

ブログエディターの更新はとりあえず終わらせて新アプリの開発に移ろうと思ってたが、
もう1回アップデートした。

ブログエディターは入力アプリだからソフトキーボードが出現することになるんで、画面が横向きだとキーボード出現時にかなり狭い。

横向きだと、
  • タイトル入力欄
  • 本文入力欄
  • 広告
となるが、
アプリタイトルが表示される箇所を記事タイトルの表示にしたい気はしてたんだが、アプリタイトルタッチしてみたらボタン反応があることに気づいた。
アプリタイトル部分がボタンとして利用できるなら、ここ記事タイトル入力用に使うべきだ!

というわけで、そうするように変更した。


android.app.ActivityのgetActionBar()でActionBarを取得できて、
android.app.ActionBarのsetHomeButtonEnabled(true)でアプリタイトル部分がボタンになる。
ボタンになることに気づいたAndroid4.1は最初からボタンになってるんだが、Androidのバージョンによっては初期時はボタンになって無いようで、
getActionBar().setHomeButtonEnabled(true);
でボタンにする必要がある。


public boolean onMenuItemSelected(int featureId,MenuItem item){
   if(item.getItemId()==android.R.id.home){
     ここに処理
   }
   return false;
}
アプリタイトル部分がボタンもメニューとして処理できるようで、onMenuItemSelectedで処理できる。
タッチされた項目がアプリタイトル部分の場合は、item.getItemId()が「android.R.id.home」になる。
return false;だと続いて標準の処理が行われて、return true;だとそこで止まると思う。

if文内はreturn true;の方が良かった気がするが、今コード見たらif文内でreturnしてなかった・・・
まあ、問題起きてないし良いか。


今回はアプリタイトル部分を記事タイトルの表示に使いボタンから処理だが、
記事タイトルが無題の場合にわかりやすいように色を変えたかったんだが、
android.app.ActivityにsetTitleColor(int textColor)ってメソッドがあるんだが、これAPIレベル21で廃止されたメソッドで、そもそもActionBarのタイトル色には影響ないみたい。
ActionBarのタイトル色を変更するのはStyleで指定するしかないようで、Javaで動的に変更するにはコンストラクタ使う方法しか無いようで無理がある感じ・・・
Activity.setTitleColorを廃止するなら、代わりにActionBarの文字色変更する機能用意して欲しいもんだな・・・

色変更ができないので実装見送りも考えたが、
次に考えてるアプリもテキストファイル編集系なんでキーボードが出てくる。
テキストファイル編集アプリはファイル名入力欄とか設けないものだと思うし、アプリタイトル部分使うのが良いと思うんで、
単色だがこの件の変更適用した。


ActionBar.setHomeButtonEnabledがAPIレベル14(Android 4.0)からなんで、元はActionBar使うためにAPIレベル11(Android 3.0)からだったが、
古い端末には対応しなくなった。

次はどんなアプリを作ろうか・・・

公開から連日バージョンアップしていたブログエディターだが、
現在ソフトキーボードで変換候補が出た際にキャレット位置によっては一時的に隠れる問題を把握しているが、解決困難なんで放置。
ブログエディターに必要な機能は十分実装されていると思うんで、更なる機能追加はユーザーが獲得できてからでいいかなと考えてる。
アプリ内購入で広告非表示オプションを導入したいとも思ってるが、それもユーザー獲得が先だね。
というわけで、ブログエディターのアップは落ち着いた感じ。


で、次何作ろうか・・・
というわけだが、

ブログエディターみたいなツール系アプリなら利用者がいれば広告効果が期待できると思うが、
設定系アプリみたいに滅多に使わないアプリじゃ広告つけてもほぼ無駄だね。
有料アプリやるより、無料アプリでユーザー獲得するのが先だと思うんで、
設定系みたいな広告つけても無駄ぽいのや、ウィジェットみたいに広告つけたら邪魔すぎるアプリは当面除外かな。
無広告の定番アプリがあって機能的にも勝てそうにないのも除外。
メモ帳みたいに作っても埋もれると思われるのも除外。

って感じかな。
難しいね・・・


Google Playで配信されてるアプリ眺めたりして考えたが、
FTP接続でリモートファイルを編集するアプリを作ろうかなーという方向に傾いてる。
WEB制作やってるからWEB系ツールしか思いつかないのかな。

単純にFTPクライアントだとアプリ多数あるから埋もれちゃいそうなんだが、
同期用アプリじゃなくて編集に特化した感じで。

そうすると、FTPクライアントとしての機能を作らなきゃだから、まず単純なFTPクライアントを作成。
HTMLファイルの編集にHTMLエディタを実装しなきゃだから、まずローカル用HTMLエディタを作成。
とか個別にアプリを作成することも考えたが、一つのアプリに機能追加していく感じの方が良いのかな。

まあ、そっち方向で考えてる。

キーボード出現時にキャレットが隠れる

公開から連日アップデートしてるブログエディターだが、
今回は、ソフトウェアキーボード出現時に、キャレットが下の方にあるとキーボードで隠れちゃう。
改善したい・・・

というわけなんだが、
android.view.ViewにonSizeChangedがあって、Viewのリサイズ時に呼び出される。
が、イベントリスナの登録はできないんで、カスタムViewを作ってイベントリスナを登録できるようにしてみた。
今回問題のViewはWebViewなんで、カスタムWebView。

CustomWebView.java
import android.webkit.WebView;
import android.content.Context;
import android.util.AttributeSet;

public class CustomWebView extends WebView{
    public CustomWebView(Context context,AttributeSet attrs){
        super(context,attrs);
    }
    public interface customOnSizeChangedListener{
        public void customOnSizeChanged(int w,int h,int oldw,int oldh);
    }
    private customOnSizeChangedListener listener;
    public void customSetOnSizeChangedListener(customOnSizeChangedListener listener){
        this.listener=listener;
    }
    protected void onSizeChanged(int w,int h,int oldw,int oldh){
        super.onSizeChanged(w,h,oldw,oldh);
        listener.customOnSizeChanged(w,h,oldw,oldh);
    }
}

MainActivity.java
((CustomWebView)view).customSetOnSizeChangedListener(new CustomWebView.customOnSizeChangedListener(){
            public void customOnSizeChanged(int w,int h,int oldw,int oldh){
                処理
           }
});

てな感じで、Viewのリサイズ時にMainActivity側で処理することができた。
layoutの.xmlファイルでカスタムViewを配置する場合は、(Context context,AttributeSet attrs)のコンストラクタが使われるみたいなんでOverride。
で、.xmlファイルには、<パッケージ名.クラス名>でカスタムViewが設置できる。
javaファイルで設置するなら、ほとんどの場合(Context context)で設置するから、そっちのコンストラクタをOverrideだね。

MainActivity側で処理できるように、イベントリスナのinterfaceを定義して、リスナ登録用のメソッドを用意。
onSizeChangedに追加でリスナを実行するようにする感じだね。


で、今回はWebViewのcontenteditable要素への入力でソフトキーボードが出現する時に問題が生じるんだが、
元々「改行→<br>」変換処理で要素が拡大してViewからはみ出した場合にスクロールする処理を入れてあるんだが、
その処理はrangeに一時的に<span>を入れて、<span>の座標がはみ出した場合にスクロールするようにしてある。

同じようにやろうとしたんだが、改行時処理と違って文字入力時処理だと、処理によってキーボードが消えちゃうって問題が発生した。
文字入力中にjavascriptでrangeに変更加えるのは問題生じそうな気もするし、javascript側で処理するのはやめたほうが良さそう・・・


Java側での処理を考えて、onSizeChangeddから元のサイズと新しいサイズが取得できるから、差をスクロールさせればできるとも思ったんだが、
View中のキャレット位置が上の方にあるって場合も考えられるし、その場合にスクロールさせちゃうと逆に消えちゃうね・・・

Java側でキャレット座標の取得ができないか調べたが、どうもできなそう。
android.view.ViewにあるgetBaseline()が怪しいかとも思ったが、WebViewでは常に-1ぽい・・・

AndroidManifest.xmlで「android:windowSoftInputMode="adjustResize"」を設定するとソフトウェアキーボード出現時にアクティビティが伸縮するらしいんだが、
うちの場合layoutで対応できてるのか、そもそもこれ設定しなくても伸縮してる。
問題はActivityのサイズじゃなくてView内のスクロール量だから、これは関係無さそう。


お手上げぽいんで、この問題は放置することにした。


EditTextでキーボード出現した場合どうなるのか試したが、EditTextの場合、何もせずに良い動きしてくれる。
WebViewの方の挙動を再度よく確認してみたが、キーボード出現時自体は自動で位置調整してくれるんだが、
1文字入力して変換候補がでた時に位置調整してくれない。EditTextなら問題ない。
WebViewでも、1文字入力で変換候補が出てキャレットが隠れるが、そのまま2文字目を入力すると再度位置調整してくれて画面内にキャレットが入る。
変換候補出現時の処理にWebViewはバグがあるっぽいな。

キャレットの座標が取得できないと位置調整できないと思うが、WebViewでもキーボード出現時と2文字目入力時は位置調整してくれるってことは、どこかで座標取得できそうな気はするが・・・

Google Playでのアプリ配信

Google Playでアプリを配信するには、Google Playにデベロッパー登録(要$25)する。

  • デベロッパー登録(要$25)
  • デフォルト言語を設定してアプリ名や紹介文などを記入。
  • スクリーンショットが最低2枚を登録
  • Google Play用の512x512アイコンを登録
  • 宣伝用画像1024x500を登録
  • その他指示に従って項目を埋める
って感じになる。

正式版APKの作成

正式版APKの作成をする場合は署名が必要。


keytool -genkey -v -keystore 出力ファイル名 -alias キーの名前 -validity 期限までの日数 -keyalg RSA
で署名のファイルが作成できる。
コマンドを実行すると質問が出てくるので、姓名や所在地、パスワードを入力する。
期限までの日数は25年以上を推薦とのことで、10000にした。

ファイルが出力されるので、
ant.propertiesに、
key.store=ファイル名(keytoolコマンドの-keystore
key.alias=キーの名前(keytoolコマンドの-alias
と記載する。

上記手順の後、
ant release
で正式なapkが作成できる。