明月照我还 发表于 2020-12-12 15:06

查找某阅读 app 的下载位置

本帖最后由 明月照我还 于 2020-12-13 12:57 编辑

>刚学习不久,正好最近遇到一个问题,拿来练练手

## 起因
最近使用某阅读应用看书,app 的阅读体验并不好,所以想要找到下载的文件导入到其他阅读器阅读,但是常规方法并没有找到,所以反编译看下下载位置。
## 准备
工具:jadx, DB Browser;
一部有 root 权限的手机;
## 查找过程
1. 首先读取包名:cn.com.bookan

2. adb shell dumpsys window 获取书刊阅读的界面类名是 EpubReaderActivity


3.
在阅读页面下方有下载按钮,点击下载后,会有一个提示:下载中,请到“书架”-“我的下载”中查看", 在 EpubReaderActivity 中搜索提示的字符串,可以找到下载按钮的点击逻辑:

```   
/* access modifiers changed from: package-private */
    @OnClick({2131296832})
    public void onDownloadClick(View view) {
      LogUtil.m15486a(this.f8694j, 20007, 3);
      if (!NetUtil.m15279a(this)) {
            MyToast.m16477a(this, getString(C1300R.string.net_error), 0).show();
      } else if (FusionField.m13348ac() > 0 || DBScanRecord.m13484a().mo19549a(this.f8694j)) {
            new CountDownTimer(1000, 200) {
                public void onFinish() {
                  if (FusionField.f10257s == 1) {
                        DBDownload.m13459a().mo19524b(EpubReaderActivity.this.f8694j, "epub");
                        DBDownload.m13459a().mo19522a(GsonUtil.m15346a(EpubReaderActivity.this.f8694j), 100, EpubReaderActivity.this.f8694j, "epub");
                  } else {
                        DBDownload.m13459a().mo19521a(EpubReaderActivity.this.f8694j, "epub");
                        DBDownload.m13459a().mo19525b(GsonUtil.m15346a(EpubReaderActivity.this.f8694j), 100, EpubReaderActivity.this.f8694j, "epub");
                  }
                  EpubReaderActivity.this.itemReaderBotomOpdoneContainer.setVisibility(0);
                  EpubReaderActivity.this.itemReaderBotomOpopContainer.setVisibility(8);
                }

                public void onTick(long j) {
                  int unused = EpubReaderActivity.this.f8678ab = EpubReaderActivity.this.f8678ab + 20;
                  EpubReaderActivity.this.itemReaderBottomDownloadText.setText(EpubReaderActivity.this.getString(C1300R.string.reader_download_ing));
                  EpubReaderActivity.this.itemReaderBottomDownloadImg.setImageResource(C1300R.C1301drawable.btn_download_resume);
                  EpubReaderActivity.this.itemReaderBottomDownloadProgress.setVisibility(0);
                  EpubReaderActivity.this.itemReaderBottomDownloadProgress.setProgress(EpubReaderActivity.this.f8678ab);
                }
            }.start();
            Toast.makeText(this, "下载中,请到“书架”-“我的下载”中查看", 0).show();
      } else {
            new MyDialogNotice(this, String.format(getString(C1300R.string.right_download), new Object[]{FusionField.m13362aq(), FusionField.m13363ar()})).show();
      }
    }
```


可以发现应该是这块逻辑做的下载操作:
```
if (FusionField.f10257s == 1) {
                        DBDownload.m13459a().mo19524b(EpubReaderActivity.this.f8694j, "epub");
                        DBDownload.m13459a().mo19522a(GsonUtil.m15346a(EpubReaderActivity.this.f8694j), 100, EpubReaderActivity.this.f8694j, "epub");
                  } else {
                        DBDownload.m13459a().mo19521a(EpubReaderActivity.this.f8694j, "epub");
                        DBDownload.m13459a().mo19525b(GsonUtil.m15346a(EpubReaderActivity.this.f8694j), 100, EpubReaderActivity.this.f8694j, "epub");
                  }
```


虽然混淆了,但是下载应该是通过 mo19522a 或 mo19525b 方法,跟进去看下:
理解错了,这俩应该是线程操作:
```
    /* renamed from: b */
    public void mo19525b(String str, int i, IssueInfo issueInfo, String str2) {
      ThreadPoolUtil.m15065a().mo21766a((Runnable) new C3138c(str, i, issueInfo, str2));
      ThreadPoolUtil.m15065a().mo21767b();
    }
```


不过在它上面正好有 run 方法:
```
public void run() {
            if (StringUtil.m15053c(this.f10398b)) {
                Debug.m15248e("DBDownloadinsert mcontent is null", new Object);
                return;
            }
            SQLiteDatabase writableDatabase = MagookDBHelper.m13490a().getWritableDatabase();
            ContentValues contentValues = new ContentValues();
            contentValues.put("content", this.f10398b);
            contentValues.put(NotificationCompat.CATEGORY_PROGRESS, Integer.valueOf(this.f10399c));
            contentValues.put("userid", String.valueOf(FusionField.m13414m()));
            contentValues.put("issueid", this.f10400d.getResourceType() == 5 ? this.f10400d.getResourceId() : this.f10400d.getIssueId());
            contentValues.put("personid", Integer.valueOf(FusionField.m13320P()));
            contentValues.put("readtype", this.f10401e);
            long insert = writableDatabase.insert(MagookDBHelper.C3166i.f10503a, (String) null, contentValues);
            Debug.m15248e("progress DB: " + this.f10399c, new Object);
            Debug.m15244a("DBDownload insert result=%s content=%s", Long.valueOf(insert), this.f10398b);
            DownloadItemModel downloadItemModel = new DownloadItemModel();
            downloadItemModel.setItem((IssueInfo) GsonUtil.m15344a(this.f10398b, IssueInfo.class));
            downloadItemModel.setProgress(this.f10399c);
            downloadItemModel.setReadType(this.f10401e);
            if (!FusionField.f10261w.containsKey(this.f10400d.getResourceType() == 5 ? this.f10400d.getResourceId() : this.f10400d.getIssueId())) {
                FusionField.f10261w.put(this.f10400d.getResourceType() == 5 ? this.f10400d.getResourceId() : this.f10400d.getIssueId(), downloadItemModel);
                PreferenceUtil.m14946a("isSynchDownload", true);
            }
      }
    }
```

