【Android】画像タップで拡大表示。さらにピンチインアウト可能にする。

これは何

Android 開発で ImageView をタップしたら画像を拡大表示し、それをピンチインアウトでズームできるようにする方法です。

利用ライブラリ

https://github.com/davemorrissey/subsampling-scale-image-view

ライブラリインストール方法は上にあるので割愛します

修正内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 拡大対象のImageViewにタップ時のリスナーをセット
mImageView.setOnClickListener(v -> {
SubsamplingScaleImageView imageViewEnlarged = new SubsamplingScaleImageView(getContext());
Bitmap bitmap = ((BitmapDrawable) mImageView.getDrawable()).getBitmap();
imageViewEnlarged.setImage(ImageSource.bitmap(bitmap));
// 画面の横幅を取得
Display display = ((Activity) getContext()).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
float width = size.x;
float factor = width / bitmap.getWidth();
Dialog dialog = new Dialog(getContext());
// 画像をセットして表示する
dialog.setContentView(imageViewEnlarged);
dialog.getWindow().setLayout((int)(bitmap.getWidth()*factor), (int)(bitmap.getHeight()*factor));
dialog.show();
});

てか Android 開発、情報少なすぎません?泣
ただ画像をタップして拡大表示してピンチインアウトするだけのことがなんでこんなに情報がないのか?
なかなかライブラリに辿り着けなくて、結構ハマっちゃいました、、
ツライけどお互い頑張りましょう、、w

参考

[Android]ImageView の scaleType を秒で決める
[Android]メモリリークを起こさずに大きな画像を表示させるライブラリ「Subsampling Scale Image View」

【Android】ProGuardからR8に変更したらアプリが落ちるようになった原因と解決策

事象

ProGuard から R8 に乗り換えた後、アプリをビルドして起動したところ、
いくつかの画面がクラッシュしてアプリが落ちる不具合が発生しました

原因

GSON を利用していた場合、文字列をそのまま利用する必要があるが、難読化されてしまったため

解決策

proguard-project.txt に以下のコードを追加する

1
2
3
4
5
### for Gson in R8
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep,allowobfuscation @interface com.google.gson.annotations.SerializedName

これ結構重要なところなのに情報が少なすぎてビビる、、
Android 開発の情報もっと増えてくれ〜

参考

R8 互換性 FAQ

【Android】BuildConfigが見つからないエラー

BuildConfig が見つからないエラーになった時の解決策です

  1. Android Studio >ファイル>キャッシュの破棄>再起動
  2. Android Studio >ビルド>プロジェクトをクリーンにする
  3. Android Studio >ビルド>プロジェクトの再ビルド

参考

BuildConfig not getting created correctly (Gradle Android)

【Android】aabファイルをリバースエンジニアリングしてみた

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# abb→apk
brew install bundletool
bundletool build-apks --mode=universal --bundle=./app-release.aab --output=./app-release.apks
unzip app-release.apks

# apk→dex
unzip universal.apk

# dex→jar
# dexをjarに変換するためのツールをダウンロードする
# https://sourceforge.net/projects/dex2jar/files/
chmod 777 dex2jar-2.0/d2j-dex2jar.sh
./dex2jar/d2j-dex2jar.sh classes.dex

# jar→class
unzip classes-dex2jar.jar
# classファイルの中身が見れるツールをダウンロード
wget https://github.com/java-decompiler/jd-gui/releases/download/v1.6.6/jd-gui-1.6.6.jar
java -jar jd-gui-1.6.6.jar

# あとは見たいclassファイルを選択すればOK

こんな感じ

良いね!

参考
Android の APK を逆コンパイルする
Java Decompiler project の JD-GUI で JAR ファイルからソースコードを生成する

AndroidアプリでiBeaconを受信する

利用ライブラリ

https://github.com/AltBeacon/android-beacon-library

設定を変更

app/build.gradle に以下を追加

1
2
3
dependencies {
implementation 'org.altbeacon:android-beacon-library:2+'
}

受信コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import org.altbeacon.beacon.*
import kotlin.collections.ArrayList

class HogeActivity : AppCompatActivity(), BeaconConsumer {
private val TAG: String = "HogeActivity"
// ビーコンマネージャ宣言
private lateinit var mBeaconManager: BeaconManager
// iBeaconのデータを認識するためのParserフォーマット
private val IBEACON_FORMAT: String = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"

private val mRegion = Region("unique-id-001", null, null, null)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_Hogee)
// ビーコンマネージャのインスタンス作成
mBeaconManager = BeaconManager.getInstanceForApplication(this)
// iBeaconのフォーマットをParserへ渡す
mBeaconManager.beaconParsers.add(BeaconParser().setBeaconLayout(IBEACON_FORMAT))
}

override fun onPause() {
super.onPause()
mBeaconManager.unbind(this)
Log.d(TAG, "ビーコンサービスを解除した")
}

override fun onResume() {
super.onResume()
mBeaconManager.bind(this)
Log.d(TAG, "ビーコンサービスを起動した")
}

override fun onBeaconServiceConnect() {

// 初期化。これがないと画面を2回以上開いた時に2重でデータを受信してしまう
mBeaconManager.removeAllMonitorNotifiers()
mBeaconManager.removeAllRangeNotifiers()
mBeaconManager.rangedRegions.forEach {region ->
mBeaconManager.stopRangingBeaconsInRegion(region)
}

mBeaconManager.addMonitorNotifier(object : MonitorNotifier {
// ビーコン信号の領域内へ侵入した際に呼ばれる
override fun didEnterRegion(region: Region) {
Log.d(TAG, "ビーコンが近くにいる!ビーコンが発信するデータの受信を開始する")
}

// ビーコン信号の領域外へ退出した際に呼ばれる
override fun didExitRegion(region: Region) {
Log.d(TAG, "ビーコンが近くにいなくなった。。ビーコンが発信するデータの受信を停止する")
}

// 領域への侵入/退出のステータスが変化した際に呼ばれる
// 一見didEnterRegionやdidExitRegionで十分に見えるが、実際にはこっちしか呼ばれないことがある
override fun didDetermineStateForRegion(state: Int, region: Region) {
Log.d(TAG, "ビーコンの侵入/退出ステータスが変化: $state")
try {
if (state == 1) {
mBeaconManager.startRangingBeaconsInRegion(region)
} else {
mBeaconManager.stopRangingBeaconsInRegion(region)
}
} catch (e: RemoteException) {
Log.d(TAG, "didDetermineStateForRegion e = " + e.message)
}
}
})

try {
mBeaconManager.startMonitoringBeaconsInRegion(mRegion)
Log.d(TAG, "ビーコンが近くにいるかどうかの監視を開始した。")
} catch (e: RemoteException) {
Log.e(TAG, "Exception", e)
e.printStackTrace()
}

mBeaconManager.addRangeNotifier(RangeNotifier { beacons, region ->
// ビーコンにデータが入っていない場合はbeaconsは[]となる
// また、設定から位置情報を許可した状態でない場合もbeaconsは[]となる
Log.d(TAG, "ビーコンデータ:${beacons}")
for (beacon in beacons) {
Log.d(TAG, "UUID:" + beacon.id1 + ", major:" + beacon.id2
+ ", minor:" + beacon.id3 + ", Distance:" + beacon.distance
+ ",RSSI" + beacon.rssi)
}
})
}
}

その他

検索したら一番上に出てくる qiita の記事とかだと removeAllMonitorNotifiers がなかったりして動かなかくて結構ハマった。。
以下の参考記事のおかげで解決した!
ありがてえ!

参考

[Android]AltBeacon を使って iBeacon を受信する

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×