前言
Leko 今天 (2020-08-26) 在 Twitter 上看到一篇值得分享的好消息,想分享到 FB 上
剛好想起之前人家介紹的 Tuigram 還有 Twiger 可以把 tweet 變成圖片
用了才發現,兩個軟體居然都只支援分享到 Instagram 上 (Leko 不是很喜歡 IG :(
所以就想說改一下 APP 讓他們支援分享到任意 App 上 yay
![]() |
---|
值得分享的好消息 |
會用到的東西
- APK 檔
- apktool
- JADX
- Android SDK
本文
Tuigram (入門級)
我們的目標很簡單,把原本的分享到 Instagram 的按鈕改成可以隨意分享
1. 反編譯
> apktool.bat d '.\Tuigram Share tweets on instagram_v1.1.7_apkpure.com.apk' -r
在原地會看到一個新生出來的資料夾
2. 看 Code
用 JADX 開啟 APK
按放大鏡把 Text search 叫出來 (順便等他 Decompile 完)
想著總之先搜尋 instagram
吧,沒想到一搜就中,yay
要代換的程式碼
看一下官方 Doc,可以看到我們需要的 Code
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));
JADX 搜尋出來的 Code 如下
public boolean b(String str, String str2) {
Intent intent = new Intent("com.instagram.share.ADD_TO_STORY");
Uri a2 = FileProvider.a(this, "com.vcoud.fileprovider", new File(str2));
intent.setType(str);
intent.putExtra("interactive_asset_uri", a2);
grantUriPermission("com.instagram.android", a2, 1);
if (getPackageManager().resolveActivity(intent, 0) == null) {
return false;
}
startActivityForResult(intent, 0);
return true;
}
// 中間省略
public void a(String str, String str2) {
Intent intent = new Intent("android.intent.action.SEND");
intent.setType(str);
Uri a2 = FileProvider.a(this, "com.vcoud.fileprovider", new File(str2));
intent.addFlags(1);
intent.putExtra("android.intent.extra.STREAM", a2);
intent.setComponent(new ComponentName("com.instagram.android", "com.instagram.share.handleractivity.ShareHandlerActivity"));
startActivity(intent);
}
可以明顯的看出 b
是分享到 IG 限動,a
是普通的 IG 貼文
a
跟我們的目標最像,所以我們改 a
(差別只在 a:7
的 setComponent
還有範例 Code 的 Intent.createChooser
)
3. 改 Code
我們打開步驟 1 生出的資料夾,在 smali/com/vcoud/tuigram/MainActivity.smali
找到我們的 target
首先我們要先把 setComponent
刪掉 (很顯然的就是 .line 11
的部分,全部註解掉)
接著加上 Intent.createChooser
的部分
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));
// 事實上相當於
String title = getResources().getText(R.string.send_to);
Intent chooser = Intent.createChooser(shareIntent, title);
startActivity(chooser)
所以我們寫
# String title = "分享至"
# 這個是上面的 getResources().getText(R.string.send_to)
# 會作為分享畫面的標題
const-string v1, "分享至"
# 在 .line 5 可以看到 new-instance v0, Landroid/content/Intent;
# 也就是 Intent
# v1 則是我們的 string
# 接受一個 Intent 和一個 CharSequence 作為參數,回傳一個 Intent
# 其中 createChooser 是一個 static method
invoke-static {v0, v1}, Landroid/content/Intent;->createChooser(Landroid/content/Intent;Ljava/lang/CharSequence;)Landroid/content/Intent;
# 把上一步驟的結果 (chooser) 移到 v1 裡 (v1 是不會再用到的 string 所以不用擔心)
move-result-object v1
# 接著我們 startActivity
# 注意到 class method 的第一個參數是 class instance,類似 python 裡的 Class function 第一個參數總是 self
# 原本他 call 的是 {p0, v0},其中 v0 是原本的 Intent
# 現在我們把 v0 換成我們剛剛新建立的 chooser,也就是 v1
invoke-virtual {p0, v1}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
結果長得像這樣
# ...
.line 11
# new-instance p1, Landroid/content/ComponentName;
# const-string p2, "com.instagram.android"
# const-string v1, "com.instagram.share.handleractivity.ShareHandlerActivity"
# invoke-direct {p1, p2, v1}, Landroid/content/ComponentName;->(Ljava/lang/String;Ljava/lang/String;)V
# invoke-virtual {v0, p1}, Landroid/content/Intent;->setComponent(Landroid/content/ComponentName;)Landroid/content/Intent;
.line 12
const-string v1, "分享至"
invoke-static {v0, v1}, Landroid/content/Intent;->createChooser(Landroid/content/Intent;Ljava/lang/CharSequence;)Landroid/content/Intent;
move-result-object v1
invoke-virtual {p0, v1}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
return-void
.end method
# ...
儲存。
4. 打包回去
> apktool.bat b '.\Tuigram Share tweets on instagram_v1.1.7_apkpure.com\'
結果會在 .\Tuigram Share tweets on instagram_v1.1.7_apkpure.com\dist\
裡面找到
build 好的 APK,簽名後裝進手機裡就大功告成辣 owo
4.1 簽名
首先建立 Keystore
> keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
keytool
在 JDK 裡面有附
接著簽名
> %ANDROID_SDK%\build-tools\%VERSION%\apksigner.bat sign --ks %KEYSTORE% %APK_PATH%
把 %ANDROID_SDK%
, %VERSION%
, %KEYSTORE%
, %APK_PATH%
換掉就可以簽名了
![]() |
---|
yay |