石の上にも数年

yaplog! のサービス終了に伴い引っ越しました 🚚

アップデート中のアプリを起動するとどうなるのか?(Android)


Nexus 7 (2013) で確認してみました。

Google Play で「更新」ボタンをタップ後に更新中のアプリを起動すると
しばらくしてからアプリの画面がスッと消えてホーム画面に戻ります。

その後、ホーム画面から更新中アプリのアイコンをタップすると
「このアプリはインストールされていません。」のトーストが表示されました。
更新中はアプリが使えない状態になっています。

アプリの更新が完了すると普通に起動できるようになります。





Google Play にサポートを打ち切ったAPIレベルのアプリが残る


例えば、Android 2.3(minSdkVersion 9)以上の端末に対応したアプリを
versionCode 1としてGoogle Playにアップロードしていたとします。

そして次のアップデートからは古い Android 2.3系端末を切り捨て、
Android 4.0以上の端末のみを対象にすることになったため
minSdkVersion 14、versionCode 2としてGoogle Playにapkをアップロードします。

これでAndroid 4.0以下の端末はアプリをインストールすることができなくなった…
と、思いきや
Android 4.0以下の端末でGoogle Playのアプリのページを開くとボタンに
「お使いの端末はこのバージョンに対応していません。」と表示される訳ではなく
まだ versionCode 1のアプリをインストールすることができます。

つまり
Android 4.0 以上の端末では versionCode 2 のアプリをインストールできる
Android 4.0 以下の端末では versionCode 1 のアプリをインストールできる
という状況になります。

これはiOSApp Storeと同じ仕組みらしいです。

Androidのタブレット端末に携帯電話のメールアドレスを登録しない方がいい気がしてきた


最近ガラケーに届く迷惑メールの数が半端ない。1日に10件程。
高校時代からガラケーを使用していますが迷惑メールが届いたことは1度もありませんでした。

考えられる理由はスマートフォンの普及。

「連絡帳へのアクセス」と「ネットワーク通信」の権限を持つAndroidアプリを Google Play からインストールした時点で、連絡帳のデータを吸い出され外部のサーバーに転送される条件が整ってしまったと言えます(悪意あるアプリの場合)。
なので自分でどんなに対策をしたとしても誰かのスマートフォンから自分の携帯電話のメールアドレスが漏洩してしまう可能性は十分にあります。

せめてもの対策として個人で所有するAndroidタブレット端末には携帯電話のメールアドレスをプロフィール登録しないようにするのがオススメだと思います。
タブレットから自分の携帯電話にメールを送信することは滅多に無いと思うので。

Android の ListView または GridView でセルを複数選択できる機能を作成する


ギャラリーアプリの削除する写真を複数枚選択する機能や
LINE アプリのグループに招待するメンバーを複数人選択する機能の作成を目指します。

Android4.0で複数選択モードを利用する/Getting Started
リストにフラグをセットすれば複数選択モードが簡単にできるらしいですが、
レイアウトをカスタマイズしたい場合や、仕入れたリストのライブラリが
複数選択モードに対応していない場合などがあります。
そのような状況の際に自力でリストの複数選択を実装する方法の一例を書きます。
(もっといいやり方があるかも知れませんが)

①まずリストを作成します(省略)。
Android - ViewHolderを使わないでListViewを高速化する - Qiita
※上記のCustomItemAdapter、Item、ItemLayoutを引用して続きを書いていきます

② customItemAdapter は MVC モデルの View に当たる
Activity または Fragment にメンバ変数として定義しておきます。
そして customItemAdapter をリストに1度だけセットします。

customItemAdapter = new CustomItemAdapter(context, resource, objects);
listView.setAdapter(customItemAdapter);

③ Item クラスにセルが選択状態であるか否かを判断する boolean 要素を追加します。

private boolean isSelected;
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}


※ Item をデータベースに保存する場合には isSelected を保存しないか全部 false にする必要がありそう
※ そうしないと次に複数選択リストを表示した際に前回の選択状態が残ってしまう
※ 選択状態を保持するやり方は色々考えられそう

④ onClickListener などでリストのセルがタップされた場合に
選択された位置から Item を取得します。
Item item = customItemAdapter.getItem(position);
item.setSelected(item.isSelected ? false : true);
// もしリストの選択状態が変化しない場合は .notifyDataSetChanged() 処理を行う
customItemAdapter.notifyDataSetChanged();

⑤ ItemLayout の bindView() に isSelected の状態によって
セルの選択状態と選択されていない状態を切り替える処理を追加する。
チェック画像アイコンを変化させたり、色を変えたり、View の表示非表示を切り替えたりします。
.setVisibility(item.isSelected ? View.VISIBLE : View.GONE);

Instagram や Twitter のようにテキスト内の「@xxx」や「#xxx」にリンクを貼る方法(Android)

やり方 ①
いい感じのライブラリがありました AutoLinkTextView

やり方 ②
SpannableString で検索すると色々と出ます。
リンクがタップされた場合の動作設定、リンクの下線を消したり
リンクの色を変更したりと、なんだかんだできます。

