Просмотр исходного кода

Merge remote-tracking branch 'origin/master'

kunfei 4 лет назад
Родитель
Сommit
9e03646b68
24 измененных файлов с 366 добавлено и 149 удалено
  1. 0 0
      app/src/main/assets/help/jsExtensions.md
  2. 227 0
      app/src/main/assets/help/jsHelp.md
  3. 36 87
      app/src/main/assets/help/ruleHelp.md
  4. 5 1
      app/src/main/assets/updateLog.md
  5. 7 1
      app/src/main/assets/web/bookSource/index.html
  6. 2 0
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  7. 15 0
      app/src/main/java/io/legado/app/help/IntentHelp.kt
  8. 2 2
      app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
  9. 2 2
      app/src/main/java/io/legado/app/model/webBook/WebBook.kt
  10. 10 10
      app/src/main/java/io/legado/app/service/WebService.kt
  11. 0 6
      app/src/main/java/io/legado/app/ui/about/AboutFragment.kt
  12. 1 1
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  13. 3 3
      app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt
  14. 12 13
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt
  15. 26 18
      app/src/main/java/io/legado/app/utils/ContextExtensions.kt
  16. 1 1
      app/src/main/java/io/legado/app/utils/NetworkUtils.kt
  17. 2 1
      app/src/main/res/layout/item_chapter_list.xml
  18. 1 0
      app/src/main/res/values-es-rES/strings.xml
  19. 1 0
      app/src/main/res/values-ja-rJP/strings.xml
  20. 1 0
      app/src/main/res/values-zh-rHK/strings.xml
  21. 1 0
      app/src/main/res/values-zh-rTW/strings.xml
  22. 1 0
      app/src/main/res/values-zh/strings.xml
  23. 1 0
      app/src/main/res/values/strings.xml
  24. 9 3
      build.gradle

+ 0 - 0
app/src/main/assets/help/jsExtensions.md


+ 227 - 0
app/src/main/assets/help/jsHelp.md