看到这里可以确定是存到 SQLITE 中了:
```
SQLiteDatabase writableDatabase = MagookDBHelper.m13490a().getWritableDatabase();   
```
进MagookDBHelper 看下:
```
public void onCreate(SQLiteDatabase sQLiteDatabase) {
      sQLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS download(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,progress INTEGER,userid INTEGER,content TEXT,readtype TEXT)");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS readrecord(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,userid INTEGER,content TEXT)");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS collection(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,userid INTEGER,content TEXT)");
      sQLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS downloadsingleperson(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,progress INTEGER,userid INTEGER,personid INTEGER,content TEXT,readtype TEXT)");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS readrecordsingleperson(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,userid INTEGER,personid INTEGER,content TEXT)");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS collectionsingleperson(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,userid INTEGER,personid INTEGER,content TEXT)");
      Debug.m15248e("Error inserting: createSQL: " + "create table IF NOT EXISTS message(_id INTEGER PRIMARY KEY AUTOINCREMENT, messageid INTEGER,status INTEGER,type INTEGER,isdelete INTEGER,title VARCHAR(256),url TEXT,content TEXT,resources TEXT,creattime VARCHAR(32))", new Object);
      sQLiteDatabase.execSQL("create table IF NOT EXISTS message(_id INTEGER PRIMARY KEY AUTOINCREMENT, messageid INTEGER,status INTEGER,type INTEGER,isdelete INTEGER,title VARCHAR(256),url TEXT,content TEXT,resources TEXT,creattime VARCHAR(32))");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS searchhistory(_id INTEGER PRIMARY KEY AUTOINCREMENT,userid INTEGER,restype INTEGER,resourcetype INTEGER,searchtype INTEGER,content TEXT)");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS readpositionrecord(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,page INTEGER,userid INTEGER)");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS audiopositionrecord(_id INTEGER PRIMARY KEY AUTOINCREMENT, issueid INTEGER,resourceid INTEGER,position INTEGER,userid INTEGER,personid INTEGER,playissueid INTEGER)");
      sQLiteDatabase.execSQL("create table IF NOT EXISTS scanrecord(_id INTEGER PRIMARY KEY AUTOINCREMENT, resourceType INTEGER,resourceid INTEGER,issueid)");
    }
```

看不出来放在哪个表了,去手机中 把 DB 拖出来看下:
adb pull /data/data/cn.com.bookan/databases/ .
注意:这个命令需要 root 权限。

看着 books.db 比较像,就是体积有点小,使用 DB Browser 打开看下:


猜测 Files 里面可能有想要的东西,切换到 浏览数据,过滤 Files:
看到一个存储路径 /storage/emulated/0/.bookan/file/487514

把这个文件取下来,放到手机里打开,确实就是刚才下载的文件。

## 至此,找到了这个 apk 下载的文件位置:
/storage/emulated/0/.bookan/file

duanwang 发表于 2020-12-13 09:14

不用这么麻烦吧,直接在文件管理器里查找文件名不就可以了吗

明月照我还 发表于 2020-12-13 14:00

Gif 发表于 2020-12-13 10:59
楼主大大,能帮忙找一下 咪咕阅读 下载的书在哪里吗,网上也找不到(要是会编程的话,也许根据楼主的思路找 ...

/storage/emulated/0/Reader/Books/
使用文件管理器可以在手机中看到这个路径,不同文件管理器看到的路径名称不同,一般手机自带的管理器上,Reader 是在你的根目录。
另外,咪咕用的是 .meb 格式,不是常见的电子书格式,不好找到能用的阅读器,所以就算取出来了用处也不大....

kk神伤 发表于 2020-12-13 08:13

66666牛皮

songxp03 发表于 2020-12-13 08:40

牛🐮,学习了

bright21vn 发表于 2020-12-13 09:09

这个还是有用的

cherub0507 发表于 2020-12-13 09:23

这个还是有用的

hnwang 发表于 2020-12-13 10:15

也正好有这个需求,正好参考下楼主的,感谢

Gif 发表于 2020-12-13 10:54

楼主牛皮!马!

kek151 发表于 2020-12-13 10:59

楼主也是牛

Gif 发表于 2020-12-13 10:59

楼主大大,能帮忙找一下 咪咕阅读 下载的书在哪里吗,网上也找不到(要是会编程的话,也许根据楼主的思路找找吧,很遗憾。。。。)
页: [1] 2
查看完整版本: 查找某阅读 app 的下载位置