文字列の中から「@xxx」を抽出する方法

// @xxxを抽出したい文字列(String)
String text = "@xxx 晴れ女? @yyy とんだハッピー @zzz 野郎だな";
//「@+半角英数字とアンダーバー」までの部分を抜き出す。
Pattern ptn = Pattern.compile("@([a-zA-Z0-9_]+)");
Matcher mt = ptn.matcher(text);
while (mt.find()) {
// mt.group() に抽出された「@xxx」が入っています。
Log.d("文章内の該当した部分", "【" + mt.group() + "】");
// whileがループする度に2つ目、3つ目の「@yyy」「@zzz」が入ります。
}

これで AndroidSNS アプリを作ることができます!

Android で画像トリミング機能を実装してみた件


AndroidInstagram や LINE アプリの様に
プロフィールアイコンに使用する画像を
切り取る処理を実装する方法について

手段その①
android Git repositories - Git at Google から拝借する

Gallery アプリ内に CropImage.java があるので
付随して必要なファイルを全てコピーします。

git clone https://android.googlesource.com/platform/packages/apps/Gallery
git clone https://android.googlesource.com/platform/packages/apps/Gallery2
git clone https://android.googlesource.com/platform/packages/apps/Gallery3D
クローンして Eclipse or Android Studio で検索すると早く見つけられます。

ギャラリーアプリは3つありますが違いはよく分かりません。
私は Gallery2 の CropImage を参照しましたが、
Gallery と Gallery3D にも CropImage ファイルが入っていました。
(Gallery3D は Android 2.0 まで?)

CropImage 周辺ファイルのカスタマイズについて
HighlightView.java のコンストラクタに以下のコードを追加しました。
public HighlightView(View ctx) {
ctx.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mContext = ctx;
}
Android 4.0 以上でもフォーカスの当たらない部分に網掛けするために
ハードウェアアクセラレーションを OFF にします。
Yukiの枝折: Android:ハードウェアアクセラレーション
しかし動きが遅くなってしまいました。
網掛けを止めればサクサク移動できるようになりました。

またフラグが色々とあるので true, false で各種設定を変更できます。

トリミングしたい画像の URI からファイルパス(String)を返す処理についてですが
Android 2.x, 4.x と 4.4 のファイルパスは違うらしいので
Android バージョンを判定して処理を変える必要があるそうです。

また SAMSUNGGALAXY Note Edge などの端末で
トリミングする画像の向きが正しくならない場合があります。
なので Bitmap を読み込む前に ExifInterface を取得して画像の向きを正しく直す必要があります。
ギャラリーから取得した写真を正しい向きで表示

丸枠のトリミングができます。


四角のトリミングもできます。


手段その②
Android 端末にデフォルトでインストールされているアプリのトリミング機能を使用する
Crop image android android - Stack Overflow
デフォルトのギャラリーアプリに画像切り抜き機能があるので Intent で呼び出して使用します。

手段その③
GitHub で公開されているライブラリを使う
ArthurHub/Android-Image-Cropper
lvillani/android-cropimage
biokys/cropimage

“CropImage android” で検索して見つけました

手段その④
AdobeCreative SDK を利用する。

ListView本体の縦幅を無理やり高く設定するとどうなるのか?(Android)


ListViewの縦幅を無理やり
「セルの縦幅×セルの数」
に設定するとどうなるのか

ListViewのxml
android:height="match_parent"
または
android:height="wrap_content"
を設定しておけば普通
そんなことはできませんが、
javaファイルからListViewの高さを
「セルの縦幅×セルの数」に無理やり変更し
スクロールにも対応した実装を作成しました。

結果はメモリが足りなくなりスクロールと
表示の動作がすごく遅くなりました。
もしもリストの項目が多い場合には
アプリが強制終了する可能性も…。
これではListViewを使う意味がなくなってしまいます。

ListViewはディスプレイに表示されていない
部分のセルをメモリから解放するのですが、
リストの縦幅を「セルの縦幅×セルの数」分サイズ取ってしまうと
ListViewのセルを全部表示してしまうことになるので
例えばリストの項目が1000個存在する場合には
ディスプレイに表示されていない部分の
セルがメモリから解放されない事になってしまいます。

結論:ListViewの縦幅は常識的な高さにするべし

Q:そもそも何故ListViewの縦幅を無理やり変更するという行為に至ったのか
A:「Pinterest」や「Google Keep」アプリの様に段違いになる2列リストにヘッダーを入れるレイアウトを作りたかったからです

段違いになる2列リストの上にヘッダーのレイアウトを置き
画面全体をスクロールさせることで「Pinterest」っぽいレイアウトを
再現しましたが、上記のようにメモリが開放されなくなるのでダメでした。

調べると段違いになる複数列リストにヘッダーとフッターを追加できるライブラリが存在しました。
AndroidStaggeredGrid

Android 5.0 からはマテリアルデザインでライブラリ無しで実現できるようにならないでしょうか