@@ -0,0 +1,227 @@
+# js变量和函数
+
+书源规则中使用js可访问以下变量
+> java 变量-当前类  
+> baseUrl 变量-当前url,String  
+> result 变量-上一步的结果  
+> book 变量-[书籍类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/Book.kt)  
+> chapter 变量-[当前目录类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookChapter.kt)  
+> source 变量-[基础书源类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BaseSource.kt)  
+> cookie 变量-[cookie操作类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/help/http/CookieStore.kt)  
+> cache 变量-[缓存操作类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/help/CacheManager.kt)  
+> title 变量-当前标题,String  
+> src 内容,源码  
+> nextChapterUrl 变量 下一章节url  
+
+## 当前类对象的可使用的部分方法
+
+### [AnalyzeUrl](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt) 部分函数
+> js中通过java.调用,只在`登录检查JS`规则中有效
+```
+initUrl() //重新解析url,可以用于登录检测js登录后重新解析url重新访问
+getHeaderMap().putAll(source.getHeaderMap(true)) //重新设置登录头
+getStrResponse( jsStr: String? = null, sourceRegex: String? = null) //返回访问结果,文本类型,书源内部重新登录后可调用此方法重新返回结果
+getResponse(): Response //返回访问结果,网络朗读引擎采用的是这个,调用登录后在调用这方法可以重新访问,参考阿里云登录检测
+```
+
+### [AnalyzeRule](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt) 部分函数
+* 获取文本/文本列表
+> `mContent` 待解析源代码,默认为当前页面  
+> `isUrl` 链接标识,默认为`false`
+```
+java.getString(ruleStr: String?, mContent: Any? = null, isUrl: Boolean = false)
+java.getStringList(ruleStr: String?, mContent: Any? = null, isUrl: Boolean = false)
+```
+* 设置解析内容
+```
+java.setContent(content: Any?, baseUrl: String? = null):
+```
+* 获取Element/Element列表
+> 如果要改变解析源代码,请先使用`java.setContent`
+```
+java.getElement(ruleStr: String)
+java.getElements(ruleStr: String)
+```
+
+### [js扩展类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/help/JsExtensions.kt) 部分函数
+* 变量存取
+```
+java.get(key)
+java.put(key, value)
+```
+* 网络请求
+```
+java.ajax(urlStr)
+java.ajaxAll(urlList: Array<String>): Array<StrResponse?>
+```
+* 调试
+```
+java.log(msg)
+java.logType(var)
+```
+* 缓存网络文件
+```
+获取
+java.cacheFile(url)
+java.cacheFile(url,saveTime)
+执行内容
+eval(String(java.cacheFile(url)))
+删除缓存文件
+cache.delete(java.md5Encode16(url))
+```
+* 获取网络zip文件里面的数据
+```
+java.getZipStringContent(url: String, path: String)
+```
+* base64
+> flags参数可省略,默认Base64.NO_WRAP,查看[flags参数说明](https://blog.csdn.net/zcmain/article/details/97051870)
+```
+java.base64Decode(str: String, flags: Int)
+java.base64Encode(str: String, flags: Int)
+```
+* 文件
+>  所有对于文件的读写删操作都是相对路径,只能操作阅读缓存/android/data/{package}/cache/内的文件
+```
+java.readTxtFile(path: String): String
+java.deleteFile(path: String) 
+```
+****
+> [常见加密解密算法介绍](https://www.yijiyong.com/algorithm/encryption/01-intro.html)
+> [相关概念](https://blog.csdn.net/OrangeJack/article/details/82913804)  
+* AES
+```
+* @param data 传入的原始数据
+* @param key AES加密的key
+* @param transformation AES加密的方式 例如AES/ECB/PKCS5Padding
+* @param iv ECB模式的偏移向量
+java.aesDecodeToString(str: String, key: String, transformation: String, iv: String)
+
+java.aesBase64DecodeToString(str: String, key: String, transformation: String, iv: String)
+
+java.aesEncodeToString(str: String, key: String, transformation: String, iv: String)
+
+java.aesEncodeToBase64String(str: String, key: String, transformation: String, iv: String)
+```
+* 3DES
+```
+* @param data 被加密的字符串
+* @param key 密钥
+* @param mode 模式 ECB/CBC/CFB/OFB/CTR
+* @param padding 补码方式 NoPadding/PKCS5Padding/
+* @param iv 加盐
+java.tripleDESEncodeBase64Str(data: String,key: String,mode: String,padding: String,iv: String): String?
+
+java.tripleDESDecodeStr(data: String,key: String,mode: String,padding: String,iv: String): String?
+```
+* 摘要
+```
+* @param data 被摘要数据
+* @param algorithm 签名算法 MD5/SHA1/SHA256/SHA512
+java.digestHex(data: String,algorithm: String,): String?
+
+java.digestBase64Str(data: String,algorithm: String,): String?
+```
+* md5
+```
+java.md5Encode(str)
+java.md5Encode16(str)
+```
+
+## book对象的可用属性
+> 使用方法: 在js中或{{}}中使用book.属性的方式即可获取.如在正文内容后加上 ##{{book.name+"正文卷"+title}} 可以净化 书名+正文卷+章节名称(如 我是大明星正文卷第二章我爸是豪门总裁) 这一类的字符.
+```
+bookUrl // 详情页Url(本地书源存储完整文件路径)
+tocUrl // 目录页Url (toc=table of Contents)
+origin // 书源URL(默认BookType.local)
+originName //书源名称 or 本地书籍文件名
+name // 书籍名称(书源获取)
+author // 作者名称(书源获取)
+kind // 分类信息(书源获取)
+customTag // 分类信息(用户修改)
+coverUrl // 封面Url(书源获取)
+customCoverUrl // 封面Url(用户修改)
+intro // 简介内容(书源获取)
+customIntro // 简介内容(用户修改)
+charset // 自定义字符集名称(仅适用于本地书籍)
+type // 0:text 1:audio
+group // 自定义分组索引号
+latestChapterTitle // 最新章节标题
+latestChapterTime // 最新章节标题更新时间
+lastCheckTime // 最近一次更新书籍信息的时间
+lastCheckCount // 最近一次发现新章节的数量
+totalChapterNum // 书籍目录总数
+durChapterTitle // 当前章节名称
+durChapterIndex // 当前章节索引
+durChapterPos // 当前阅读的进度(首行字符的索引位置)
+durChapterTime // 最近一次阅读书籍的时间(打开正文的时间)
+canUpdate // 刷新书架时更新书籍信息
+order // 手动排序
+originOrder //书源排序
+variable // 自定义书籍变量信息(用于书源规则检索书籍信息)
+ ```
+
+## chapter对象的部分可用属性
+> 使用方法: 在js中或{{}}中使用chapter.属性的方式即可获取.如在正文内容后加上 ##{{chapter.title+chapter.index}} 可以净化 章节标题+序号(如 第二章 天仙下凡2) 这一类的字符.
+ ```
+ url // 章节地址
+ title // 章节标题
+ baseUrl //用来拼接相对url
+ bookUrl // 书籍地址
+ index // 章节序号
+ resourceUrl // 音频真实URL
+ tag //
+ start // 章节起始位置
+ end // 章节终止位置
+ variable //变量
+ ```
+ 
+## source对象的部分可用函数
+* 获取书源url
+```
+source.getKey()
+```
+* 书源变量存取
+```
+source.setVariable(variable: String?)
+source.getVariable()
+```
+
+* 登录头操作
+```
+source.getLoginHeader()
+source.getLoginHeaderMap().get(key: String)
+source.putLoginHeader(header: String)
+source.removeLoginHeader()
+```
+* 用户登录信息操作
+> 使用`登录UI`规则,并成功登录,阅读自动加密保存登录UI规则中除type为button的信息
+```
+source.getLoginInfo()
+source.getLoginInfoMap().get(key: String)
+source.removeLoginInfo()
+```
+## cookie对象的部分可用函数
+```
+获取全部cookie
+cookie.getCookie(url)
+获取cookie某一键值
+cookie.getKey(url,key)
+删除cookie
+cookie.removeCookie(key)
+```
+
+## cache对象的部分可用函数
+> saveTime单位:秒,可省略  
+> 保存至数据库和缓存文件(50M),保存的内容较大时请使用`getFile putFile`
+```
+保存
+cache.put(key, value , saveTime)
+读取数据库
+cache.get(key)
+删除
+cache.delete(key)
+缓存文件内容
+cache.putFile(key, value, saveTime)
+读取文件内容
+cache.getFile(key)
+```

+ 36 - 87
app/src/main/assets/help/ruleHelp.md

@@ -2,8 +2,7 @@
 
 
 * [书源帮助文档](https://alanskycn.gitee.io/teachme/Rule/source.html)
 * [书源帮助文档](https://alanskycn.gitee.io/teachme/Rule/source.html)
 * [订阅源帮助文档](https://alanskycn.gitee.io/teachme/Rule/rss.html)
 * [订阅源帮助文档](https://alanskycn.gitee.io/teachme/Rule/rss.html)
-* [js扩展类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/help/JsExtensions.kt)
-* 辅助键盘❓中可插入URL参数模板,打开帮助,选择文件
+* 辅助键盘❓中可插入URL参数模板,打开帮助,js教程,正则教程,选择文件
 * 规则标志, {{......}}内使用规则必须有明显的规则标志,没有规则标志当作js执行
 * 规则标志, {{......}}内使用规则必须有明显的规则标志,没有规则标志当作js执行
 ```
 ```
 @@ 默认规则,直接写时可以省略@@
 @@ 默认规则,直接写时可以省略@@
@@ -12,6 +11,36 @@
 : regex规则,不可省略,只可以用在书籍列表和目录列表
 : regex规则,不可省略,只可以用在书籍列表和目录列表
 ```
 ```
 
 
+* 登录UI
+> 不使用内置webView登录网站,需要使用`登录URL`规则实现登录逻辑,可使用`登录检查JS`检查登录结果
+```
+规则填写示范
+[
+    {
+        name: "telephone",
+        type: "text"
+    },
+    {
+        name: "password",
+        type: "password"
+    },
+    {
+        name: "注册",
+        type: "button",
+        action: "http://www.yooike.com/xiaoshuo/#/register?title=%E6%B3%A8%E5%86%8C"
+    }
+]
+成功登录后在js中获取读取登录信息
+source.getLoginInfo()
+source.getLoginInfoMap().get("telephone")
+登录信息示范
+{
+    "telephone":"123456",
+    "password":"123456"
+}
+
+```
+
 * 发现url格式
 * 发现url格式
 ```json
 ```json
 [
 [
@@ -29,25 +58,6 @@
 ]
 ]
 ```
 ```
 
 
-* 获取登录后的cookie
-```
-获取全部
-cookie.getCookie(url)
-获取某一键值
-cookie.getKey(url,key)
-```
-
-* 缓存网络文件
-```
-获取
-java.cacheFile(url)
-java.cacheFile(url,saveTime)
-执行内容
-eval(String(java.cacheFile(url)))
-删除缓存文件
-cache.delete(java.md5Encode16(url))
-```
-
 * 请求头,支持http代理,socks4 socks5代理设置
 * 请求头,支持http代理,socks4 socks5代理设置
 ```
 ```
 socks5代理
 socks5代理
@@ -64,19 +74,6 @@ http代理
 }
 }
 注意:这些请求头是无意义的,会被忽略掉
 注意:这些请求头是无意义的,会被忽略掉
 ```
 ```
-  
-* js 变量和函数
-```
-java 变量-当前类
-baseUrl 变量-当前url,String
-result 变量-上一步的结果
-book 变量-书籍类,方法见 io.legado.app.data.entities.Book
-cookie 变量-cookie操作类,方法见 io.legado.app.help.http.CookieStore
-cache 变量-缓存操作类,方法见 io.legado.app.help.CacheManager
-chapter 变量-当前目录类,方法见 io.legado.app.data.entities.BookChapter
-title 变量-当前标题,String
-src 内容,源码
-```
 
 
 * url添加js参数,解析url时执行,可在访问url时处理url,例
 * url添加js参数,解析url时执行,可在访问url时处理url,例
 ```
 ```
@@ -113,7 +110,7 @@ https://www.baidu.com,{"js":"java.url=java.url+'yyyy'"}
 })()
 })()
 ```
 ```
 
 
-* 正文图片链接支持修改headers
+* 图片链接支持修改headers
 ```
 ```
 let options = {
 let options = {
 "headers": {"User-Agent": "xxxx","Referrer":baseUrl,"Cookie":"aaa=vbbb;"}
 "headers": {"User-Agent": "xxxx","Referrer":baseUrl,"Cookie":"aaa=vbbb;"}
@@ -121,58 +118,7 @@ let options = {
 '<img src="'+src+","+JSON.stringify(options)+'">'
 '<img src="'+src+","+JSON.stringify(options)+'">'
 ```
 ```
 
 
- ## 部分js对象属性说明
-上述js变量与函数中,一些js的对象属性用的频率较高,在此列举。方便写源的时候快速翻阅。
-
-### book对象的可用属性
-> 使用方法: 在js中或{{}}中使用book.属性的方式即可获取.如在正文内容后加上 ##{{book.name+"正文卷"+title}} 可以净化 书名+正文卷+章节名称(如 我是大明星正文卷第二章我爸是豪门总裁) 这一类的字符.
-```
-bookUrl // 详情页Url(本地书源存储完整文件路径)
-tocUrl // 目录页Url (toc=table of Contents)
-origin // 书源URL(默认BookType.local)
-originName //书源名称 or 本地书籍文件名
-name // 书籍名称(书源获取)
-author // 作者名称(书源获取)
-kind // 分类信息(书源获取)
-customTag // 分类信息(用户修改)
-coverUrl // 封面Url(书源获取)
-customCoverUrl // 封面Url(用户修改)
-intro // 简介内容(书源获取)
-customIntro // 简介内容(用户修改)
-charset // 自定义字符集名称(仅适用于本地书籍)
-type // 0:text 1:audio
-group // 自定义分组索引号
-latestChapterTitle // 最新章节标题
-latestChapterTime // 最新章节标题更新时间
-lastCheckTime // 最近一次更新书籍信息的时间
-lastCheckCount // 最近一次发现新章节的数量
-totalChapterNum // 书籍目录总数
-durChapterTitle // 当前章节名称
-durChapterIndex // 当前章节索引
-durChapterPos // 当前阅读的进度(首行字符的索引位置)
-durChapterTime // 最近一次阅读书籍的时间(打开正文的时间)
-canUpdate // 刷新书架时更新书籍信息
-order // 手动排序
-originOrder //书源排序
-variable // 自定义书籍变量信息(用于书源规则检索书籍信息)
- ```
-
-### chapter对象的可用属性
-> 使用方法: 在js中或{{}}中使用chapter.属性的方式即可获取.如在正文内容后加上 ##{{chapter.title+chapter.index}} 可以净化 章节标题+序号(如 第二章 天仙下凡2) 这一类的字符.
- ```
- url // 章节地址
- title // 章节标题
- baseUrl //用来拼接相对url
- bookUrl // 书籍地址
- index // 章节序号
- resourceUrl // 音频真实URL
- tag //
- start // 章节起始位置
- end // 章节终止位置
- variable //变量
- ```
-
-### 字体解析使用
+* 字体解析使用
 > 使用方法,在正文替换规则中使用,原理根据f1字体的字形数据到f2中查找字形对应的编码
 > 使用方法,在正文替换规则中使用,原理根据f1字体的字形数据到f2中查找字形对应的编码
 ```
 ```
 <js>
 <js>
@@ -188,3 +134,6 @@ variable // 自定义书籍变量信息(用于书源规则检索书籍信息)
 </js>
 </js>
 ```
 ```
 
 
+* 购买操作
+> 返回购买链接,可直接填写链接或者JavaScript  
+> 可用变量 book chapter

+ 5 - 1
app/src/main/assets/updateLog.md

@@ -11,11 +11,15 @@
 * 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
 * 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
 * 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
 * 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
 
 
+**2020/01/17**
+* 添加payAction规则,返回购买链接
+* 书源编辑中的辅助键盘❓中可查看js说明文档
+
 **2022/01/11**
 **2022/01/11**
 
 
 * 紧急修复在线tts朗读bug
 * 紧急修复在线tts朗读bug
 * 紧急修复登录问题
 * 紧急修复登录问题
-* 添加isVolume规则,支持二级目录,页眉标题、正文标题显示优化 by Xwite
+* 添加isVolume规则,支持二级目录,正文标题显示优化 by Xwite
 
 
 **2022/01/10**
 **2022/01/10**
 
 

+ 7 - 1
app/src/main/assets/web/bookSource/index.html

@@ -251,7 +251,7 @@
                           placeholder="选择章节链接 (规则结果为String类型的Url)"></textarea>
                           placeholder="选择章节链接 (规则结果为String类型的Url)"></textarea>
             </div>
             </div>
             <div>
             <div>
-                <div>Volume标识:</div>
+                <div>卷名标识:</div>
                 <textarea rows="1" id="ruleToc_isVolume" class="ruleToc" title="isVolume"
                 <textarea rows="1" id="ruleToc_isVolume" class="ruleToc" title="isVolume"
                           placeholder="章节名称是否是卷名 (规则结果为Bool)"></textarea>
                           placeholder="章节名称是否是卷名 (规则结果为Bool)"></textarea>
             </div>
             </div>
@@ -311,6 +311,12 @@
                           title="imageStyle"
                           title="imageStyle"
                           placeholder="FULL:铺满 不填:默认样式"></textarea>
                           placeholder="FULL:铺满 不填:默认样式"></textarea>
             </div>
             </div>
+            <div>
+                <div>购买操作:</div>
+                <textarea rows="1" id="ruleContent_payAction" class="ruleContent"
+                          title="payAction"
+                          placeholder="购买章节 返回链接或js"></textarea>
+            </div>
             <p></p>
             <p></p>
             <div><b>其它规则</b></div>
             <div><b>其它规则</b></div>
             <div>
             <div>

+ 2 - 0
app/src/main/java/io/legado/app/data/entities/BookChapter.kt

@@ -109,6 +109,8 @@ data class BookChapter(
     }
     }
 
 
     fun getAbsoluteURL(): String {
     fun getAbsoluteURL(): String {
+        //二级目录解析的卷链接为空 返回目录页的链接
+        if (url.startsWith(title) && isVolume) return baseUrl
         val urlMatcher = AnalyzeUrl.paramPattern.matcher(url)
         val urlMatcher = AnalyzeUrl.paramPattern.matcher(url)
         val urlBefore = if (urlMatcher.find()) url.substring(0, urlMatcher.start()) else url
         val urlBefore = if (urlMatcher.find()) url.substring(0, urlMatcher.start()) else url
         val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl, urlBefore)
         val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl, urlBefore)

+ 15 - 0
app/src/main/java/io/legado/app/help/IntentHelp.kt

@@ -2,12 +2,27 @@ package io.legado.app.help
 
 
 import android.content.Context
 import android.content.Context
 import android.content.Intent
 import android.content.Intent
+import android.net.Uri
 import io.legado.app.R
 import io.legado.app.R
 import io.legado.app.utils.toastOnUi
 import io.legado.app.utils.toastOnUi
+import splitties.init.appCtx
 
 
 @Suppress("unused")
 @Suppress("unused")
 object IntentHelp {
 object IntentHelp {
 
 
+    fun getBrowserIntent(url: String): Intent {
+        return getBrowserIntent(Uri.parse(url))
+    }
+
+    fun getBrowserIntent(uri: Uri): Intent {
+        val intent = Intent(Intent.ACTION_VIEW)
+        intent.data = uri
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+        if (intent.resolveActivity(appCtx.packageManager) == null) {
+            return Intent.createChooser(intent, "请选择浏览器")
+        }
+        return intent
+    }
 
 
     fun toTTSSetting(context: Context) {
     fun toTTSSetting(context: Context) {
         //跳转到文字转语音设置界面
         //跳转到文字转语音设置界面

+ 2 - 2
app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt

@@ -193,8 +193,8 @@ object BookChapterList {
                 }
                 }
                 if (bookChapter.url.isEmpty()) {
                 if (bookChapter.url.isEmpty()) {
                     if (bookChapter.isVolume) {
                     if (bookChapter.isVolume) {
-                        bookChapter.url = bookChapter.title
-                        Debug.log(bookSource.bookSourceUrl, "一级目录${index}未获取到url,使用章节标题替代")
+                        bookChapter.url = bookChapter.title + index
+                        Debug.log(bookSource.bookSourceUrl, "一级目录${index}未获取到url,使用${bookChapter.title}${index}替代")
                     } else {
                     } else {
                         bookChapter.url = baseUrl
                         bookChapter.url = baseUrl
                         Debug.log(bookSource.bookSourceUrl, "目录${index}未获取到url,使用baseUrl替代")
                         Debug.log(bookSource.bookSourceUrl, "目录${index}未获取到url,使用baseUrl替代")

+ 2 - 2
app/src/main/java/io/legado/app/model/webBook/WebBook.kt

@@ -261,8 +261,8 @@ object WebBook {
             Debug.log(bookSource.bookSourceUrl, "⇒正文规则为空,使用章节链接:${bookChapter.url}")
             Debug.log(bookSource.bookSourceUrl, "⇒正文规则为空,使用章节链接:${bookChapter.url}")
             return bookChapter.url
             return bookChapter.url
         }
         }
-        if(bookChapter.isVolume && bookChapter.url == bookChapter.title) {
-            Debug.log(bookSource.bookSourceUrl, "⇒一级目录获取链接为空,使用${bookChapter.tag}")
+        if(bookChapter.isVolume && bookChapter.url.startsWith(bookChapter.title)) {
+            Debug.log(bookSource.bookSourceUrl, "⇒一级目录正文不解析规则")
             return bookChapter.tag ?: ""
             return bookChapter.tag ?: ""
         }
         }
         return if (bookChapter.url == book.bookUrl && !book.tocHtml.isNullOrEmpty()) {
         return if (bookChapter.url == book.bookUrl && !book.tocHtml.isNullOrEmpty()) {

+ 10 - 10
app/src/main/java/io/legado/app/service/WebService.kt

@@ -10,7 +10,6 @@ import io.legado.app.constant.AppConst
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.IntentAction
 import io.legado.app.constant.IntentAction
 import io.legado.app.constant.PreferKey
 import io.legado.app.constant.PreferKey
-import io.legado.app.ui.main.MainActivity
 import io.legado.app.utils.*
 import io.legado.app.utils.*
 import io.legado.app.web.HttpServer
 import io.legado.app.web.HttpServer
 import io.legado.app.web.WebSocketServer
 import io.legado.app.web.WebSocketServer
@@ -45,6 +44,15 @@ class WebService : BaseService() {
         upTile(true)
         upTile(true)
     }
     }
 
 
+    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+        when (intent?.action) {
+            IntentAction.stop -> stopSelf()
+            "copyHostAddress" -> sendToClip(hostAddress)
+            else -> upWebServer()
+        }
+        return super.onStartCommand(intent, flags, startId)
+    }
+
     override fun onDestroy() {
     override fun onDestroy() {
         super.onDestroy()
         super.onDestroy()
         isRun = false
         isRun = false
@@ -58,14 +66,6 @@ class WebService : BaseService() {
         upTile(false)
         upTile(false)
     }
     }
 
 
-    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
-        when (intent?.action) {
-            IntentAction.stop -> stopSelf()
-            else -> upWebServer()
-        }
-        return super.onStartCommand(intent, flags, startId)
-    }
-
     private fun upWebServer() {
     private fun upWebServer() {
         if (httpServer?.isAlive == true) {
         if (httpServer?.isAlive == true) {
             httpServer?.stop()
             httpServer?.stop()
@@ -114,7 +114,7 @@ class WebService : BaseService() {
             .setContentTitle(getString(R.string.web_service))
             .setContentTitle(getString(R.string.web_service))
             .setContentText(notificationContent)
             .setContentText(notificationContent)
             .setContentIntent(
             .setContentIntent(
-                activityPendingIntent<MainActivity>("webService")
+                servicePendingIntent<WebService>("copyHostAddress")
             )
             )
         builder.addAction(
         builder.addAction(
             R.drawable.ic_stop_black_24dp,
             R.drawable.ic_stop_black_24dp,

+ 0 - 6
app/src/main/java/io/legado/app/ui/about/AboutFragment.kt

@@ -22,12 +22,6 @@ class AboutFragment : PreferenceFragmentCompat() {
     private val licenseUrl = "https://github.com/gedoor/legado/blob/master/LICENSE"
     private val licenseUrl = "https://github.com/gedoor/legado/blob/master/LICENSE"
     private val disclaimerUrl = "https://gedoor.github.io/MyBookshelf/disclaimer.html"
     private val disclaimerUrl = "https://gedoor.github.io/MyBookshelf/disclaimer.html"
     private val qqGroups = linkedMapOf(
     private val qqGroups = linkedMapOf(
-        Pair("(QQ群VIP中转)1017837876", "0d9-zpmqbYfK3i_wt8uCvQoB2lmXadrg"),
-        Pair("(QQ群VIP1)701903217", "-iolizL4cbJSutKRpeImHlXlpLDZnzeF"),
-        Pair("(QQ群VIP2)263949160", "xwfh7_csb2Gf3Aw2qexEcEtviLfLfd4L"),
-        Pair("(QQ群VIP3)680280282", "_N0i7yZObjKSeZQvzoe2ej7j02kLnOOK"),
-        Pair("(QQ群VIP4)682555679", "VF2UwvUCuaqlo6pddWTe_kw__a1_Fr8O"),
-        Pair("(QQ群VIP5)161622578", "S81xdnhJ5EBC389LTUvoyiyM-wr71pvJ"),
         Pair("(QQ群1)805192012", "6GlFKjLeIk5RhQnR3PNVDaKB6j10royo"),
         Pair("(QQ群1)805192012", "6GlFKjLeIk5RhQnR3PNVDaKB6j10royo"),
         Pair("(QQ群2)773736122", "5Bm5w6OgLupXnICbYvbgzpPUgf0UlsJF"),
         Pair("(QQ群2)773736122", "5Bm5w6OgLupXnICbYvbgzpPUgf0UlsJF"),
         Pair("(QQ群3)981838750", "g_Sgmp2nQPKqcZQ5qPcKLHziwX_mpps9"),
         Pair("(QQ群3)981838750", "g_Sgmp2nQPKqcZQ5qPcKLHziwX_mpps9"),

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt

@@ -842,7 +842,7 @@ class ReadBookActivity : BaseReadBookActivity(),
                 startActivity<WebViewActivity> {
                 startActivity<WebViewActivity> {
                     putExtra("title", getString(R.string.chapter_pay))
                     putExtra("title", getString(R.string.chapter_pay))
                     putExtra("url", it)
                     putExtra("url", it)
-                    IntentData.put(it, ReadBook.bookSource)
+                    IntentData.put(it, ReadBook.bookSource?.getHeaderMap(true))
                 }
                 }
             }
             }
         }.onError {
         }.onError {

+ 3 - 3
app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt

@@ -129,7 +129,7 @@ object ChapterProvider {
                 matcher.appendTail(sb)
                 matcher.appendTail(sb)
                 text = sb.toString()
                 text = sb.toString()
                 val isTitle = index == 0
                 val isTitle = index == 0
-                val isVolumeTitle = bookChapter.isVolume && isTitle && bookChapter.url == bookChapter.title && bookChapter.tag.isNullOrBlank()
+                val isVolumeTitle = bookChapter.isVolume && isTitle && contents.size == 1
                 val textPaint = if (isTitle) titlePaint else contentPaint
                 val textPaint = if (isTitle) titlePaint else contentPaint
                 if (!(isTitle && ReadBookConfig.titleMode == 2)) {
                 if (!(isTitle && ReadBookConfig.titleMode == 2)) {
                     setTypeText(
                     setTypeText(
@@ -147,7 +147,7 @@ object ChapterProvider {
                     val text = content.substring(start, matcher.start())
                     val text = content.substring(start, matcher.start())
                     if (text.isNotBlank()) {
                     if (text.isNotBlank()) {
                         val isTitle = index == 0
                         val isTitle = index == 0
-                        val isVolumeTitle = bookChapter.isVolume && isTitle && bookChapter.url == bookChapter.title && bookChapter.tag.isNullOrBlank()
+                        val isVolumeTitle = bookChapter.isVolume && isTitle && contents.size == 1
                         val textPaint = if (isTitle) titlePaint else contentPaint
                         val textPaint = if (isTitle) titlePaint else contentPaint
                         if (!(isTitle && ReadBookConfig.titleMode == 2)) {
                         if (!(isTitle && ReadBookConfig.titleMode == 2)) {
                             setTypeText(
                             setTypeText(
@@ -169,7 +169,7 @@ object ChapterProvider {
                     val text = content.substring(start, content.length)
                     val text = content.substring(start, content.length)
                     if (text.isNotBlank()) {
                     if (text.isNotBlank()) {
                         val isTitle = index == 0
                         val isTitle = index == 0
-                        val isVolumeTitle = bookChapter.isVolume && isTitle && bookChapter.url == bookChapter.title && bookChapter.tag.isNullOrBlank()
+                        val isVolumeTitle = bookChapter.isVolume && isTitle && contents.size == 1
                         val textPaint = if (isTitle) titlePaint else contentPaint
                         val textPaint = if (isTitle) titlePaint else contentPaint
                         if (!(isTitle && ReadBookConfig.titleMode == 2)) {
                         if (!(isTitle && ReadBookConfig.titleMode == 2)) {
                             setTypeText(
                             setTypeText(

+ 12 - 13
app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt

@@ -77,7 +77,7 @@ class BookSourceEditActivity :
     override fun onPostCreate(savedInstanceState: Bundle?) {
     override fun onPostCreate(savedInstanceState: Bundle?) {
         super.onPostCreate(savedInstanceState)
         super.onPostCreate(savedInstanceState)
         if (!LocalConfig.ruleHelpVersionIsLast) {
         if (!LocalConfig.ruleHelpVersionIsLast) {
-            showRuleHelp()
+            showHelp("ruleHelp")
         }
         }
     }
     }
 
 
@@ -119,7 +119,7 @@ class BookSourceEditActivity :
                 getString(R.string.share_book_source),
                 getString(R.string.share_book_source),
                 ErrorCorrectionLevel.L
                 ErrorCorrectionLevel.L
             )
             )
-            R.id.menu_help -> showRuleHelp()
+            R.id.menu_help -> showHelp("ruleHelp")
             R.id.menu_login -> getSource().let { source ->
             R.id.menu_login -> getSource().let { source ->
                 if (checkSource(source)) {
                 if (checkSource(source)) {
                     viewModel.save(source) {
                     viewModel.save(source) {
@@ -281,6 +281,7 @@ class BookSourceEditActivity :
             add(EditEntity("sourceRegex", cr?.sourceRegex, R.string.rule_source_regex))
             add(EditEntity("sourceRegex", cr?.sourceRegex, R.string.rule_source_regex))
             add(EditEntity("replaceRegex", cr?.replaceRegex, R.string.rule_replace_regex))
             add(EditEntity("replaceRegex", cr?.replaceRegex, R.string.rule_replace_regex))
             add(EditEntity("imageStyle", cr?.imageStyle, R.string.rule_image_style))
             add(EditEntity("imageStyle", cr?.imageStyle, R.string.rule_image_style))
+            add(EditEntity("payAction", cr?.payAction, R.string.rule_pay_action))
         }
         }
         binding.tabLayout.selectTab(binding.tabLayout.getTabAt(0))
         binding.tabLayout.selectTab(binding.tabLayout.getTabAt(0))
         setEditEntities(0)
         setEditEntities(0)
@@ -376,6 +377,7 @@ class BookSourceEditActivity :
                 "sourceRegex" -> contentRule.sourceRegex = it.value
                 "sourceRegex" -> contentRule.sourceRegex = it.value
                 "replaceRegex" -> contentRule.replaceRegex = it.value
                 "replaceRegex" -> contentRule.replaceRegex = it.value
                 "imageStyle" -> contentRule.imageStyle = it.value
                 "imageStyle" -> contentRule.imageStyle = it.value
+                "payAction" -> contentRule.payAction = it.value
             }
             }
         }
         }
         source.ruleSearch = searchRule
         source.ruleSearch = searchRule
@@ -418,26 +420,23 @@ class BookSourceEditActivity :
     }
     }
 
 
     private fun showHelpDialog() {
     private fun showHelpDialog() {
-        val items = arrayListOf("插入URL参数", "书源教程", "正则教程", "选择文件")
+        val items = arrayListOf("插入URL参数", "书源教程", "js教程", "正则教程", "选择文件")
         selector(getString(R.string.help), items) { _, index ->
         selector(getString(R.string.help), items) { _, index ->
             when (index) {
             when (index) {
                 0 -> insertText(AppConst.urlOption)
                 0 -> insertText(AppConst.urlOption)
-                1 -> showRuleHelp()
-                2 -> showRegexHelp()
-                3 -> selectDoc.launch {
+                1 -> showHelp("ruleHelp")
+                2 -> showHelp("jsHelp")
+                3 -> showHelp("regexHelp")
+                4 -> selectDoc.launch {
                     mode = HandleFileContract.FILE
                     mode = HandleFileContract.FILE
                 }
                 }
             }
             }
         }
         }
     }
     }
 
 
-    private fun showRuleHelp() {
-        val mdText = String(assets.open("help/ruleHelp.md").readBytes())
-        showDialogFragment(TextDialog(mdText, TextDialog.Mode.MD))
-    }
-
-    private fun showRegexHelp() {
-        val mdText = String(assets.open("help/regexHelp.md").readBytes())
+    private fun showHelp(fileName: String) {
+        //显示目录help下的帮助文档
+        val mdText = String(assets.open("help/${fileName}.md").readBytes())
         showDialogFragment(TextDialog(mdText, TextDialog.Mode.MD))
         showDialogFragment(TextDialog(mdText, TextDialog.Mode.MD))
     }
     }
 
 

+ 26 - 18
app/src/main/java/io/legado/app/utils/ContextExtensions.kt

@@ -27,6 +27,7 @@ import androidx.preference.PreferenceManager
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
 import io.legado.app.R
 import io.legado.app.R
 import io.legado.app.constant.AppConst
 import io.legado.app.constant.AppConst
+import io.legado.app.help.IntentHelp
 import timber.log.Timber
 import timber.log.Timber
 import java.io.File
 import java.io.File
 import java.io.FileOutputStream
 import java.io.FileOutputStream
@@ -62,6 +63,20 @@ inline fun <reified T : Service> Context.servicePendingIntent(
     return getService(this, 0, intent, flags)
     return getService(this, 0, intent, flags)
 }
 }
 
 
+@SuppressLint("UnspecifiedImmutableFlag")
+fun Context.activityPendingIntent(
+    intent: Intent,
+    action: String
+): PendingIntent? {
+    intent.action = action
+    val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+        FLAG_UPDATE_CURRENT or FLAG_MUTABLE
+    } else {
+        FLAG_UPDATE_CURRENT
+    }
+    return getActivity(this, 0, intent, flags)
+}
+
 @SuppressLint("UnspecifiedImmutableFlag")
 @SuppressLint("UnspecifiedImmutableFlag")
 inline fun <reified T : Activity> Context.activityPendingIntent(
 inline fun <reified T : Activity> Context.activityPendingIntent(
     action: String,
     action: String,
@@ -145,8 +160,8 @@ fun Context.restart() {
     intent?.let {
     intent?.let {
         intent.addFlags(
         intent.addFlags(
             Intent.FLAG_ACTIVITY_NEW_TASK
             Intent.FLAG_ACTIVITY_NEW_TASK
-                    or Intent.FLAG_ACTIVITY_CLEAR_TASK
-                    or Intent.FLAG_ACTIVITY_CLEAR_TOP
+                or Intent.FLAG_ACTIVITY_CLEAR_TASK
+                or Intent.FLAG_ACTIVITY_CLEAR_TOP
         )
         )
         startActivity(intent)
         startActivity(intent)
         //杀掉以前进程
         //杀掉以前进程
@@ -284,25 +299,18 @@ val Context.externalCache: File
     get() = this.externalCacheDir ?: this.cacheDir
     get() = this.externalCacheDir ?: this.cacheDir
 
 
 fun Context.openUrl(url: String) {
 fun Context.openUrl(url: String) {
-    openUrl(Uri.parse(url))
+    try {
+        startActivity(IntentHelp.getBrowserIntent(url))
+    } catch (e: Exception) {
+        toastOnUi(e.localizedMessage ?: "open url error")
+    }
 }
 }
 
 
 fun Context.openUrl(uri: Uri) {
 fun Context.openUrl(uri: Uri) {
-    val intent = Intent(Intent.ACTION_VIEW)
-    intent.data = uri
-    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-    if (intent.resolveActivity(packageManager) != null) {
-        try {
-            startActivity(intent)
-        } catch (e: Exception) {
-            toastOnUi(e.localizedMessage ?: "open url error")
-        }
-    } else {
-        try {
-            startActivity(Intent.createChooser(intent, "请选择浏览器"))
-        } catch (e: Exception) {
-            toastOnUi(e.localizedMessage ?: "open url error")
-        }
+    try {
+        startActivity(IntentHelp.getBrowserIntent(uri))
+    } catch (e: Exception) {
+        toastOnUi(e.localizedMessage ?: "open url error")
     }
     }
 }
 }
 
 

+ 1 - 1
app/src/main/java/io/legado/app/utils/NetworkUtils.kt

@@ -153,7 +153,7 @@ object NetworkUtils {
     }
     }
 
 
     /**
     /**
-     * 获取二级域名,供cookie保存和读取
+     * 获取域名,供cookie保存和读取
      * http://1.2.3.4 => 1.2.3.4
      * http://1.2.3.4 => 1.2.3.4
      * https://www.example.com =>  example.com
      * https://www.example.com =>  example.com
      * http://www.biquge.com.cn => biquge.com.cn
      * http://www.biquge.com.cn => biquge.com.cn

+ 2 - 1
app/src/main/res/layout/item_chapter_list.xml

@@ -17,7 +17,7 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toLeftOf="@+id/iv_checked"
         app:layout_constraintRight_toLeftOf="@+id/iv_checked"
-        app:layout_constraintBottom_toBottomOf="parent" />
+        app:layout_constraintBottom_toTopOf="@id/tv_tag" />
 
 
     <TextView
     <TextView
         android:id="@+id/tv_tag"
         android:id="@+id/tv_tag"
@@ -26,6 +26,7 @@
         android:textSize="12sp"
         android:textSize="12sp"
         android:visibility="gone"
         android:visibility="gone"
         android:singleLine="true"
         android:singleLine="true"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
         app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toLeftOf="@+id/iv_checked" />
         app:layout_constraintRight_toLeftOf="@+id/iv_checked" />

+ 1 - 0
app/src/main/res/values-es-rES/strings.xml

@@ -423,6 +423,7 @@
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_image_style">图片样式(imageStyle)</string>
     <string name="rule_image_style">图片样式(imageStyle)</string>
+    <string name="rule_pay_action">pay action(payAction)</string>
 
 
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>

+ 1 - 0
app/src/main/res/values-ja-rJP/strings.xml

@@ -427,6 +427,7 @@
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_image_style">图片样式(imageStyle)</string>
     <string name="rule_image_style">图片样式(imageStyle)</string>
+    <string name="rule_pay_action">pay action(payAction)</string>
 
 
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>

+ 1 - 0
app/src/main/res/values-zh-rHK/strings.xml

@@ -420,6 +420,7 @@
     <string name="rule_next_content">正文下一頁 URL 規則 (nextContentUrl)</string>
     <string name="rule_next_content">正文下一頁 URL 規則 (nextContentUrl)</string>
     <string name="rule_web_js">WebViewJs (webJs)</string>
     <string name="rule_web_js">WebViewJs (webJs)</string>
     <string name="rule_source_regex">資源正則 (sourceRegex)</string>
     <string name="rule_source_regex">資源正則 (sourceRegex)</string>
+    <string name="rule_pay_action">购买操作(payAction)</string>
     <string name="source_icon">圖標 (sourceIcon)</string>
     <string name="source_icon">圖標 (sourceIcon)</string>
     <string name="r_articles">列表規則 (ruleArticles)</string>
     <string name="r_articles">列表規則 (ruleArticles)</string>
     <string name="r_next">列表下一頁規則 (ruleArticles)</string>
     <string name="r_next">列表下一頁規則 (ruleArticles)</string>

+ 1 - 0
app/src/main/res/values-zh-rTW/strings.xml

@@ -426,6 +426,7 @@
     <string name="rule_image_style">圖片樣式(imageStyle)</string>
     <string name="rule_image_style">圖片樣式(imageStyle)</string>
     <string name="rule_replace_regex">取代規則(replaceRegex)</string>
     <string name="rule_replace_regex">取代規則(replaceRegex)</string>
     <string name="rule_source_regex">資源正則(sourceRegex)</string>
     <string name="rule_source_regex">資源正則(sourceRegex)</string>
+    <string name="rule_pay_action">购买操作(payAction)</string>
 
 
     <string name="source_icon">圖示(sourceIcon)</string>
     <string name="source_icon">圖示(sourceIcon)</string>
     <string name="r_articles">列表規則(ruleArticles)</string>
     <string name="r_articles">列表規則(ruleArticles)</string>

+ 1 - 0
app/src/main/res/values-zh/strings.xml

@@ -426,6 +426,7 @@
     <string name="rule_image_style">图片样式(imageStyle)</string>
     <string name="rule_image_style">图片样式(imageStyle)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
+    <string name="rule_pay_action">购买操作(payAction)</string>
 
 
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -427,6 +427,7 @@
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
     <string name="rule_source_regex">资源正则(sourceRegex)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_replace_regex">替换规则(replaceRegex)</string>
     <string name="rule_image_style">图片样式(imageStyle)</string>
     <string name="rule_image_style">图片样式(imageStyle)</string>
+    <string name="rule_pay_action">购买操作(payAction)</string>
 
 
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="source_icon">图标(sourceIcon)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>
     <string name="r_articles">列表规则(ruleArticles)</string>

+ 9 - 3
build.gradle

@@ -3,11 +3,14 @@
 buildscript {
 buildscript {
     ext.kotlin_version = '1.6.10'
     ext.kotlin_version = '1.6.10'
     repositories {
     repositories {
+        //原仓库
         google()
         google()
         mavenCentral()
         mavenCentral()
         maven { url 'https://plugins.gradle.org/m2/' }
         maven { url 'https://plugins.gradle.org/m2/' }
-        maven { url 'https://maven.aliyun.com/repository/public' }
-        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
+        //镜像仓库,无法连接源仓库自行启用镜像仓库,不要提交修改
+        //maven { url 'https://maven.aliyun.com/repository/google' }
+        //maven { url 'https://maven.aliyun.com/repository/public' }
+        //maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
     }
     }
     dependencies {
     dependencies {
         classpath 'com.android.tools.build:gradle:7.0.4'
         classpath 'com.android.tools.build:gradle:7.0.4'
@@ -19,10 +22,13 @@ buildscript {
 
 
 allprojects {
 allprojects {
     repositories {
     repositories {
+        //原仓库
         google()
         google()
         mavenCentral()
         mavenCentral()
-        maven { url 'https://maven.aliyun.com/repository/public' }
         maven { url 'https://jitpack.io' }
         maven { url 'https://jitpack.io' }
+        //镜像仓库,无法连接源仓库自行启用镜像仓库,不要提交修改
+        //maven { url 'https://maven.aliyun.com/repository/google' }
+        //maven { url 'https://maven.aliyun.com/repository/public' }
     }
     }
 }
 }