@ -0,0 +1,19 @@ |
||||
--- |
||||
name: "[FeatureRequest] 功能请求模板" |
||||
about: 提交你希望能够在阅读中增加的功能 |
||||
title: "[Feature Request] " |
||||
labels: '需求' |
||||
assignees: '' |
||||
--- |
||||
|
||||
### 功能描述(请清晰的、详细的描述你想要的功能) |
||||
> |
||||
|
||||
### 期望实现方式(阅读应该如何实现该功能) |
||||
> |
||||
|
||||
### 附加信息(其他的与功能相关的附加信息) |
||||
> |
||||
|
||||
### 效果演示(可以手绘一些草图,或者提供可借鉴的图片) |
||||
> |
@ -0,0 +1,98 @@ |
||||
import requests, os, datetime, sys |
||||
|
||||
# Cookie 中 phpdisk_info 的值 |
||||
cookie_phpdisk_info = os.environ.get('phpdisk_info') |
||||
# Cookie 中 ylogin 的值 |
||||
cookie_ylogin = os.environ.get('ylogin') |
||||
|
||||
# 请求头 |
||||
headers = { |
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36 Edg/89.0.774.45', |
||||
'Accept-Language': 'zh-CN,zh;q=0.9', |
||||
'Referer': 'https://pc.woozooo.com/account.php?action=login' |
||||
} |
||||
|
||||
# 小饼干 |
||||
cookie = { |
||||
'ylogin': cookie_ylogin, |
||||
'phpdisk_info': cookie_phpdisk_info |
||||
} |
||||
|
||||
|
||||
# 日志打印 |
||||
def log(msg): |
||||
utc_time = datetime.datetime.utcnow() |
||||
china_time = utc_time + datetime.timedelta(hours=8) |
||||
print(f"[{china_time.strftime('%Y.%m.%d %H:%M:%S')}] {msg}") |
||||
|
||||
|
||||
# 检查是否已登录 |
||||
def login_by_cookie(): |
||||
url_account = "https://pc.woozooo.com/account.php" |
||||
if cookie['phpdisk_info'] is None: |
||||
log('ERROR: 请指定 Cookie 中 phpdisk_info 的值!') |
||||
return False |
||||
if cookie['ylogin'] is None: |
||||
log('ERROR: 请指定 Cookie 中 ylogin 的值!') |
||||
return False |
||||
res = requests.get(url_account, headers=headers, cookies=cookie, verify=True) |
||||
if '网盘用户登录' in res.text: |
||||
log('ERROR: 登录失败,请更新Cookie') |
||||
return False |
||||
else: |
||||
log('登录成功') |
||||
return True |
||||
|
||||
|
||||
# 上传文件 |
||||
def upload_file(file_dir, folder_id): |
||||
file_name = os.path.basename(file_dir) |
||||
url_upload = "https://up.woozooo.com/fileup.php" |
||||
headers['Referer'] = f'https://up.woozooo.com/mydisk.php?item=files&action=index&u={cookie_ylogin}' |
||||
post_data = { |
||||
"task": "1", |
||||
"folder_id": folder_id, |
||||
"id": "WU_FILE_0", |
||||
"name": file_name, |
||||
} |
||||
files = {'upload_file': (file_name, open(file_dir, "rb"), 'application/octet-stream')} |
||||
res = requests.post(url_upload, data=post_data, files=files, headers=headers, cookies=cookie, timeout=120).json() |
||||
log(f"{file_dir} -> {res['info']}") |
||||
return res['zt'] == 1 |
||||
|
||||
|
||||
# 上传文件夹内的文件 |
||||
def upload_folder(folder_dir, folder_id): |
||||
file_list = sorted(os.listdir(folder_dir), reverse=True) |
||||
for file in file_list: |
||||
path = os.path.join(folder_dir, file) |
||||
if os.path.isfile(path): |
||||
upload_file(path, folder_id) |
||||
else: |
||||
upload_folder(path, folder_id) |
||||
|
||||
|
||||
# 上传 |
||||
def upload(dir, folder_id): |
||||
if dir is None: |
||||
log('ERROR: 请指定上传的文件路径') |
||||
return |
||||
if folder_id is None: |
||||
log('ERROR: 请指定蓝奏云的文件夹id') |
||||
return |
||||
if os.path.isfile(dir): |
||||
upload_file(dir, str(folder_id)) |
||||
else: |
||||
upload_folder(dir, str(folder_id)) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
argv = sys.argv[1:] |
||||
if len(argv) != 2: |
||||
log('ERROR: 参数错误,请以这种格式重新尝试\npython lzy_web.py 需上传的路径 蓝奏云文件夹id') |
||||
# 需上传的路径 |
||||
upload_path = argv[0] |
||||
# 蓝奏云文件夹id |
||||
lzy_folder_id = argv[1] |
||||
if login_by_cookie(): |
||||
upload(upload_path, lzy_folder_id) |
@ -0,0 +1,47 @@ |
||||
import os, sys, telebot |
||||
|
||||
# 上传文件 |
||||
def upload_file(tb, chat_id, file_dir): |
||||
doc = open(file_dir, 'rb') |
||||
tb.send_document(chat_id, doc) |
||||
|
||||
# 上传文件夹内的文件 |
||||
def upload_folder(tb, chat_id, folder_dir): |
||||
file_list = sorted(os.listdir(folder_dir)) |
||||
for file in file_list: |
||||
path = os.path.join(folder_dir, file) |
||||
if os.path.isfile(path): |
||||
upload_file(tb, chat_id, path) |
||||
else: |
||||
upload_folder(tb, chat_id, path) |
||||
|
||||
# 上传 |
||||
def upload(tb, chat_id, dir): |
||||
if tb is None: |
||||
log('ERROR: 输入正确的token') |
||||
return |
||||
if chat_id is None: |
||||
log('ERROR: 输入正确的chat_id') |
||||
return |
||||
if dir is None: |
||||
log('ERROR: 请指定上传的文件路径') |
||||
return |
||||
if os.path.isfile(dir): |
||||
upload_file(tb, chat_id, dir) |
||||
else: |
||||
upload_folder(tb, chat_id, dir) |
||||
|
||||
if __name__ == '__main__': |
||||
argv = sys.argv[1:] |
||||
if len(argv) != 3: |
||||
log('ERROR: 参数错误,请以这种格式重新尝试\npython tg_bot.py $token $chat_id 待上传的路径') |
||||
# Token |
||||
TOKEN = argv[0] |
||||
# chat_id |
||||
chat_id = argv[1] |
||||
# 待上传文件的路径 |
||||
upload_path = argv[2] |
||||
#创建连接 |
||||
tb = telebot.TeleBot(TOKEN) |
||||
#开始上传 |
||||
upload(tb, chat_id, upload_path) |
@ -0,0 +1,32 @@ |
||||
#更新fork |
||||
name: update fork |
||||
|
||||
on: |
||||
schedule: |
||||
- cron: '0 16 * * *' #设置定时任务 |
||||
|
||||
jobs: |
||||
build: |
||||
runs-on: ubuntu-latest |
||||
if: ${{ github.event.repository.owner.id == github.event.sender.id && github.actor != 'gedoor' }} |
||||
steps: |
||||
- name: Checkout |
||||
uses: actions/checkout@v2 |
||||
with: |
||||
fetch-depth: 0 |
||||
- name: Install git |
||||
run: | |
||||
sudo apt-get update |
||||
sudo apt-get -y install git |
||||
- name: Set env |
||||
run: | |
||||
git config --global user.email "github-actions@github.com" |
||||
git config --global user.name "github-actions" |
||||
- name: Update fork |
||||
run: | |
||||
git remote add upstream https://github.com/gedoor/legado.git |
||||
git remote -v |
||||
git fetch upstream |
||||
git checkout master |
||||
git merge upstream/master |
||||
git push origin master |
@ -0,0 +1,99 @@ |
||||
name: Build and Release |
||||
|
||||
on: |
||||
push: |
||||
branches: |
||||
- master |
||||
paths: |
||||
- 'CHANGELOG.md' |
||||
# schedule: |
||||
# - cron: '0 4 * * *' |
||||
|
||||
jobs: |
||||
build: |
||||
runs-on: ubuntu-latest |
||||
env: |
||||
# 登录蓝奏云后在控制台运行document.cookie |
||||
ylogin: ${{ secrets.LANZOU_ID }} |
||||
phpdisk_info: ${{ secrets.LANZOU_PSD }} |
||||
# 蓝奏云里的文件夹ID(阅读3测试版:2670621) |
||||
LANZOU_FOLDER_ID: 'b0f7pt4ja' |
||||
# 是否上传到artifact |
||||
UPLOAD_ARTIFACT: 'true' |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
with: |
||||
fetch-depth: 0 |
||||
- uses: actions/cache@v2 |
||||
with: |
||||
path: | |
||||
~/.gradle/caches |
||||
~/.gradle/wrapper |
||||
key: ${{ runner.os }}-legado-${{ hashFiles('**/updateLog.md') }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} |
||||
restore-keys: | |
||||
${{ runner.os }}-legado-${{ hashFiles('**/updateLog.md') }}- |
||||
- name: Release Apk Sign |
||||
run: | |
||||
echo "给apk增加签名" |
||||
cp $GITHUB_WORKSPACE/.github/workflows/legado.jks $GITHUB_WORKSPACE/app/legado.jks |
||||
sed '$a\RELEASE_STORE_FILE=./legado.jks' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_ALIAS=legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_STORE_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
- name: Unify Version Name |
||||
run: | |
||||
echo "统一版本号" |
||||
VERSION=$(date -d "8 hour" -u +3.%y.%m%d%H) |
||||
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV |
||||
sed "/def version/c def version = \"$VERSION\"" $GITHUB_WORKSPACE/app/build.gradle -i |
||||
- name: Build With Gradle |
||||
run: | |
||||
echo "开始进行release构建" |
||||
chmod +x gradlew |
||||
./gradlew assembleRelease --build-cache --parallel |
||||
- name: Organize the Files |
||||
run: | |
||||
mkdir -p ${{ github.workspace }}/apk/ |
||||
cp -rf ${{ github.workspace }}/app/build/outputs/apk/*/*/*.apk ${{ github.workspace }}/apk/ |
||||
- name: Upload App To Artifact |
||||
if: ${{ env.UPLOAD_ARTIFACT != 'false' }} |
||||
uses: actions/upload-artifact@v2 |
||||
with: |
||||
name: legado apk |
||||
path: ${{ github.workspace }}/apk/*.apk |
||||
- name: Upload App To Lanzou |
||||
if: ${{ env.ylogin }} |
||||
run: | |
||||
path="$GITHUB_WORKSPACE/apk/" |
||||
python3 $GITHUB_WORKSPACE/.github/scripts/lzy_web.py "$path" "$LANZOU_FOLDER_ID" |
||||
echo "[$(date -u -d '+8 hour' '+%Y.%m.%d %H:%M:%S')] 分享链接: https://kunfei.lanzoux.com/b0f7pt4ja" |
||||
- name: Release |
||||
uses: softprops/action-gh-release@59c3b4891632ff9a897f99a91d7bc557467a3a22 |
||||
with: |
||||
name: legado_app_${{ env.RELEASE_VERSION }} |
||||
tag_name: ${{ env.RELEASE_VERSION }} |
||||
body_path: ${{ github.workspace }}/CHANGELOG.md |
||||
draft: false |
||||
prerelease: false |
||||
files: ${{ github.workspace }}/apk/*.apk |
||||
env: |
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
||||
- name: Push Assets To "release" Branch |
||||
run: | |
||||
cd $GITHUB_WORKSPACE/apk || exit 1 |
||||
git init |
||||
git config --local user.name "github-actions[bot]" |
||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" |
||||
git checkout -b release |
||||
git add *.apk |
||||
git commit -m "${{ env.RELEASE_VERSION }}" |
||||
git remote add origin "https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}" |
||||
git push -f -u origin release |
||||
- name: Purge Jsdelivr Cache |
||||
run: | |
||||
result=$(curl -s https://purge.jsdelivr.net/gh/${{ github.repository }}@release/) |
||||
if echo $result |grep -q 'success.*true'; then |
||||
echo "jsdelivr缓存更新成功" |
||||
else |
||||
echo $result |
||||
fi |
@ -0,0 +1,161 @@ |
||||
name: Test Build |
||||
|
||||
on: |
||||
push: |
||||
branches: |
||||
- master |
||||
workflow_dispatch: |
||||
|
||||
jobs: |
||||
prepare: |
||||
runs-on: ubuntu-latest |
||||
outputs: |
||||
version: ${{ steps.set-ver.outputs.version }} |
||||
versionL: ${{ steps.set-ver.outputs.versionL }} |
||||
lanzou: ${{ steps.check.outputs.lanzou }} |
||||
telegram: ${{ steps.check.outputs.telegram }} |
||||
steps: |
||||
- id: set-ver |
||||
run: | |
||||
echo "::set-output name=version::$(date -d "8 hour" -u +3.%y.%m%d%H)" |
||||
echo "::set-output name=versionL::$(date -d "8 hour" -u +3.%y.%m%d%H%M)" |
||||
- id: check |
||||
run: | |
||||
if [ ${{ secrets.LANZOU_ID }} ]; then |
||||
echo "::set-output name=lanzou::yes" |
||||
fi |
||||
if [ ${{ secrets.BOT_TOKEN }} ]; then |
||||
echo "::set-output name=telegram::yes" |
||||
fi |
||||
|
||||
build: |
||||
needs: prepare |
||||
strategy: |
||||
matrix: |
||||
product: [app, google] |
||||
type: [release, releaseA] |
||||
fail-fast: false |
||||
runs-on: ubuntu-latest |
||||
env: |
||||
product: ${{ matrix.product }} |
||||
type: ${{ matrix.type }} |
||||
VERSION: ${{ needs.prepare.outputs.version }} |
||||
VERSIONL: ${{ needs.prepare.outputs.versionL }} |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
with: |
||||
fetch-depth: 0 |
||||
- uses: actions/cache@v2 |
||||
with: |
||||
path: | |
||||
~/.gradle/caches |
||||
~/.gradle/wrapper |
||||
key: ${{ runner.os }}-legado-${{ hashFiles('**/updateLog.md') }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} |
||||
restore-keys: | |
||||
${{ runner.os }}-legado-${{ hashFiles('**/updateLog.md') }}- |
||||
- name: Clear 18PlusList.txt |
||||
run: | |
||||
echo "清空18PlusList.txt" |
||||
echo "">$GITHUB_WORKSPACE/app/src/main/assets/18PlusList.txt |
||||
- name: Release Apk Sign |
||||
run: | |
||||
echo "给apk增加签名" |
||||
cp $GITHUB_WORKSPACE/.github/workflows/legado.jks $GITHUB_WORKSPACE/app/legado.jks |
||||
sed '$a\RELEASE_STORE_FILE=./legado.jks' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_ALIAS=legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_STORE_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
- name: Build With Gradle |
||||
run: | |
||||
if [ ${{ env.type }} == 'release' ]; then |
||||
typeName="原包名" |
||||
else |
||||
typeName="共存" |
||||
sed "s/'.release'/'.releaseA'/" $GITHUB_WORKSPACE/app/build.gradle -i |
||||
sed 's/.release/.releaseA/' $GITHUB_WORKSPACE/app/google-services.json -i |
||||
fi |
||||
echo "统一版本号" |
||||
sed "/def version/c def version = \"${{ env.VERSION }}\"" $GITHUB_WORKSPACE/app/build.gradle -i |
||||
echo "开始${{ env.product }}$typeName构建" |
||||
chmod +x gradlew |
||||
./gradlew assemble${{ env.product }}release --build-cache --parallel --daemon --warning-mode all |
||||
echo "修改文件名" |
||||
mkdir -p ${{ github.workspace }}/apk/ |
||||
for file in `ls ${{ github.workspace }}/app/build/outputs/apk/*/*/*.apk`; do |
||||
mv "$file" ${{ github.workspace }}/apk/legado_${{ env.product }}_${{ env.VERSIONL }}_$typeName.apk |
||||
done |
||||
- name: Upload App To Artifact |
||||
uses: actions/upload-artifact@v2 |
||||
with: |
||||
name: legado.${{ env.product }}.${{ env.type }} |
||||
path: ${{ github.workspace }}/apk/*.apk |
||||
|
||||
lanzou: |
||||
needs: [prepare, build] |
||||
if: ${{ needs.prepare.outputs.lanzou }} |
||||
runs-on: ubuntu-latest |
||||
env: |
||||
# 登录蓝奏云后在控制台运行document.cookie |
||||
ylogin: ${{ secrets.LANZOU_ID }} |
||||
phpdisk_info: ${{ secrets.LANZOU_PSD }} |
||||
# 蓝奏云里的文件夹ID(阅读3测试版:2670621) |
||||
LANZOU_FOLDER_ID: '2670621' |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- uses: actions/download-artifact@v2 |
||||
with: |
||||
path: apk/ |
||||
- working-directory: apk/ |
||||
run: mv */*.apk . ;rm -rf */ |
||||
- name: Upload To Lanzou |
||||
continue-on-error: true |
||||
run: | |
||||
path="$GITHUB_WORKSPACE/apk/" |
||||
python3 $GITHUB_WORKSPACE/.github/scripts/lzy_web.py "$path" "$LANZOU_FOLDER_ID" |
||||
echo "[$(date -u -d '+8 hour' '+%Y.%m.%d %H:%M:%S')] 分享链接: https://kunfei.lanzoux.com/b0f810h4b" |
||||
|
||||
test_Branch: |
||||
needs: [prepare, build] |
||||
runs-on: ubuntu-latest |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- uses: actions/download-artifact@v2 |
||||
with: |
||||
path: apk/ |
||||
- working-directory: apk/ |
||||
run: mv */*.apk . ;rm -rf */ |
||||
- name: Push To "test" Branch |
||||
run: | |
||||
cd $GITHUB_WORKSPACE/apk |
||||
git init |
||||
git config --local user.name "github-actions[bot]" |
||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" |
||||
git checkout -b test |
||||
git add *.apk |
||||
git commit -m "${{ needs.prepare.outputs.versionL }}" |
||||
git remote add origin "https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}" |
||||
git push -f -u origin test |
||||
|
||||
telegram: |
||||
needs: [prepare, build] |
||||
if: ${{ needs.prepare.outputs.telegram }} |
||||
runs-on: ubuntu-latest |
||||
env: |
||||
CHANNEL_ID: ${{ secrets.CHANNEL_ID }} |
||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }} |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- uses: actions/download-artifact@v2 |
||||
with: |
||||
path: apk/ |
||||
- working-directory: apk/ |
||||
run: | |
||||
for file in `ls */*.apk`; do |
||||
mv "$file" "$(echo "$file"|sed -e 's#.*\/##g' -e "s/_/ /g" -e 's/legado/阅读/')" |
||||
done |
||||
rm -rf */ |
||||
- name: Post to channel |
||||
run: | |
||||
pip install pyTelegramBotAPI |
||||
path="$GITHUB_WORKSPACE/apk/" |
||||
python3 $GITHUB_WORKSPACE/.github/scripts/tg_bot.py "$BOT_TOKEN" "$CHANNEL_ID" "$path" |
@ -0,0 +1,14 @@ |
||||
*.iml |
||||
.gradle |
||||
/local.properties |
||||
.DS_Store |
||||
/build |
||||
/captures |
||||
.externalNativeBuild |
||||
/release |
||||
/tmp |
||||
node_modules/ |
||||
/app/app |
||||
/app/google |
||||
/app/gradle.properties |
||||
package-lock.json |
@ -0,0 +1,14 @@ |
||||
# Default ignored files |
||||
/shelf/ |
||||
/workspace.xml |
||||
# Datasource local storage ignored files |
||||
/dataSources/ |
||||
/dataSources.local.xml |
||||
# Editor-based HTTP Client requests |
||||
/httpRequests/ |
||||
# Custom ignored |
||||
/caches/ |
||||
/dictionaries/ |
||||
/modules/ |
||||
/libraries/ |
||||
/*.xml |
@ -0,0 +1,125 @@ |
||||
<component name="ProjectCodeStyleConfiguration"> |
||||
<code_scheme name="Project" version="173"> |
||||
<JetCodeStyleSettings> |
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> |
||||
</JetCodeStyleSettings> |
||||
<codeStyleSettings language="XML"> |
||||
<indentOptions> |
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" /> |
||||
</indentOptions> |
||||
<arrangement> |
||||
<rules> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>xmlns:android</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>^$</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>xmlns:.*</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>^$</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
<order>BY_NAME</order> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>.*:id</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>.*:name</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>name</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>^$</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>style</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>^$</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>.*</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>^$</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
<order>BY_NAME</order> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>.*</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
<order>ANDROID_ATTRIBUTE_ORDER</order> |
||||
</rule> |
||||
</section> |
||||
<section> |
||||
<rule> |
||||
<match> |
||||
<AND> |
||||
<NAME>.*</NAME> |
||||
<XML_ATTRIBUTE /> |
||||
<XML_NAMESPACE>.*</XML_NAMESPACE> |
||||
</AND> |
||||
</match> |
||||
<order>BY_NAME</order> |
||||
</rule> |
||||
</section> |
||||
</rules> |
||||
</arrangement> |
||||
</codeStyleSettings> |
||||
<codeStyleSettings language="kotlin"> |
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> |
||||
<indentOptions> |
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" /> |
||||
</indentOptions> |
||||
</codeStyleSettings> |
||||
</code_scheme> |
||||
</component> |
@ -0,0 +1,5 @@ |
||||
<component name="ProjectCodeStyleConfiguration"> |
||||
<state> |
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" /> |
||||
</state> |
||||
</component> |
@ -0,0 +1,20 @@ |
||||
<component name="InspectionProjectProfileManager"> |
||||
<profile version="1.0"> |
||||
<option name="myName" value="Project Default" /> |
||||
<inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true"> |
||||
<option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" /> |
||||
<option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" /> |
||||
</inspection_tool> |
||||
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true"> |
||||
<option name="myValues"> |
||||
<value> |
||||
<list size="1"> |
||||
<item index="0" class="java.lang.String" itemvalue="name" /> |
||||
</list> |
||||
</value> |
||||
</option> |
||||
<option name="myCustomValuesEnabled" value="true" /> |
||||
</inspection_tool> |
||||
<inspection_tool class="NonAsciiCharacters" enabled="false" level="WARNING" enabled_by_default="false" /> |
||||
</profile> |
||||
</component> |
@ -0,0 +1,6 @@ |
||||
<component name="InspectionProjectProfileManager"> |
||||
<settings> |
||||
<option name="USE_PROJECT_PROFILE" value="false" /> |
||||
<version value="1.0" /> |
||||
</settings> |
||||
</component> |
@ -0,0 +1,4 @@ |
||||
**2021/08/09** |
||||
|
||||
1. 修复选择文字不能选择单个文字的bug |
||||
2. |
@ -0,0 +1,674 @@ |
||||
GNU GENERAL PUBLIC LICENSE |
||||
Version 3, 29 June 2007 |
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> |
||||
Everyone is permitted to copy and distribute verbatim copies |
||||
of this license document, but changing it is not allowed. |
||||
|
||||
Preamble |
||||
|
||||
The GNU General Public License is a free, copyleft license for |
||||
software and other kinds of works. |
||||
|
||||
The licenses for most software and other practical works are designed |
||||
to take away your freedom to share and change the works. By contrast, |
||||
the GNU General Public License is intended to guarantee your freedom to |
||||
share and change all versions of a program--to make sure it remains free |
||||
software for all its users. We, the Free Software Foundation, use the |
||||
GNU General Public License for most of our software; it applies also to |
||||
any other work released this way by its authors. You can apply it to |
||||
your programs, too. |
||||
|
||||
When we speak of free software, we are referring to freedom, not |
||||
price. Our General Public Licenses are designed to make sure that you |
||||
have the freedom to distribute copies of free software (and charge for |
||||
them if you wish), that you receive source code or can get it if you |
||||
want it, that you can change the software or use pieces of it in new |
||||
free programs, and that you know you can do these things. |
||||
|
||||
To protect your rights, we need to prevent others from denying you |
||||
these rights or asking you to surrender the rights. Therefore, you have |
||||
certain responsibilities if you distribute copies of the software, or if |
||||
you modify it: responsibilities to respect the freedom of others. |
||||
|
||||
For example, if you distribute copies of such a program, whether |
||||
gratis or for a fee, you must pass on to the recipients the same |
||||
freedoms that you received. You must make sure that they, too, receive |
||||
or can get the source code. And you must show them these terms so they |
||||
know their rights. |
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps: |
||||
(1) assert copyright on the software, and (2) offer you this License |
||||
giving you legal permission to copy, distribute and/or modify it. |
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains |
||||
that there is no warranty for this free software. For both users' and |
||||
authors' sake, the GPL requires that modified versions be marked as |
||||
changed, so that their problems will not be attributed erroneously to |
||||
authors of previous versions. |
||||
|
||||
Some devices are designed to deny users access to install or run |
||||
modified versions of the software inside them, although the manufacturer |
||||
can do so. This is fundamentally incompatible with the aim of |
||||
protecting users' freedom to change the software. The systematic |
||||
pattern of such abuse occurs in the area of products for individuals to |
||||
use, which is precisely where it is most unacceptable. Therefore, we |
||||
have designed this version of the GPL to prohibit the practice for those |
||||
products. If such problems arise substantially in other domains, we |
||||
stand ready to extend this provision to those domains in future versions |
||||
of the GPL, as needed to protect the freedom of users. |
||||
|
||||
Finally, every program is threatened constantly by software patents. |
||||
States should not allow patents to restrict development and use of |
||||
software on general-purpose computers, but in those that do, we wish to |
||||
avoid the special danger that patents applied to a free program could |
||||
make it effectively proprietary. To prevent this, the GPL assures that |
||||
patents cannot be used to render the program non-free. |
||||
|
||||
The precise terms and conditions for copying, distribution and |
||||
modification follow. |
||||
|
||||
TERMS AND CONDITIONS |
||||
|
||||
0. Definitions. |
||||
|
||||
"This License" refers to version 3 of the GNU General Public License. |
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of |
||||
works, such as semiconductor masks. |
||||
|
||||
"The Program" refers to any copyrightable work licensed under this |
||||
License. Each licensee is addressed as "you". "Licensees" and |
||||
"recipients" may be individuals or organizations. |
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work |
||||
in a fashion requiring copyright permission, other than the making of an |
||||
exact copy. The resulting work is called a "modified version" of the |
||||
earlier work or a work "based on" the earlier work. |
||||
|
||||
A "covered work" means either the unmodified Program or a work based |
||||
on the Program. |
||||
|
||||
To "propagate" a work means to do anything with it that, without |
||||
permission, would make you directly or secondarily liable for |
||||
infringement under applicable copyright law, except executing it on a |
||||
computer or modifying a private copy. Propagation includes copying, |
||||
distribution (with or without modification), making available to the |
||||
public, and in some countries other activities as well. |
||||
|
||||
To "convey" a work means any kind of propagation that enables other |
||||
parties to make or receive copies. Mere interaction with a user through |
||||
a computer network, with no transfer of a copy, is not conveying. |
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices" |
||||
to the extent that it includes a convenient and prominently visible |
||||
feature that (1) displays an appropriate copyright notice, and (2) |
||||
tells the user that there is no warranty for the work (except to the |
||||
extent that warranties are provided), that licensees may convey the |
||||
work under this License, and how to view a copy of this License. If |
||||
the interface presents a list of user commands or options, such as a |
||||
menu, a prominent item in the list meets this criterion. |
||||
|
||||
1. Source Code. |
||||
|
||||
The "source code" for a work means the preferred form of the work |
||||
for making modifications to it. "Object code" means any non-source |
||||
form of a work. |
||||
|
||||
A "Standard Interface" means an interface that either is an official |
||||
standard defined by a recognized standards body, or, in the case of |
||||
interfaces specified for a particular programming language, one that |
||||
is widely used among developers working in that language. |
||||
|
||||
The "System Libraries" of an executable work include anything, other |
||||
than the work as a whole, that (a) is included in the normal form of |
||||
packaging a Major Component, but which is not part of that Major |
||||
Component, and (b) serves only to enable use of the work with that |
||||
Major Component, or to implement a Standard Interface for which an |
||||
implementation is available to the public in source code form. A |
||||
"Major Component", in this context, means a major essential component |
||||
(kernel, window system, and so on) of the specific operating system |
||||
(if any) on which the executable work runs, or a compiler used to |
||||
produce the work, or an object code interpreter used to run it. |
||||
|
||||
The "Corresponding Source" for a work in object code form means all |
||||
the source code needed to generate, install, and (for an executable |
||||
work) run the object code and to modify the work, including scripts to |
||||
control those activities. However, it does not include the work's |
||||
System Libraries, or general-purpose tools or generally available free |
||||
programs which are used unmodified in performing those activities but |
||||
which are not part of the work. For example, Corresponding Source |
||||
includes interface definition files associated with source files for |
||||
the work, and the source code for shared libraries and dynamically |
||||
linked subprograms that the work is specifically designed to require, |
||||
such as by intimate data communication or control flow between those |
||||
subprograms and other parts of the work. |
||||
|
||||
The Corresponding Source need not include anything that users |
||||
can regenerate automatically from other parts of the Corresponding |
||||
Source. |
||||
|
||||
The Corresponding Source for a work in source code form is that |
||||
same work. |
||||
|
||||
2. Basic Permissions. |
||||
|
||||
All rights granted under this License are granted for the term of |
||||
copyright on the Program, and are irrevocable provided the stated |
||||
conditions are met. This License explicitly affirms your unlimited |
||||
permission to run the unmodified Program. The output from running a |
||||
covered work is covered by this License only if the output, given its |
||||
content, constitutes a covered work. This License acknowledges your |
||||
rights of fair use or other equivalent, as provided by copyright law. |
||||
|
||||
You may make, run and propagate covered works that you do not |
||||
convey, without conditions so long as your license otherwise remains |
||||
in force. You may convey covered works to others for the sole purpose |
||||
of having them make modifications exclusively for you, or provide you |
||||
with facilities for running those works, provided that you comply with |
||||
the terms of this License in conveying all material for which you do |
||||
not control copyright. Those thus making or running the covered works |
||||
for you must do so exclusively on your behalf, under your direction |
||||
and control, on terms that prohibit them from making any copies of |
||||
your copyrighted material outside their relationship with you. |
||||
|
||||
Conveying under any other circumstances is permitted solely under |
||||
the conditions stated below. Sublicensing is not allowed; section 10 |
||||
makes it unnecessary. |
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
||||
|
||||
No covered work shall be deemed part of an effective technological |
||||
measure under any applicable law fulfilling obligations under article |
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or |
||||
similar laws prohibiting or restricting circumvention of such |
||||
measures. |
||||
|
||||
When you convey a covered work, you waive any legal power to forbid |
||||
circumvention of technological measures to the extent such circumvention |
||||
is effected by exercising rights under this License with respect to |
||||
the covered work, and you disclaim any intention to limit operation or |
||||
modification of the work as a means of enforcing, against the work's |
||||
users, your or third parties' legal rights to forbid circumvention of |
||||
technological measures. |
||||
|
||||
4. Conveying Verbatim Copies. |
||||
|
||||
You may convey verbatim copies of the Program's source code as you |
||||
receive it, in any medium, provided that you conspicuously and |
||||
appropriately publish on each copy an appropriate copyright notice; |
||||
keep intact all notices stating that this License and any |
||||
non-permissive terms added in accord with section 7 apply to the code; |
||||
keep intact all notices of the absence of any warranty; and give all |
||||
recipients a copy of this License along with the Program. |
||||
|
||||
You may charge any price or no price for each copy that you convey, |
||||
and you may offer support or warranty protection for a fee. |
||||
|
||||
5. Conveying Modified Source Versions. |
||||
|
||||
You may convey a work based on the Program, or the modifications to |
||||
produce it from the Program, in the form of source code under the |
||||
terms of section 4, provided that you also meet all of these conditions: |
||||
|
||||
a) The work must carry prominent notices stating that you modified |
||||
it, and giving a relevant date. |
||||
|
||||
b) The work must carry prominent notices stating that it is |
||||
released under this License and any conditions added under section |
||||
7. This requirement modifies the requirement in section 4 to |
||||
"keep intact all notices". |
||||
|
||||
c) You must license the entire work, as a whole, under this |
||||
License to anyone who comes into possession of a copy. This |
||||
License will therefore apply, along with any applicable section 7 |
||||
additional terms, to the whole of the work, and all its parts, |
||||
regardless of how they are packaged. This License gives no |
||||
permission to license the work in any other way, but it does not |
||||
invalidate such permission if you have separately received it. |
||||
|
||||
d) If the work has interactive user interfaces, each must display |
||||
Appropriate Legal Notices; however, if the Program has interactive |
||||
interfaces that do not display Appropriate Legal Notices, your |
||||
work need not make them do so. |
||||
|
||||
A compilation of a covered work with other separate and independent |
||||
works, which are not by their nature extensions of the covered work, |
||||
and which are not combined with it such as to form a larger program, |
||||
in or on a volume of a storage or distribution medium, is called an |
||||
"aggregate" if the compilation and its resulting copyright are not |
||||
used to limit the access or legal rights of the compilation's users |
||||
beyond what the individual works permit. Inclusion of a covered work |
||||
in an aggregate does not cause this License to apply to the other |
||||
parts of the aggregate. |
||||
|
||||
6. Conveying Non-Source Forms. |
||||
|
||||
You may convey a covered work in object code form under the terms |
||||
of sections 4 and 5, provided that you also convey the |
||||
machine-readable Corresponding Source under the terms of this License, |
||||
in one of these ways: |
||||
|
||||
a) Convey the object code in, or embodied in, a physical product |
||||
(including a physical distribution medium), accompanied by the |
||||
Corresponding Source fixed on a durable physical medium |
||||
customarily used for software interchange. |
||||
|
||||
b) Convey the object code in, or embodied in, a physical product |
||||
(including a physical distribution medium), accompanied by a |
||||
written offer, valid for at least three years and valid for as |
||||
long as you offer spare parts or customer support for that product |
||||
model, to give anyone who possesses the object code either (1) a |
||||
copy of the Corresponding Source for all the software in the |
||||
product that is covered by this License, on a durable physical |
||||
medium customarily used for software interchange, for a price no |
||||
more than your reasonable cost of physically performing this |
||||
conveying of source, or (2) access to copy the |
||||
Corresponding Source from a network server at no charge. |
||||
|
||||
c) Convey individual copies of the object code with a copy of the |
||||
written offer to provide the Corresponding Source. This |
||||
alternative is allowed only occasionally and noncommercially, and |
||||
only if you received the object code with such an offer, in accord |
||||
with subsection 6b. |
||||
|
||||
d) Convey the object code by offering access from a designated |
||||
place (gratis or for a charge), and offer equivalent access to the |
||||
Corresponding Source in the same way through the same place at no |
||||
further charge. You need not require recipients to copy the |
||||
Corresponding Source along with the object code. If the place to |
||||
copy the object code is a network server, the Corresponding Source |
||||
may be on a different server (operated by you or a third party) |
||||
that supports equivalent copying facilities, provided you maintain |
||||
clear directions next to the object code saying where to find the |
||||
Corresponding Source. Regardless of what server hosts the |
||||
Corresponding Source, you remain obligated to ensure that it is |
||||
available for as long as needed to satisfy these requirements. |
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided |
||||
you inform other peers where the object code and Corresponding |
||||
Source of the work are being offered to the general public at no |
||||
charge under subsection 6d. |
||||
|
||||
A separable portion of the object code, whose source code is excluded |
||||
from the Corresponding Source as a System Library, need not be |
||||
included in conveying the object code work. |
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any |
||||
tangible personal property which is normally used for personal, family, |
||||
or household purposes, or (2) anything designed or sold for incorporation |
||||
into a dwelling. In determining whether a product is a consumer product, |
||||
doubtful cases shall be resolved in favor of coverage. For a particular |
||||
product received by a particular user, "normally used" refers to a |
||||
typical or common use of that class of product, regardless of the status |
||||
of the particular user or of the way in which the particular user |
||||
actually uses, or expects or is expected to use, the product. A product |
||||
is a consumer product regardless of whether the product has substantial |
||||
commercial, industrial or non-consumer uses, unless such uses represent |
||||
the only significant mode of use of the product. |
||||
|
||||
"Installation Information" for a User Product means any methods, |
||||
procedures, authorization keys, or other information required to install |
||||
and execute modified versions of a covered work in that User Product from |
||||
a modified version of its Corresponding Source. The information must |
||||
suffice to ensure that the continued functioning of the modified object |
||||
code is in no case prevented or interfered with solely because |
||||
modification has been made. |
||||
|
||||
If you convey an object code work under this section in, or with, or |
||||
specifically for use in, a User Product, and the conveying occurs as |
||||
part of a transaction in which the right of possession and use of the |
||||
User Product is transferred to the recipient in perpetuity or for a |
||||
fixed term (regardless of how the transaction is characterized), the |
||||
Corresponding Source conveyed under this section must be accompanied |
||||
by the Installation Information. But this requirement does not apply |
||||
if neither you nor any third party retains the ability to install |
||||
modified object code on the User Product (for example, the work has |
||||
been installed in ROM). |
||||
|
||||
The requirement to provide Installation Information does not include a |
||||
requirement to continue to provide support service, warranty, or updates |
||||
for a work that has been modified or installed by the recipient, or for |
||||
the User Product in which it has been modified or installed. Access to a |
||||
network may be denied when the modification itself materially and |
||||
adversely affects the operation of the network or violates the rules and |
||||
protocols for communication across the network. |
||||
|
||||
Corresponding Source conveyed, and Installation Information provided, |
||||
in accord with this section must be in a format that is publicly |
||||
documented (and with an implementation available to the public in |
||||
source code form), and must require no special password or key for |
||||
unpacking, reading or copying. |
||||
|
||||
7. Additional Terms. |
||||
|
||||
"Additional permissions" are terms that supplement the terms of this |
||||
License by making exceptions from one or more of its conditions. |
||||
Additional permissions that are applicable to the entire Program shall |
||||
be treated as though they were included in this License, to the extent |
||||
that they are valid under applicable law. If additional permissions |
||||
apply only to part of the Program, that part may be used separately |
||||
under those permissions, but the entire Program remains governed by |
||||
this License without regard to the additional permissions. |
||||
|
||||
When you convey a copy of a covered work, you may at your option |
||||
remove any additional permissions from that copy, or from any part of |
||||
it. (Additional permissions may be written to require their own |
||||
removal in certain cases when you modify the work.) You may place |
||||
additional permissions on material, added by you to a covered work, |
||||
for which you have or can give appropriate copyright permission. |
||||
|
||||
Notwithstanding any other provision of this License, for material you |
||||
add to a covered work, you may (if authorized by the copyright holders of |
||||
that material) supplement the terms of this License with terms: |
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the |
||||
terms of sections 15 and 16 of this License; or |
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or |
||||
author attributions in that material or in the Appropriate Legal |
||||
Notices displayed by works containing it; or |
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or |
||||
requiring that modified versions of such material be marked in |
||||
reasonable ways as different from the original version; or |
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or |
||||
authors of the material; or |
||||
|
||||
e) Declining to grant rights under trademark law for use of some |
||||
trade names, trademarks, or service marks; or |
||||
|
||||
f) Requiring indemnification of licensors and authors of that |
||||
material by anyone who conveys the material (or modified versions of |
||||
it) with contractual assumptions of liability to the recipient, for |
||||
any liability that these contractual assumptions directly impose on |
||||
those licensors and authors. |
||||
|
||||
All other non-permissive additional terms are considered "further |
||||
restrictions" within the meaning of section 10. If the Program as you |
||||
received it, or any part of it, contains a notice stating that it is |
||||
governed by this License along with a term that is a further |
||||
restriction, you may remove that term. If a license document contains |
||||
a further restriction but permits relicensing or conveying under this |
||||
License, you may add to a covered work material governed by the terms |
||||
of that license document, provided that the further restriction does |
||||
not survive such relicensing or conveying. |
||||
|
||||
If you add terms to a covered work in accord with this section, you |
||||
must place, in the relevant source files, a statement of the |
||||
additional terms that apply to those files, or a notice indicating |
||||
where to find the applicable terms. |
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the |
||||
form of a separately written license, or stated as exceptions; |
||||
the above requirements apply either way. |
||||
|
||||
8. Termination. |
||||
|
||||
You may not propagate or modify a covered work except as expressly |
||||
provided under this License. Any attempt otherwise to propagate or |
||||
modify it is void, and will automatically terminate your rights under |
||||
this License (including any patent licenses granted under the third |
||||
paragraph of section 11). |
||||
|
||||
However, if you cease all violation of this License, then your |
||||
license from a particular copyright holder is reinstated (a) |
||||
provisionally, unless and until the copyright holder explicitly and |
||||
finally terminates your license, and (b) permanently, if the copyright |
||||
holder fails to notify you of the violation by some reasonable means |
||||
prior to 60 days after the cessation. |
||||
|
||||
Moreover, your license from a particular copyright holder is |
||||
reinstated permanently if the copyright holder notifies you of the |
||||
violation by some reasonable means, this is the first time you have |
||||
received notice of violation of this License (for any work) from that |
||||
copyright holder, and you cure the violation prior to 30 days after |
||||
your receipt of the notice. |
||||
|
||||
Termination of your rights under this section does not terminate the |
||||
licenses of parties who have received copies or rights from you under |
||||
this License. If your rights have been terminated and not permanently |
||||
reinstated, you do not qualify to receive new licenses for the same |
||||
material under section 10. |
||||
|
||||
9. Acceptance Not Required for Having Copies. |
||||
|
||||
You are not required to accept this License in order to receive or |
||||
run a copy of the Program. Ancillary propagation of a covered work |
||||
occurring solely as a consequence of using peer-to-peer transmission |
||||
to receive a copy likewise does not require acceptance. However, |
||||
nothing other than this License grants you permission to propagate or |
||||
modify any covered work. These actions infringe copyright if you do |
||||
not accept this License. Therefore, by modifying or propagating a |
||||
covered work, you indicate your acceptance of this License to do so. |
||||
|
||||
10. Automatic Licensing of Downstream Recipients. |
||||
|
||||
Each time you convey a covered work, the recipient automatically |
||||
receives a license from the original licensors, to run, modify and |
||||
propagate that work, subject to this License. You are not responsible |
||||
for enforcing compliance by third parties with this License. |
||||
|
||||
An "entity transaction" is a transaction transferring control of an |
||||
organization, or substantially all assets of one, or subdividing an |
||||
organization, or merging organizations. If propagation of a covered |
||||
work results from an entity transaction, each party to that |
||||
transaction who receives a copy of the work also receives whatever |
||||
licenses to the work the party's predecessor in interest had or could |
||||
give under the previous paragraph, plus a right to possession of the |
||||
Corresponding Source of the work from the predecessor in interest, if |
||||
the predecessor has it or can get it with reasonable efforts. |
||||
|
||||
You may not impose any further restrictions on the exercise of the |
||||
rights granted or affirmed under this License. For example, you may |
||||
not impose a license fee, royalty, or other charge for exercise of |
||||
rights granted under this License, and you may not initiate litigation |
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that |
||||
any patent claim is infringed by making, using, selling, offering for |
||||
sale, or importing the Program or any portion of it. |
||||
|
||||
11. Patents. |
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this |
||||
License of the Program or a work on which the Program is based. The |
||||
work thus licensed is called the contributor's "contributor version". |
||||
|
||||
A contributor's "essential patent claims" are all patent claims |
||||
owned or controlled by the contributor, whether already acquired or |
||||
hereafter acquired, that would be infringed by some manner, permitted |
||||
by this License, of making, using, or selling its contributor version, |
||||
but do not include claims that would be infringed only as a |
||||
consequence of further modification of the contributor version. For |
||||
purposes of this definition, "control" includes the right to grant |
||||
patent sublicenses in a manner consistent with the requirements of |
||||
this License. |
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free |
||||
patent license under the contributor's essential patent claims, to |
||||
make, use, sell, offer for sale, import and otherwise run, modify and |
||||
propagate the contents of its contributor version. |
||||
|
||||
In the following three paragraphs, a "patent license" is any express |
||||
agreement or commitment, however denominated, not to enforce a patent |
||||
(such as an express permission to practice a patent or covenant not to |
||||
sue for patent infringement). To "grant" such a patent license to a |
||||
party means to make such an agreement or commitment not to enforce a |
||||
patent against the party. |
||||
|
||||
If you convey a covered work, knowingly relying on a patent license, |
||||
and the Corresponding Source of the work is not available for anyone |
||||
to copy, free of charge and under the terms of this License, through a |
||||
publicly available network server or other readily accessible means, |
||||
then you must either (1) cause the Corresponding Source to be so |
||||
available, or (2) arrange to deprive yourself of the benefit of the |
||||
patent license for this particular work, or (3) arrange, in a manner |
||||
consistent with the requirements of this License, to extend the patent |
||||
license to downstream recipients. "Knowingly relying" means you have |
||||
actual knowledge that, but for the patent license, your conveying the |
||||
covered work in a country, or your recipient's use of the covered work |
||||
in a country, would infringe one or more identifiable patents in that |
||||
country that you have reason to believe are valid. |
||||
|
||||
If, pursuant to or in connection with a single transaction or |
||||
arrangement, you convey, or propagate by procuring conveyance of, a |
||||
covered work, and grant a patent license to some of the parties |
||||
receiving the covered work authorizing them to use, propagate, modify |
||||
or convey a specific copy of the covered work, then the patent license |
||||
you grant is automatically extended to all recipients of the covered |
||||
work and works based on it. |
||||
|
||||
A patent license is "discriminatory" if it does not include within |
||||
the scope of its coverage, prohibits the exercise of, or is |
||||
conditioned on the non-exercise of one or more of the rights that are |
||||
specifically granted under this License. You may not convey a covered |
||||
work if you are a party to an arrangement with a third party that is |
||||
in the business of distributing software, under which you make payment |
||||
to the third party based on the extent of your activity of conveying |
||||
the work, and under which the third party grants, to any of the |
||||
parties who would receive the covered work from you, a discriminatory |
||||
patent license (a) in connection with copies of the covered work |
||||
conveyed by you (or copies made from those copies), or (b) primarily |
||||
for and in connection with specific products or compilations that |
||||
contain the covered work, unless you entered into that arrangement, |
||||
or that patent license was granted, prior to 28 March 2007. |
||||
|
||||
Nothing in this License shall be construed as excluding or limiting |
||||
any implied license or other defenses to infringement that may |
||||
otherwise be available to you under applicable patent law. |
||||
|
||||
12. No Surrender of Others' Freedom. |
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or |
||||
otherwise) that contradict the conditions of this License, they do not |
||||
excuse you from the conditions of this License. If you cannot convey a |
||||
covered work so as to satisfy simultaneously your obligations under this |
||||
License and any other pertinent obligations, then as a consequence you may |
||||
not convey it at all. For example, if you agree to terms that obligate you |
||||
to collect a royalty for further conveying from those to whom you convey |
||||
the Program, the only way you could satisfy both those terms and this |
||||
License would be to refrain entirely from conveying the Program. |
||||
|
||||
13. Use with the GNU Affero General Public License. |
||||
|
||||
Notwithstanding any other provision of this License, you have |
||||
permission to link or combine any covered work with a work licensed |
||||
under version 3 of the GNU Affero General Public License into a single |
||||
combined work, and to convey the resulting work. The terms of this |
||||
License will continue to apply to the part which is the covered work, |
||||
but the special requirements of the GNU Affero General Public License, |
||||
section 13, concerning interaction through a network will apply to the |
||||
combination as such. |
||||
|
||||
14. Revised Versions of this License. |
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of |
||||
the GNU General Public License from time to time. Such new versions will |
||||
be similar in spirit to the present version, but may differ in detail to |
||||
address new problems or concerns. |
||||
|
||||
Each version is given a distinguishing version number. If the |
||||
Program specifies that a certain numbered version of the GNU General |
||||
Public License "or any later version" applies to it, you have the |
||||
option of following the terms and conditions either of that numbered |
||||
version or of any later version published by the Free Software |
||||
Foundation. If the Program does not specify a version number of the |
||||
GNU General Public License, you may choose any version ever published |
||||
by the Free Software Foundation. |
||||
|
||||
If the Program specifies that a proxy can decide which future |
||||
versions of the GNU General Public License can be used, that proxy's |
||||
public statement of acceptance of a version permanently authorizes you |
||||
to choose that version for the Program. |
||||
|
||||
Later license versions may give you additional or different |
||||
permissions. However, no additional obligations are imposed on any |
||||
author or copyright holder as a result of your choosing to follow a |
||||
later version. |
||||
|
||||
15. Disclaimer of Warranty. |
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY |
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT |
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY |
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM |
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF |
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
||||
|
||||
16. Limitation of Liability. |
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS |
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY |
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE |
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF |
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD |
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), |
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF |
||||
SUCH DAMAGES. |
||||
|
||||
17. Interpretation of Sections 15 and 16. |
||||
|
||||
If the disclaimer of warranty and limitation of liability provided |
||||
above cannot be given local legal effect according to their terms, |
||||
reviewing courts shall apply local law that most closely approximates |
||||
an absolute waiver of all civil liability in connection with the |
||||
Program, unless a warranty or assumption of liability accompanies a |
||||
copy of the Program in return for a fee. |
||||
|
||||
END OF TERMS AND CONDITIONS |
||||
|
||||
How to Apply These Terms to Your New Programs |
||||
|
||||
If you develop a new program, and you want it to be of the greatest |
||||
possible use to the public, the best way to achieve this is to make it |
||||
free software which everyone can redistribute and change under these terms. |
||||
|
||||
To do so, attach the following notices to the program. It is safest |
||||
to attach them to the start of each source file to most effectively |
||||
state the exclusion of warranty; and each file should have at least |
||||
the "copyright" line and a pointer to where the full notice is found. |
||||
|
||||
<one line to give the program's name and a brief idea of what it does.> |
||||
Copyright (C) <year> <name of author> |
||||
|
||||
This program is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
||||
Also add information on how to contact you by electronic and paper mail. |
||||
|
||||
If the program does terminal interaction, make it output a short |
||||
notice like this when it starts in an interactive mode: |
||||
|
||||
<program> Copyright (C) <year> <name of author> |
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
||||
This is free software, and you are welcome to redistribute it |
||||
under certain conditions; type `show c' for details. |
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate |
||||
parts of the General Public License. Of course, your program's commands |
||||
might be different; for a GUI interface, you would use an "about box". |
||||
|
||||
You should also get your employer (if you work as a programmer) or school, |
||||
if any, to sign a "copyright disclaimer" for the program, if necessary. |
||||
For more information on this, and how to apply and follow the GNU GPL, see |
||||
<https://www.gnu.org/licenses/>. |
||||
|
||||
The GNU General Public License does not permit incorporating your program |
||||
into proprietary programs. If your program is a subroutine library, you |
||||
may consider it more useful to permit linking proprietary applications with |
||||
the library. If this is what you want to do, use the GNU Lesser General |
||||
Public License instead of this License. But first, please read |
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>. |
@ -0,0 +1,130 @@ |
||||
[![icon_android](https://github.com/gedoor/gedoor.github.io/blob/master/images/icon_android.png)](https://play.google.com/store/apps/details?id=io.legado.play.release) |
||||
<a href="https://data.newrank.cn/m/s.html?s=NykyOzI9MS5LNQ%3D%3D" target="_blank"> |
||||
<img src="https://img.shields.io/badge/-微信关注“开源阅读”公众号-orange.svg" alt="#" align="right"> |
||||
</a> |
||||
|
||||
<div align="center"> |
||||
<img width="125" height="125" src="https://github.com/gedoor/legado/raw/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png" alt="legado"/> |
||||
|
||||
Legado / 开源阅读 |
||||
<br> |
||||
<a href="https://gedoor.github.io" target="_blank">gedoor.github.io</a> / <a href="https://www.legado.top/" target="_blank">legado.top</a> |
||||
<br> |
||||
Legado is a free and open source novel reader for Android. |
||||
</div> |
||||
|
||||
[![](https://img.shields.io/badge/-Contents:-696969.svg)](#contents) [![](https://img.shields.io/badge/-Function-F5F5F5.svg)](#Function-主要功能-) [![](https://img.shields.io/badge/-Download-F5F5F5.svg)](#Download-下载-) [![](https://img.shields.io/badge/-Community-F5F5F5.svg)](#Community-交流社区-) [![](https://img.shields.io/badge/-API-F5F5F5.svg)](#API-) [![](https://img.shields.io/badge/-Other-F5F5F5.svg)](#Other-其他-) [![](https://img.shields.io/badge/-Grateful-F5F5F5.svg)](#Grateful-感谢-) [![](https://img.shields.io/badge/-Interface-F5F5F5.svg)](#Interface-界面-) |
||||
|
||||
>新用户? |
||||
> |
||||
>软件不提供内容,需要您自己手动添加,例如导入书源等。 |
||||
>看看 [官方帮助文档](https://www.yuque.com/legado/wiki),也许里面就有你要的答案。 |
||||
|
||||
# Function-主要功能 [![](https://img.shields.io/badge/-Function-F5F5F5.svg)](#Function-主要功能-) |
||||
<details><summary>English</summary> |
||||
1. Online reading from a variety of sources.<br> |
||||
2. Local reading of downloaded content.<br> |
||||
3. A configurable reader with multiple viewers, reading directions and other settings. <br> |
||||
4. Categories to organize your library.<br> |
||||
5. Light and dark themes.<br> |
||||
6. Schedule updating your library for new chapters.<br> |
||||
7. read offline or to your desired cloud service |
||||
</details> |
||||
|
||||
<details><summary>中文</summary> |
||||
1.自定义书源,自己设置规则,抓取网页数据,规则简单易懂,软件内有规则说明。<br> |
||||
2.列表书架,网格书架自由切换。<br> |
||||
3.书源规则支持搜索及发现,所有找书看书功能全部自定义,找书更方便。<br> |
||||
4.订阅内容,可以订阅想看的任何内容,看你想看<br> |
||||
5.支持替换净化,去除广告替换内容很方便。<br> |
||||
6.支持本地TXT、EPUB阅读,手动浏览,智能扫描。<br> |
||||
7.支持高度自定义阅读界面,切换字体、颜色、背景、行距、段距、加粗、简繁转换等。<br> |
||||
8.支持多种翻页模式,覆盖、仿真、滑动、滚动等。<br> |
||||
9.软件开源,持续优化,无广告。 |
||||
</details> |
||||
|
||||
<a href="#readme"> |
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right"> |
||||
</a> |
||||
|
||||
# Download-下载 [![](https://img.shields.io/badge/-Download-F5F5F5.svg)](#Download-下载-) |
||||
#### Android-安卓 |
||||
* [Releases](https://github.com/gedoor/legado/releases/latest) |
||||
* [Google play - $1.99](https://play.google.com/store/apps/details?id=io.legado.play.release) |
||||
* [Coolapk](https://www.coolapk.com/apk/io.legado.app.release) |
||||
* [Jsdelivr](https://cdn.jsdelivr.net/gh/gedoor/legado@release/) |
||||
* [\#Beta](https://kunfei.lanzoui.com/b0f810h4b) |
||||
|
||||
|
||||
#### IOS-苹果 |
||||
* 准备中(No release) - [Github](https://github.com/gedoor/YueDuFlutter) |
||||
|
||||
<a href="#readme"> |
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right"> |
||||
</a> |
||||
|
||||
# Community-交流社区 [![](https://img.shields.io/badge/-Community-F5F5F5.svg)](#Community-交流社区-) |
||||
|
||||
#### Telegram |
||||
[![Telegram-group](https://img.shields.io/badge/Telegram-%E7%BE%A4%E7%BB%84-blue)](https://t.me/yueduguanfang) [![Telegram-channel](https://img.shields.io/badge/Telegram-%E9%A2%91%E9%81%93-blue)](https://t.me/legado_channels) |
||||
|
||||
#### Discord |
||||
[![Discord](https://img.shields.io/discord/560731361414086666?color=%235865f2&label=Discord)](https://discord.gg/VtUfRyzRXn) |
||||
|
||||
#### Other |
||||
https://www.yuque.com/legado/wiki/community |
||||
|
||||
<a href="#readme"> |
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right"> |
||||
</a> |
||||
|
||||
# API [![](https://img.shields.io/badge/-API-F5F5F5.svg)](#API-) |
||||
* 阅读3.0 提供了2种方式的API:`Web方式`和`Content Provider方式`。您可以在[这里](api.md)根据需要自行调用。 |
||||
* 可通过url唤起阅读进行一键导入,url格式: legado://import/{path}?src={url} |
||||
* path类型: bookSource,rssSource,replaceRule,textTocRule,httpTTS,theme,readConfig |
||||
* path类型解释: 书源,订阅源,替换规则,本地txt小说目录规则,在线朗读引擎,主题,阅读排版 |
||||
|
||||
<a href="#readme"> |
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right"> |
||||
</a> |
||||
|
||||
# Other-其他 [![](https://img.shields.io/badge/-Other-F5F5F5.svg)](#Other-其他-) |
||||
##### 免责声明 |
||||
https://gedoor.github.io/about.html |
||||
##### 阅读3.0 |
||||
* [书源规则](https://alanskycn.gitee.io/teachme) |
||||
* [更新日志](/app/src/main/assets/updateLog.md) |
||||
* [帮助文档](/app/src/main/assets/help/appHelp.md) |
||||
* [web端](https://github.com/celetor/web-yuedu3) |
||||
|
||||
<a href="#readme"> |
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right"> |
||||
</a> |
||||
|
||||
# Grateful-感谢 [![](https://img.shields.io/badge/-Grateful-F5F5F5.svg)](#Grateful-感谢-) |
||||
> * org.jsoup:jsoup |
||||
> * cn.wanghaomiao:JsoupXpath |
||||
> * com.jayway.jsonpath:json-path |
||||
> * com.github.gedoor:rhino-android |
||||
> * com.squareup.okhttp3:okhttp |
||||
> * com.github.bumptech.glide:glide |
||||
> * org.nanohttpd:nanohttpd |
||||
> * org.nanohttpd:nanohttpd-websocket |
||||
> * cn.bingoogolapple:bga-qrcode-zxing |
||||
> * com.jaredrummler:colorpicker |
||||
> * org.apache.commons:commons-text |
||||
> * io.noties.markwon:core |
||||
> * io.noties.markwon:image-glide |
||||
> * com.hankcs:hanlp |
||||
> * com.positiondev.epublib:epublib-core |
||||
<a href="#readme"> |
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right"> |
||||
</a> |
||||
|
||||
# Interface-界面 [![](https://img.shields.io/badge/-Interface-F5F5F5.svg)](#Interface-界面-) |
||||
<img src="https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B1.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B2.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B3.jpg" width="270"> |
||||
<img src="https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B4.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B5.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B6.jpg" width="270"> |
||||
|
||||
<a href="#readme"> |
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right"> |
||||
</a> |
@ -0,0 +1,194 @@ |
||||
# 阅读API |
||||
## 对于Web的配置 |
||||
您需要先在设置中启用"Web 服务"。 |
||||
## 使用 |
||||
### Web |
||||
以下说明假设您的操作在本机进行,且开放端口为1234。 |
||||
如果您要从远程计算机访问[阅读](),请将`127.0.0.1`替换成手机IP。 |
||||
#### 插入单个书源 |
||||
``` |
||||
URL = http://127.0.0.1:1234/saveSource |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt) |
||||
|
||||
#### 插入多个书源or订阅源 |
||||
|
||||
``` |
||||
URL = http://127.0.0.1:1234/saveBookSources |
||||
URL = http://127.0.0.1:1234/saveRssSources |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 获取书源 |
||||
|
||||
``` |
||||
URL = http://127.0.0.1:1234/getBookSource?url=xxx |
||||
URL = http://127.0.0.1:1234/getRssSource?url=xxx |
||||
Method = GET |
||||
``` |
||||
|
||||
#### 获取所有书源or订阅源 |
||||
|
||||
``` |
||||
URL = http://127.0.0.1:1234/getBookSources |
||||
URL = http://127.0.0.1:1234/getRssSources |
||||
Method = GET |
||||
``` |
||||
|
||||
#### 删除多个书源or订阅源 |
||||
|
||||
``` |
||||
URL = http://127.0.0.1:1234/deleteBookSources |
||||
URL = http://127.0.0.1:1234/deleteRssSources |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 插入书籍 |
||||
``` |
||||
URL = http://127.0.0.1:1234/saveBook |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/Book.kt)。 |
||||
|
||||
#### 获取所有书籍 |
||||
``` |
||||
URL = http://127.0.0.1:1234/getBookshelf |
||||
Method = GET |
||||
``` |
||||
|
||||
获取APP内的所有书籍。 |
||||
|
||||
#### 获取书籍章节列表 |
||||
``` |
||||
URL = http://127.0.0.1:1234/getChapterList?url=xxx |
||||
Method = GET |
||||
``` |
||||
|
||||
获取指定图书的章节列表。 |
||||
|
||||
#### 获取书籍内容 |
||||
``` |
||||
URL = http://127.0.0.1:1234/getBookContent?url=xxx&index=1 |
||||
Method = GET |
||||
``` |
||||
获取指定图书的第`index`章节的文本内容。 |
||||
|
||||
#### 获取封面 |
||||
``` |
||||
URL = http://127.0.0.1:1234/cover?path=xxxxx |
||||
Method = GET |
||||
``` |
||||
|
||||
|
||||
### Content Provider |
||||
* 需声明`io.legado.READ_WRITE`权限 |
||||
* `providerHost`为`包名.readerProvider`, 如`io.legado.app.release.readerProvider`,不同包的地址不同,防止冲突安装失败 |
||||
* 以下出现的`providerHost`请自行替换 |
||||
|
||||
#### 插入单个书源or订阅源 |
||||
|
||||
``` |
||||
URL = content://providerHost/bookSource/insert |
||||
URL = content://providerHost/rssSource/insert |
||||
Method = insert |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt) |
||||
|
||||
#### 插入多个书源or订阅源 |
||||
|
||||
``` |
||||
URL = content://providerHost/bookSources/insert |
||||
URL = content://providerHost/rssSources/insert |
||||
Method = insert |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 获取书源or订阅源 |
||||
|
||||
``` |
||||
URL = content://providerHost/bookSource/query?url=xxx |
||||
URL = content://providerHost/rssSource/query?url=xxx |
||||
Method = query |
||||
``` |
||||
|
||||
获取指定URL对应的书源信息。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 获取所有书源or订阅源 |
||||
|
||||
``` |
||||
URL = content://providerHost/bookSources/query |
||||
URL = content://providerHost/rssSources/query |
||||
Method = query |
||||
``` |
||||
|
||||
获取APP内的所有书源。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 删除多个书源or订阅源 |
||||
|
||||
``` |
||||
URL = content://providerHost/bookSources/delete |
||||
URL = content://providerHost/rssSources/delete |
||||
Method = delete |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 插入书籍 |
||||
``` |
||||
URL = content://providerHost/book/insert |
||||
Method = insert |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/Book.kt)。 |
||||
|
||||
#### 获取所有书籍 |
||||
``` |
||||
URL = content://providerHost/books/query |
||||
Method = query |
||||
``` |
||||
|
||||
获取APP内的所有书籍。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 获取书籍章节列表 |
||||
``` |
||||
URL = content://providerHost/book/chapter/query?url=xxx |
||||
Method = query |
||||
``` |
||||
|
||||
获取指定图书的章节列表。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 获取书籍内容 |
||||
|
||||
``` |
||||
URL = content://providerHost/book/content/query?url=xxx&index=1 |
||||
Method = query |
||||
``` |
||||
获取指定图书的第`index`章节的文本内容。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 获取封面 |
||||
``` |
||||
URL = content://providerHost/book/cover/query?path=xxxx |
||||
Method = query |
||||
``` |
@ -0,0 +1,2 @@ |
||||
/build |
||||
/so |
@ -0,0 +1,227 @@ |
||||
apply plugin: 'com.android.application' |
||||
apply plugin: 'kotlin-android' |
||||
apply plugin: 'kotlin-parcelize' |
||||
apply plugin: 'kotlin-kapt' |
||||
apply plugin: 'de.timfreiheit.resourceplaceholders' |
||||
apply from: 'download.gradle' |
||||
|
||||
static def releaseTime() { |
||||
return new Date().format("yy.MMddHH", TimeZone.getTimeZone("GMT+8")) |
||||
} |
||||
|
||||
def name = "legado" |
||||
def version = "3." + releaseTime() |
||||
def gitCommits = Integer.parseInt('git rev-list --count HEAD'.execute([], project.rootDir).text.trim()) |
||||
|
||||
android { |
||||
compileSdkVersion 32 |
||||
buildToolsVersion '32.0.0' |
||||
kotlinOptions { |
||||
jvmTarget = "11" |
||||
} |
||||
signingConfigs { |
||||
if (project.hasProperty("RELEASE_STORE_FILE")) { |
||||
myConfig { |
||||
storeFile file(RELEASE_STORE_FILE) |
||||
storePassword RELEASE_STORE_PASSWORD |
||||
keyAlias RELEASE_KEY_ALIAS |
||||
keyPassword RELEASE_KEY_PASSWORD |
||||
v1SigningEnabled true |
||||
v2SigningEnabled true |
||||
} |
||||
} |
||||
} |
||||
defaultConfig { |
||||
applicationId "io.legado.app" |
||||
minSdkVersion 21 |
||||
targetSdkVersion 32 |
||||
versionCode gitCommits |
||||
versionName version |
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" |
||||
project.ext.set("archivesBaseName", name + "_" + version) |
||||
multiDexEnabled true |
||||
|
||||
javaCompileOptions { |
||||
annotationProcessorOptions { |
||||
arguments += [ |
||||
"room.incremental" : "true", |
||||
"room.expandProjection": "true", |
||||
"room.schemaLocation" : "$projectDir/schemas".toString() |
||||
] |
||||
} |
||||
} |
||||
} |
||||
buildFeatures { |
||||
viewBinding true |
||||
} |
||||
buildTypes { |
||||
release { |
||||
buildConfigField "String", "Cronet_Version", "\"$CronetVersion\"" |
||||
if (project.hasProperty("RELEASE_STORE_FILE")) { |
||||
signingConfig signingConfigs.myConfig |
||||
} |
||||
applicationIdSuffix '.release' |
||||
|
||||
minifyEnabled false |
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
||||
} |
||||
debug { |
||||
buildConfigField "String", "Cronet_Version", "\"$CronetVersion\"" |
||||
if (project.hasProperty("RELEASE_STORE_FILE")) { |
||||
signingConfig signingConfigs.myConfig |
||||
} |
||||
applicationIdSuffix '.debug' |
||||
versionNameSuffix 'debug' |
||||
minifyEnabled false |
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
||||
} |
||||
android.applicationVariants.all { variant -> |
||||
variant.outputs.all { |
||||
def flavor = variant.productFlavors[0].name |
||||
outputFileName = "${name}_${flavor}_${defaultConfig.versionName}.apk" |
||||
} |
||||
} |
||||
} |
||||
flavorDimensions "mode" |
||||
productFlavors { |
||||
app { |
||||
dimension "mode" |
||||
manifestPlaceholders = [APP_CHANNEL_VALUE: "app"] |
||||
} |
||||
google { |
||||
dimension "mode" |
||||
applicationId "io.legado.play" |
||||
manifestPlaceholders = [APP_CHANNEL_VALUE: "google"] |
||||
} |
||||
} |
||||
compileOptions { |
||||
// Flag to enable support for the new language APIs |
||||
coreLibraryDesugaringEnabled true |
||||
// Sets Java compatibility to Java 11 |
||||
sourceCompatibility JavaVersion.VERSION_11 |
||||
targetCompatibility JavaVersion.VERSION_11 |
||||
} |
||||
|
||||
sourceSets { |
||||
// Adds exported schema location as test app assets. |
||||
androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) |
||||
} |
||||
tasks.withType(JavaCompile) { |
||||
//options.compilerArgs << "-Xlint:unchecked" |
||||
} |
||||
} |
||||
|
||||
resourcePlaceholders { |
||||
files = ['xml/shortcuts.xml'] |
||||
} |
||||
|
||||
kapt { |
||||
arguments { |
||||
arg("room.schemaLocation", "$projectDir/schemas") |
||||
} |
||||
} |
||||
|
||||
dependencies { |
||||
coreLibraryDesugaring('com.android.tools:desugar_jdk_libs:1.1.5') |
||||
testImplementation('junit:junit:4.13.2') |
||||
androidTestImplementation('androidx.test:runner:1.4.0') |
||||
androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0') |
||||
implementation('androidx.multidex:multidex:2.0.1') |
||||
//kotlin |
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version") |
||||
//Kotlin反射 |
||||
implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version") |
||||
//协程 |
||||
def coroutines_version = '1.6.0' |
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") |
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version") |
||||
|
||||
//androidX |
||||
implementation('androidx.core:core-ktx:1.7.0') |
||||
implementation('androidx.appcompat:appcompat:1.4.0') |
||||
implementation('androidx.activity:activity-ktx:1.4.0') |
||||
implementation('androidx.fragment:fragment-ktx:1.4.0') |
||||
implementation('androidx.preference:preference-ktx:1.1.1') |
||||
implementation('androidx.constraintlayout:constraintlayout:2.1.2') |
||||
implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0') |
||||
implementation('androidx.viewpager2:viewpager2:1.0.0') |
||||
implementation('com.google.android.material:material:1.4.0') |
||||
implementation('com.google.android.flexbox:flexbox:3.0.0') |
||||
implementation('com.google.code.gson:gson:2.8.9') |
||||
implementation('androidx.webkit:webkit:1.4.0') |
||||
|
||||
implementation('com.jakewharton.timber:timber:5.0.1') |
||||
|
||||
//media |
||||
implementation("androidx.media:media:1.4.3") |
||||
def exoplayer_version = '2.16.1' |
||||
implementation("com.google.android.exoplayer:exoplayer-core:$exoplayer_version") |
||||
implementation("com.google.android.exoplayer:extension-okhttp:$exoplayer_version") |
||||
|
||||
//Splitties |
||||
def splitties_version = '3.0.0' |
||||
implementation("com.louiscad.splitties:splitties-appctx:$splitties_version") |
||||
implementation("com.louiscad.splitties:splitties-systemservices:$splitties_version") |
||||
implementation("com.louiscad.splitties:splitties-views:$splitties_version") |
||||
|
||||
//lifecycle |
||||
def lifecycle_version = '2.4.0' |
||||
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version") |
||||
|
||||
//room |
||||
def room_version = '2.4.0' |
||||
implementation("androidx.room:room-runtime:$room_version") |
||||
implementation("androidx.room:room-ktx:$room_version") |
||||
kapt("androidx.room:room-compiler:$room_version") |
||||
testImplementation("androidx.room:room-testing:$room_version") |
||||
|
||||
//liveEventBus |
||||
implementation('io.github.jeremyliao:live-event-bus-x:1.8.0') |
||||
|
||||
//规则相关 |
||||
implementation('org.jsoup:jsoup:1.14.3') |
||||
implementation('com.jayway.jsonpath:json-path:2.6.0') |
||||
implementation('cn.wanghaomiao:JsoupXpath:2.5.1') |
||||
implementation(project(path: ':epublib')) |
||||
|
||||
//JS rhino |
||||
implementation('com.github.gedoor:rhino-android:1.6') |
||||
|
||||
//网络 |
||||
implementation('com.squareup.okhttp3:okhttp:4.9.3') |
||||
implementation(fileTree(dir: 'cronetlib', include: ['*.jar', '*.aar'])) |
||||
|
||||
//Glide |
||||
implementation('com.github.bumptech.glide:glide:4.12.0') |
||||
kapt('com.github.bumptech.glide:compiler:4.12.0') |
||||
|
||||
//webServer |
||||
def nanoHttpdVersion = "2.3.1" |
||||
implementation("org.nanohttpd:nanohttpd:$nanoHttpdVersion") |
||||
implementation("org.nanohttpd:nanohttpd-websocket:$nanoHttpdVersion") |
||||
|
||||
//二维码 |
||||
implementation('com.github.jenly1314:zxing-lite:2.1.1') |
||||
|
||||
//颜色选择 |
||||
implementation('com.jaredrummler:colorpicker:1.1.0') |
||||
|
||||
//apache |
||||
implementation('org.apache.commons:commons-text:1.9') |
||||
|
||||
//MarkDown |
||||
def markwonVersion = "4.6.2" |
||||
implementation("io.noties.markwon:core:$markwonVersion") |
||||
implementation("io.noties.markwon:image-glide:$markwonVersion") |
||||
implementation("io.noties.markwon:ext-tables:$markwonVersion") |
||||
implementation("io.noties.markwon:html:$markwonVersion") |
||||
|
||||
//转换繁体 |
||||
implementation('com.github.liuyueyi.quick-chinese-transfer:quick-transfer-core:0.2.3') |
||||
|
||||
//代码编辑com.github.AmrDeveloper:CodeView已集成到应用内 |
||||
//epubLib集成到应用内 |
||||
|
||||
// LeakCanary |
||||
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' |
||||
} |
@ -0,0 +1,110 @@ |
||||
import java.security.MessageDigest |
||||
|
||||
apply plugin: 'de.undercouch.download' |
||||
|
||||
def BASE_PATH = "https://storage.googleapis.com/chromium-cronet/android/" + CronetVersion + "/Release/cronet/" |
||||
def assetsDir = projectDir.toString() + "/src/main/assets" |
||||
def libPath = projectDir.toString() + "/cronetlib" |
||||
def soPath = projectDir.toString() + "/so" |
||||
|
||||
/** |
||||
* 从文件生成MD5 |
||||
* @param file |
||||
* @return |
||||
*/ |
||||
static def generateMD5(final file) { |
||||
MessageDigest digest = MessageDigest.getInstance("MD5") |
||||
file.withInputStream() { is -> |
||||
byte[] buffer = new byte[1024] |
||||
int numRead = 0 |
||||
while ((numRead = is.read(buffer)) > 0) { |
||||
digest.update(buffer, 0, numRead) |
||||
} |
||||
} |
||||
return String.format("%032x", new BigInteger(1, digest.digest())).toLowerCase() |
||||
} |
||||
|
||||
/** |
||||
* 下载Cronet相关的jar |
||||
*/ |
||||
task downloadJar(type: Download) { |
||||
src([ |
||||
BASE_PATH + "cronet_api.jar", |
||||
BASE_PATH + "cronet_impl_common_java.jar", |
||||
BASE_PATH + "cronet_impl_native_java.jar", |
||||
BASE_PATH + "cronet_impl_platform_java.jar", |
||||
]) |
||||
dest libPath |
||||
overwrite true |
||||
onlyIfModified true |
||||
} |
||||
/** |
||||
* 下载Cronet的arm64-v8a so |
||||
*/ |
||||
task downloadARM64(type: Download) { |
||||
src BASE_PATH + "libs/arm64-v8a/libcronet." + CronetVersion + ".so" |
||||
dest soPath + "/arm64-v8a.so" |
||||
overwrite true |
||||
onlyIfModified true |
||||
} |
||||
/** |
||||
* 下载Cronet的armeabi-v7a so |
||||
*/ |
||||
task downloadARMv7(type: Download) { |
||||
src BASE_PATH + "libs/armeabi-v7a/libcronet." + CronetVersion + ".so" |
||||
dest soPath + "/armeabi-v7a.so" |
||||
overwrite true |
||||
onlyIfModified true |
||||
} |
||||
/** |
||||
* 下载Cronet的x86_64 so |
||||
*/ |
||||
task downloadX86_64(type: Download) { |
||||
src BASE_PATH + "libs/x86_64/libcronet." + CronetVersion + ".so" |
||||
dest soPath + "/x86_64.so" |
||||
overwrite true |
||||
onlyIfModified true |
||||
} |
||||
/** |
||||
* 下载Cronet的x86 so |
||||
*/ |
||||
task downloadX86(type: Download) { |
||||
src BASE_PATH + "libs/x86/libcronet." + CronetVersion + ".so" |
||||
dest soPath + "/x86.so" |
||||
overwrite true |
||||
onlyIfModified true |
||||
} |
||||
|
||||
/** |
||||
* 更新Cronet版本时执行这个task |
||||
* 先更改gradle.properties 里面的版本号,然后再执行 |
||||
* gradlew app:downloadCronet |
||||
*/ |
||||
task downloadCronet() { |
||||
dependsOn downloadJar, downloadARM64, downloadARMv7, downloadX86_64, downloadX86 |
||||
|
||||
doLast { |
||||
StringBuilder sb = new StringBuilder("{") |
||||
def files = new File(soPath).listFiles() |
||||
for (File file : files) { |
||||
println file.name.replace(".so", "") |
||||
sb.append("\"").append(file.name.replace(".so", "")).append("\":\"").append(generateMD5(file)).append("\",") |
||||
} |
||||
sb.append("\"version\":\"").append(CronetVersion).append("\"}") |
||||
|
||||
println sb.toString() |
||||
|
||||
println assetsDir |
||||
def f1 = new File(assetsDir + "/cronet.json") |
||||
if (!f1.exists()) { |
||||
f1.parentFile.mkdirs() |
||||
f1.createNewFile() |
||||
} |
||||
f1.text = sb.toString() |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
|
@ -0,0 +1,151 @@ |
||||
{ |
||||
"project_info": { |
||||
"project_number": "453392274790", |
||||
"firebase_url": "https://legado-fca69.firebaseio.com", |
||||
"project_id": "legado-fca69", |
||||
"storage_bucket": "legado-fca69.appspot.com" |
||||
}, |
||||
"client": [ |
||||
{ |
||||
"client_info": { |
||||
"mobilesdk_app_id": "1:453392274790:android:c4eac14b1410eec5f624a7", |
||||
"android_client_info": { |
||||
"package_name": "io.legado.app.debug" |
||||
} |
||||
}, |
||||
"oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
], |
||||
"api_key": [ |
||||
{ |
||||
"current_key": "AIzaSyD90mfNLhA7cAzzI9SonpSz5mrF5BnmyJA" |
||||
} |
||||
], |
||||
"services": { |
||||
"appinvite_service": { |
||||
"other_platform_oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
] |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"client_info": { |
||||
"mobilesdk_app_id": "1:453392274790:android:c1481c1c3d3f51eff624a7", |
||||
"android_client_info": { |
||||
"package_name": "io.legado.app.release" |
||||
} |
||||
}, |
||||
"oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-trrgennt5njr1lhil1sgtf0ogcgd38fo.apps.googleusercontent.com", |
||||
"client_type": 1, |
||||
"android_info": { |
||||
"package_name": "io.legado.app.release", |
||||
"certificate_hash": "fd67dba87b7b761631266f19ddde249054aac5c1" |
||||
} |
||||
}, |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
], |
||||
"api_key": [ |
||||
{ |
||||
"current_key": "AIzaSyD90mfNLhA7cAzzI9SonpSz5mrF5BnmyJA" |
||||
} |
||||
], |
||||
"services": { |
||||
"appinvite_service": { |
||||
"other_platform_oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
] |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"client_info": { |
||||
"mobilesdk_app_id": "1:453392274790:android:b891abd2331577dff624a7", |
||||
"android_client_info": { |
||||
"package_name": "io.legado.play.release" |
||||
} |
||||
}, |
||||
"oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-f8sjn6ohs72rg1dvp0pdvk42nkq54p0k.apps.googleusercontent.com", |
||||
"client_type": 1, |
||||
"android_info": { |
||||
"package_name": "io.legado.play.release", |
||||
"certificate_hash": "00819ace9891386e535967cbafd6a88f3797bd5b" |
||||
} |
||||
}, |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
], |
||||
"api_key": [ |
||||
{ |
||||
"current_key": "AIzaSyD90mfNLhA7cAzzI9SonpSz5mrF5BnmyJA" |
||||
} |
||||
], |
||||
"services": { |
||||
"appinvite_service": { |
||||
"other_platform_oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
] |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"client_info": { |
||||
"mobilesdk_app_id": "1:453392274790:android:b891abd2331577dff624a7", |
||||
"android_client_info": { |
||||
"package_name": "io.legado.play.debug" |
||||
} |
||||
}, |
||||
"oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-f8sjn6ohs72rg1dvp0pdvk42nkq54p0k.apps.googleusercontent.com", |
||||
"client_type": 1, |
||||
"android_info": { |
||||
"package_name": "io.legado.play.debug", |
||||
"certificate_hash": "00819ace9891386e535967cbafd6a88f3797bd5b" |
||||
} |
||||
}, |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
], |
||||
"api_key": [ |
||||
{ |
||||
"current_key": "AIzaSyD90mfNLhA7cAzzI9SonpSz5mrF5BnmyJA" |
||||
} |
||||
], |
||||
"services": { |
||||
"appinvite_service": { |
||||
"other_platform_oauth_client": [ |
||||
{ |
||||
"client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", |
||||
"client_type": 3 |
||||
} |
||||
] |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"configuration_version": "1" |
||||
} |
@ -0,0 +1,231 @@ |
||||
# Add project specific ProGuard rules here. |
||||
# You can control the set of applied configuration files using the |
||||
# proguardFiles setting in build.gradle. |
||||
# |
||||
# For more details, see |
||||
# http://developer.android.com/guide/developing/tools/proguard.html |
||||
|
||||
# If your project uses WebView with JS, uncomment the following |
||||
# and specify the fully qualified class name to the JavaScript interface |
||||
# class: |
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
||||
# public *; |
||||
#} |
||||
|
||||
# Uncomment this to preserve the line number information for |
||||
# debugging stack traces. |
||||
#-keepattributes SourceFile,LineNumberTable |
||||
|
||||
# If you keep the line number information, uncomment this to |
||||
# hide the original source file name. |
||||
#-renamesourcefileattribute SourceFile |
||||
# 混合时不使用大小写混合,混合后的类名为小写 |
||||
-dontusemixedcaseclassnames |
||||
|
||||
# 指定不去忽略非公共库的类 |
||||
-dontskipnonpubliclibraryclasses |
||||
|
||||
# 这句话能够使我们的项目混淆后产生映射文件 |
||||
# 包含有类名->混淆后类名的映射关系 |
||||
-verbose |
||||
|
||||
# 指定不去忽略非公共库的类成员 |
||||
-dontskipnonpubliclibraryclassmembers |
||||
|
||||
# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。 |
||||
-dontpreverify |
||||
|
||||
# 保留Annotation不混淆 |
||||
-keepattributes *Annotation*,InnerClasses |
||||
|
||||
# 避免混淆泛型 |
||||
-keepattributes Signature |
||||
|
||||
# 抛出异常时保留代码行号 |
||||
-keepattributes SourceFile,LineNumberTable |
||||
|
||||
# 指定混淆是采用的算法,后面的参数是一个过滤器 |
||||
# 这个过滤器是谷歌推荐的算法,一般不做更改 |
||||
-optimizations !code/simplification/cast,!field/*,!class/merging/* |
||||
|
||||
|
||||
############################################# |
||||
# |
||||
# Android开发中一些需要保留的公共部分 |
||||
# |
||||
############################################# |
||||
# 屏蔽错误Unresolved class name |
||||
#noinspection ShrinkerUnresolvedReference |
||||
|
||||
# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆 |
||||
# 因为这些子类都有可能被外部调用 |
||||
-keep public class * extends android.app.Activity |
||||
-keep public class * extends android.app.Application |
||||
-keep public class * extends android.app.Service |
||||
-keep public class * extends android.content.BroadcastReceiver |
||||
-keep public class * extends android.content.ContentProvider |
||||
-keep public class * extends android.app.backup.BackupAgentHelper |
||||
-keep public class * extends android.preference.Preference |
||||
-keep public class * extends android.view.View |
||||
|
||||
# 保留androidx下的所有类及其内部类 |
||||
-keep class androidx.** {*;} |
||||
|
||||
# 保留继承的 |
||||
-keep public class * extends androidx.** |
||||
|
||||
# 保留R下面的资源 |
||||
-keep class **.R$* {*;} |
||||
|
||||
# 保留本地native方法不被混淆 |
||||
-keepclasseswithmembernames class * { |
||||
native <methods>; |
||||
} |
||||
|
||||
# 保留在Activity中的方法参数是view的方法, |
||||
# 这样以来我们在layout中写的onClick就不会被影响 |
||||
-keepclassmembers class * extends android.app.Activity{ |
||||
public void *(android.view.View); |
||||
} |
||||
|
||||
# 保留枚举类不被混淆 |
||||
-keepclassmembers enum * { |
||||
public static **[] values(); |
||||
public static ** valueOf(java.lang.String); |
||||
} |
||||
|
||||
# 保留我们自定义控件(继承自View)不被混淆 |
||||
-keep public class * extends android.view.View{ |
||||
*** get*(); |
||||
void set*(***); |
||||
public <init>(android.content.Context); |
||||
public <init>(android.content.Context, android.util.AttributeSet); |
||||
public <init>(android.content.Context, android.util.AttributeSet, int); |
||||
} |
||||
|
||||
# 保留Parcelable序列化类不被混淆 |
||||
-keep class * implements android.os.Parcelable { |
||||
public static final android.os.Parcelable$Creator *; |
||||
} |
||||
|
||||
# 保留Serializable序列化的类不被混淆 |
||||
-keepclassmembers class * implements java.io.Serializable { |
||||
static final long serialVersionUID; |
||||
private static final java.io.ObjectStreamField[] serialPersistentFields; |
||||
!static !transient <fields>; |
||||
!private <fields>; |
||||
!private <methods>; |
||||
private void writeObject(java.io.ObjectOutputStream); |
||||
private void readObject(java.io.ObjectInputStream); |
||||
java.lang.Object writeReplace(); |
||||
java.lang.Object readResolve(); |
||||
} |
||||
|
||||
# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆 |
||||
-keepclassmembers class * { |
||||
void *(**On*Event); |
||||
void *(**On*Listener); |
||||
} |
||||
|
||||
# webView处理,项目中没有使用到webView忽略即可 |
||||
-keepclassmembers class * extends android.webkit.WebViewClient { |
||||
public void *(android.webkit.WebView, java.lang.String); |
||||
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); |
||||
public boolean *(android.webkit.WebView, java.lang.String); |
||||
} |
||||
|
||||
# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用 |
||||
# 记得proguard-android.txt中一定不要加-dontoptimize才起作用 |
||||
# 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制 |
||||
-assumenosideeffects class android.util.Log { |
||||
public static int v(...); |
||||
public static int i(...); |
||||
public static int w(...); |
||||
public static int d(...); |
||||
public static int e(...); |
||||
} |
||||
|
||||
# 保持js引擎调用的java类 |
||||
-keep class **.analyzeRule.**{*;} |
||||
# 保持web类 |
||||
-keep class **.web.**{*;} |
||||
#数据类 |
||||
-keep class **.data.**{*;} |
||||
|
||||
-dontwarn rx.** |
||||
-dontwarn okio.** |
||||
-dontwarn javax.annotation.** |
||||
-dontwarn org.apache.log4j.lf5.viewer.** |
||||
-dontnote org.apache.log4j.lf5.viewer.** |
||||
-dontwarn freemarker.** |
||||
-dontnote org.python.core.** |
||||
-dontwarn com.hwangjr.rxbus.** |
||||
-dontwarn okhttp3.** |
||||
-dontwarn org.conscrypt.** |
||||
-dontwarn com.jeremyliao.liveeventbus.** |
||||
|
||||
-keep class com.google.gson.** { *; } |
||||
-keep class com.ke.gson.** { *; } |
||||
-keep class com.jeremyliao.liveeventbus.** { *; } |
||||
-keep class okhttp3.**{*;} |
||||
-keep class okio.**{*;} |
||||
-keep class com.hwangjr.rxbus.**{*;} |
||||
-keep class org.conscrypt.**{*;} |
||||
-keep class android.support.**{*;} |
||||
-keep class me.grantland.widget.**{*;} |
||||
-keep class de.hdodenhof.circleimageview.**{*;} |
||||
-keep class tyrant.explosionfield.**{*;} |
||||
-keep class tyrantgit.explosionfield.**{*;} |
||||
-keep class freemarker.**{*;} |
||||
-keep class com.gyf.barlibrary.** {*;} |
||||
##JSOUP |
||||
-keep class org.jsoup.**{*;} |
||||
-keep class **.xpath.**{*;} |
||||
|
||||
-keep class org.slf4j.**{*;} |
||||
-dontwarn org.slf4j.** |
||||
|
||||
-keep class org.codehaus.**{*;} |
||||
-dontwarn org.codehaus.** |
||||
-keep class com.jayway.**{*;} |
||||
-dontwarn com.jayway.** |
||||
-keep class com.fasterxml.**{*;} |
||||
|
||||
-keep class javax.swing.**{*;} |
||||
-dontwarn javax.swing.** |
||||
-keep class java.awt.**{*;} |
||||
-dontwarn java.awt.** |
||||
-keep class sun.misc.**{*;} |
||||
-dontwarn sun.misc.** |
||||
-keep class sun.reflect.**{*;} |
||||
-dontwarn sun.reflect.** |
||||
|
||||
## Rhino |
||||
-keep class javax.script.** { *; } |
||||
-keep class com.sun.script.javascript.** { *; } |
||||
-keep class org.mozilla.javascript.** { *; } |
||||
|
||||
###EPUB |
||||
-dontwarn nl.siegmann.epublib.** |
||||
-dontwarn org.xmlpull.** |
||||
-keep class nl.siegmann.epublib.**{*;} |
||||
-keep class javax.xml.**{*;} |
||||
-keep class org.xmlpull.**{*;} |
||||
|
||||
-keep class org.simpleframework.**{*;} |
||||
-dontwarn org.simpleframework.xml.** |
||||
|
||||
-keepclassmembers class * { |
||||
public <init> (org.json.JSONObject); |
||||
} |
||||
-keepclassmembers enum * { |
||||
public static **[] values(); |
||||
public static ** valueOf(java.lang.String); |
||||
} |
||||
|
||||
|
||||
# Keep all of Cronet API as it's used by the Cronet module. |
||||
-keep public class org.chromium.net.* { |
||||
!private *; |
||||
*; |
||||
} |
@ -0,0 +1,26 @@ |
||||
package io.legado.app |
||||
|
||||
import android.net.Uri |
||||
import android.util.Log |
||||
import androidx.test.InstrumentationRegistry |
||||
import androidx.test.runner.AndroidJUnit4 |
||||
import org.junit.Test |
||||
import org.junit.runner.RunWith |
||||
|
||||
/** |
||||
* Instrumented test, which will execute on an Android device. |
||||
* |
||||
* See [testing documentation](http://d.android.com/tools/testing). |
||||
*/ |
||||
@RunWith(AndroidJUnit4::class) |
||||
class ExampleInstrumentedTest { |
||||
@Test |
||||
fun testContentProvider() { |
||||
// Context of the app under test. |
||||
val appContext = InstrumentationRegistry.getTargetContext() |
||||
Log.d("test", |
||||
appContext.contentResolver.query(Uri.parse("content://io.legado.app.api.ReaderProvider/sources/query"),null,null,null,null) |
||||
!!.getString(0) |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,50 @@ |
||||
package io.legado.app |
||||
|
||||
import androidx.room.Room |
||||
import androidx.room.migration.Migration |
||||
import androidx.room.testing.MigrationTestHelper |
||||
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory |
||||
import androidx.test.platform.app.InstrumentationRegistry |
||||
import androidx.test.runner.AndroidJUnit4 |
||||
import io.legado.app.data.AppDatabase |
||||
import org.junit.Rule |
||||
import org.junit.Test |
||||
import org.junit.runner.RunWith |
||||
import java.io.IOException |
||||
|
||||
@RunWith(AndroidJUnit4::class) |
||||
class MigrationTest { |
||||
private val TEST_DB = "migration-test" |
||||
|
||||
private val ALL_MIGRATIONS = arrayOf<Migration>( |
||||
|
||||
) |
||||
|
||||
@Rule |
||||
val helper: MigrationTestHelper = MigrationTestHelper( |
||||
InstrumentationRegistry.getInstrumentation(), |
||||
AppDatabase::class.java.canonicalName, |
||||
FrameworkSQLiteOpenHelperFactory() |
||||
) |
||||
|
||||
@Test |
||||
@Throws(IOException::class) |
||||
fun migrateAll() { |
||||
// Create earliest version of the database. |
||||
helper.createDatabase(TEST_DB, 30).apply { |
||||
close() |
||||
} |
||||
|
||||
// Open latest version of the database. Room will validate the schema |
||||
// once all migrations execute. |
||||
Room.databaseBuilder( |
||||
InstrumentationRegistry.getInstrumentation().targetContext, |
||||
AppDatabase::class.java, |
||||
TEST_DB |
||||
).addMigrations(*ALL_MIGRATIONS) |
||||
.build().apply { |
||||
openHelper.writableDatabase |
||||
close() |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,4 @@ |
||||
<resources> |
||||
<string name="app_name">阅读·D</string> |
||||
<string name="receiving_shared_label">阅读·D·搜索</string> |
||||
</resources> |
@ -0,0 +1,4 @@ |
||||
<resources> |
||||
<string name="app_name">legado·D</string> |
||||
<string name="receiving_shared_label">legado·D·search</string> |
||||
</resources> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">阅读Pro</string> |
||||
|
||||
</resources> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">閱讀Pro</string> |
||||
|
||||
</resources> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">閱讀Pro</string> |
||||
|
||||
</resources> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">legadoPro</string> |
||||
|
||||
</resources> |
@ -0,0 +1,465 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:tools="http://schemas.android.com/tools" |
||||
package="io.legado.app"> |
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" /> |
||||
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /> |
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> |
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> |
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> |
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> |
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> |
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> |
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> |
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> |
||||
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> |
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> |
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> |
||||
<uses-permission |
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE" |
||||
tools:ignore="ScopedStorage" /> |
||||
|
||||
<application |
||||
android:name=".App" |
||||
android:allowBackup="true" |
||||
android:icon="@mipmap/ic_launcher" |
||||
android:label="@string/app_name" |
||||
android:networkSecurityConfig="@xml/network_security_config" |
||||
android:requestLegacyExternalStorage="true" |
||||
android:supportsRtl="true" |
||||
android:theme="@style/AppTheme.Light" |
||||
tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute"> |
||||
<!-- 主入口 --> |
||||
<activity |
||||
android:name=".ui.welcome.WelcomeActivity" |
||||
android:exported="true"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="android.app.shortcuts" |
||||
android:launchMode="singleTask" |
||||
android:resource="@xml/shortcuts" /> |
||||
</activity> |
||||
<!-- 图标1 --> |
||||
<activity |
||||
android:name=".ui.welcome.Launcher1" |
||||
android:enabled="false" |
||||
android:exported="true" |
||||
android:icon="@mipmap/launcher1"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="android.app.shortcuts" |
||||
android:launchMode="singleTask" |
||||
android:resource="@xml/shortcuts" /> |
||||
</activity> |
||||
<!-- 图标2 --> |
||||
<activity |
||||
android:name=".ui.welcome.Launcher2" |
||||
android:enabled="false" |
||||
android:exported="true" |
||||
android:icon="@mipmap/launcher2"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="android.app.shortcuts" |
||||
android:launchMode="singleTask" |
||||
android:resource="@xml/shortcuts" /> |
||||
</activity> |
||||
<!-- 图标3 --> |
||||
<activity |
||||
android:name=".ui.welcome.Launcher3" |
||||
android:enabled="false" |
||||
android:exported="true" |
||||
android:icon="@mipmap/launcher3"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="android.app.shortcuts" |
||||
android:launchMode="singleTask" |
||||
android:resource="@xml/shortcuts" /> |
||||
</activity> |
||||
<!-- 图标4 --> |
||||
<activity |
||||
android:name=".ui.welcome.Launcher4" |
||||
android:enabled="false" |
||||
android:exported="true" |
||||
android:icon="@mipmap/launcher4"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="android.app.shortcuts" |
||||
android:launchMode="singleTask" |
||||
android:resource="@xml/shortcuts" /> |
||||
</activity> |
||||
<!-- 图标5 --> |
||||
<activity |
||||
android:name=".ui.welcome.Launcher5" |
||||
android:enabled="false" |
||||
android:exported="true" |
||||
android:icon="@mipmap/launcher5"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="android.app.shortcuts" |
||||
android:launchMode="singleTask" |
||||
android:resource="@xml/shortcuts" /> |
||||
</activity> |
||||
<!-- 图标6 --> |
||||
<activity |
||||
android:name=".ui.welcome.Launcher6" |
||||
android:enabled="false" |
||||
android:exported="true" |
||||
android:icon="@mipmap/launcher6"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="android.app.shortcuts" |
||||
android:launchMode="singleTask" |
||||
android:resource="@xml/shortcuts" /> |
||||
</activity> |
||||
<!-- 主界面 --> |
||||
<activity |
||||
android:name=".ui.main.MainActivity" |
||||
android:alwaysRetainTaskState="true" |
||||
android:launchMode="singleTask" /> |
||||
<!-- 阅读界面 --> |
||||
<activity |
||||
android:name=".ui.book.read.ReadBookActivity" |
||||
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" |
||||
android:exported="true" |
||||
android:launchMode="singleTask"> |
||||
<intent-filter> |
||||
<action android:name="com.samsung.android.support.REMOTE_ACTION" /> |
||||
</intent-filter> |
||||
|
||||
<meta-data |
||||
android:name="com.samsung.android.support.REMOTE_ACTION" |
||||
android:resource="@xml/spen_remote_actions" /> |
||||
</activity> |
||||
<!-- 书籍详情页 --> |
||||
<activity |
||||
android:name=".ui.book.info.BookInfoActivity" |
||||
android:launchMode="singleTop" /> |
||||
<!-- 书籍信息编辑 --> |
||||
<activity |
||||
android:name=".ui.book.info.edit.BookInfoEditActivity" |
||||
android:launchMode="singleTask" /> |
||||
<!-- 音频播放界面 --> |
||||
<activity |
||||
android:name="io.legado.app.ui.book.audio.AudioPlayActivity" |
||||
android:launchMode="singleTask" /> |
||||
<!-- 授权界面 --> |
||||
<activity |
||||
android:name="io.legado.app.lib.permission.PermissionActivity" |
||||
android:theme="@style/Activity.Permission" /> |
||||
<!-- 二维码扫描 --> |
||||
<activity |
||||
android:name=".ui.qrcode.QrCodeActivity" |
||||
android:launchMode="singleTask" /> |
||||
<!-- 规则订阅 --> |
||||
<activity |
||||
android:name=".ui.rss.subscription.RuleSubActivity" |
||||
android:launchMode="singleTask" /> |
||||
<!-- 书源编辑 --> |
||||
<activity |
||||
android:name=".ui.book.source.edit.BookSourceEditActivity" |
||||
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" |
||||
android:launchMode="singleTask" |
||||
android:windowSoftInputMode="adjustResize|stateHidden" /> |
||||
<!-- 订阅源编辑 --> |
||||
<activity |
||||
android:name=".ui.rss.source.edit.RssSourceEditActivity" |
||||
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" |
||||
android:launchMode="singleTask" |
||||
android:windowSoftInputMode="adjustResize|stateHidden" /> |
||||
<!-- 书源编辑 --> |
||||
<activity |
||||
android:name=".ui.replace.edit.ReplaceEditActivity" |
||||
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" |
||||
android:launchMode="singleTask" |
||||
android:windowSoftInputMode="adjustResize|stateHidden" /> |
||||
<!-- 配置界面 --> |
||||
<activity |
||||
android:name=".ui.config.ConfigActivity" |
||||
android:launchMode="singleTask" /> |
||||
<!-- 搜索界面 --> |
||||
<activity |
||||
android:name=".ui.book.search.SearchActivity" |
||||
android:launchMode="standard" /> |
||||
<!-- 关于界面 --> |
||||
<activity |
||||
android:name=".ui.about.AboutActivity" |
||||
android:launchMode="singleTask" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 捐赠界面 --> |
||||
<activity |
||||
android:name=".ui.about.DonateActivity" |
||||
android:launchMode="singleTask" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 书源管理 --> |
||||
<activity |
||||
android:name=".ui.book.source.manage.BookSourceActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 订阅源管理 --> |
||||
<activity |
||||
android:name=".ui.rss.source.manage.RssSourceActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- txt目录规则管理 --> |
||||
<activity |
||||
android:name=".ui.book.local.rule.TxtTocRuleActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 替换规则界面 --> |
||||
<activity |
||||
android:name=".ui.replace.ReplaceRuleActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 书籍管理 --> |
||||
<activity |
||||
android:name=".ui.book.arrange.ArrangeBookActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 书源调试 --> |
||||
<activity |
||||
android:name=".ui.book.source.debug.BookSourceDebugActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 目录 --> |
||||
<activity |
||||
android:name=".ui.book.toc.TocActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- 正文搜索 --> |
||||
<activity |
||||
android:name=".ui.book.searchContent.SearchContentActivity" |
||||
android:launchMode="singleTop" |
||||
android:screenOrientation="behind" /> |
||||
<!-- RSS条目 --> |
||||
<activity |
||||
android:name=".ui.rss.article.RssSortActivity" |
||||
android:launchMode="singleTop" /> |
||||
<!-- RSS阅读 --> |
||||
<activity |
||||
android:name=".ui.rss.read.ReadRssActivity" |
||||
android:configChanges="orientation|screenSize" |
||||
android:hardwareAccelerated="true" |
||||
android:launchMode="singleTop" /> |
||||
<!-- 导入书籍 --> |
||||
<activity |
||||
android:name=".ui.book.local.ImportBookActivity" |
||||
android:launchMode="singleTop" /> |
||||
<!-- 发现界面 --> |
||||
<activity |
||||
android:name=".ui.book.explore.ExploreShowActivity" |
||||
android:launchMode="singleTop" /> |
||||
<!-- 订阅源调试 --> |
||||
<activity |
||||
android:name=".ui.rss.source.debug.RssSourceDebugActivity" |
||||
android:launchMode="singleTop" /> |
||||
<!-- Rss收藏 --> |
||||
<activity |
||||
android:name=".ui.rss.favorites.RssFavoritesActivity" |
||||
android:launchMode="singleTop" /> |
||||
<!-- 缓存界面 --> |
||||
<activity |
||||
android:name=".ui.book.cache.CacheActivity" |
||||
android:launchMode="singleTop" /> |
||||
<!-- WebView界面 --> |
||||
<activity |
||||
android:name=".ui.browser.WebViewActivity" |
||||
android:launchMode="standard" /> |
||||
<!-- 书源登录 --> |
||||
<activity |
||||
android:name="io.legado.app.ui.login.SourceLoginActivity" |
||||
android:configChanges="orientation|screenSize" |
||||
android:hardwareAccelerated="true" |
||||
android:theme="@style/AppTheme.Transparent" /> |
||||
<!-- 阅读记录 --> |
||||
<activity |
||||
android:name=".ui.about.ReadRecordActivity" |
||||
android:configChanges="orientation|screenSize" |
||||
android:hardwareAccelerated="true" /> |
||||
<!-- 选择文件 --> |
||||
<activity |
||||
android:name=".ui.document.HandleFileActivity" |
||||
android:configChanges="orientation|screenSize" |
||||
android:hardwareAccelerated="true" |
||||
android:theme="@style/AppTheme.Transparent" /> |
||||
<!-- 文字处理 --> |
||||
<activity |
||||
android:name=".receiver.SharedReceiverActivity" |
||||
android:exported="true" |
||||
android:label="@string/receiving_shared_label" |
||||
android:theme="@style/AppTheme.Transparent"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.PROCESS_TEXT" /> |
||||
|
||||
<category android:name="android.intent.category.DEFAULT" /> |
||||
|
||||
<data android:mimeType="text/plain" /> |
||||
</intent-filter> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.SEND" /> |
||||
|
||||
<category android:name="android.intent.category.DEFAULT" /> |
||||
|
||||
<data android:mimeType="text/plain" /> |
||||
</intent-filter> |
||||
</activity> |
||||
<!-- 一键导入 --> |
||||
<activity |
||||
android:name=".ui.association.OnLineImportActivity" |
||||
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" |
||||
android:exported="true" |
||||
android:theme="@style/AppTheme.Transparent"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.VIEW" /> |
||||
|
||||
<category android:name="android.intent.category.DEFAULT" /> |
||||
<category android:name="android.intent.category.BROWSABLE" /> |
||||
|
||||
<data android:scheme="legado" /> |
||||
<data android:scheme="yuedu" /> |
||||
</intent-filter> |
||||
</activity> |
||||
<!-- 打开文件 --> |
||||
<activity |
||||
android:name=".ui.association.FileAssociationActivity" |
||||
android:exported="true" |
||||
android:launchMode="singleTop" |
||||
android:theme="@style/AppTheme.Transparent"> |
||||
<!-- VIEW (Open with) action --> |
||||
<!-- Works when an app knows the media type of a file, e.g. Gmail or Chrome. --> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.VIEW" /> |
||||
|
||||
<category android:name="android.intent.category.DEFAULT" /> |
||||
<category android:name="android.intent.category.BROWSABLE" /> |
||||
|
||||
<data android:scheme="app" /> |
||||
<data android:scheme="content" /> |
||||
<data android:scheme="file" /> |
||||
<!-- text --> |
||||
<data android:mimeType="text/plain" /> |
||||
<!-- json --> |
||||
<data android:mimeType="application/json" /> |
||||
<!-- EPUB --> |
||||
<data android:mimeType="application/epub+zip" /> |
||||
</intent-filter> |
||||
<!-- Works when an app doesn't know the media type, e.g. Dropbox --> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.VIEW" /> |
||||
|
||||
<category android:name="android.intent.category.DEFAULT" /> |
||||
<category android:name="android.intent.category.BROWSABLE" /> |
||||
|
||||
<data android:host="*" /> |
||||
|
||||
<data android:scheme="app" /> |
||||
<data android:scheme="content" /> |
||||
<data android:scheme="file" /> |
||||
<!-- This media type is necessary, otherwise it won't match on the file extension --> |
||||
<data android:mimeType="*/*" /> |
||||
<!--TXT--> |
||||
<data android:pathPattern=".*\\.txt" /> |
||||
<data android:pathPattern=".*\\.TXT" /> |
||||
<!--JSON--> |
||||
<data android:pathPattern=".*\\.json" /> |
||||
<data android:pathPattern=".*\\.JSON" /> |
||||
<!-- EPUB --> |
||||
<data android:pathPattern=".*\\.epub" /> |
||||
<data android:pathPattern=".*\\.EPUB" /> |
||||
</intent-filter> |
||||
</activity> |
||||
|
||||
<service android:name=".service.CheckSourceService" /> |
||||
<service android:name=".service.CacheBookService" /> |
||||
<service android:name=".service.WebService" /> |
||||
<service |
||||
android:name=".service.WebTileService" |
||||
android:exported="true" |
||||
android:icon="@drawable/ic_web_service_noti" |
||||
android:label="legado Web Service" |
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> |
||||
<intent-filter> |
||||
<action android:name="android.service.quicksettings.action.QS_TILE" /> |
||||
</intent-filter> |
||||
</service> |
||||
<service android:name=".service.TTSReadAloudService" /> |
||||
<service android:name=".service.HttpReadAloudService" /> |
||||
<service android:name=".service.AudioPlayService" /> |
||||
<service android:name=".service.DownloadService" /> |
||||
|
||||
<receiver |
||||
android:name=".receiver.MediaButtonReceiver" |
||||
android:exported="true"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MEDIA_BUTTON" /> |
||||
</intent-filter> |
||||
</receiver> |
||||
|
||||
<provider |
||||
android:name=".api.ReaderProvider" |
||||
android:authorities="${applicationId}.readerProvider" |
||||
android:enabled="true" |
||||
android:exported="true" |
||||
tools:ignore="ExportedContentProvider" /> |
||||
<provider |
||||
android:name="androidx.core.content.FileProvider" |
||||
android:authorities="${applicationId}.fileProvider" |
||||
android:exported="false" |
||||
android:grantUriPermissions="true"> |
||||
<meta-data |
||||
android:name="android.support.FILE_PROVIDER_PATHS" |
||||
android:resource="@xml/file_paths" /> |
||||
</provider> |
||||
|
||||
<meta-data |
||||
android:name="channel" |
||||
android:value="${APP_CHANNEL_VALUE}" /> |
||||
</application> |
||||
|
||||
<queries> |
||||
<intent> |
||||
<action android:name="android.intent.action.TTS_SERVICE" /> |
||||
</intent> |
||||
<intent> |
||||
<action android:name="android.intent.action.PROCESS_TEXT" /> |
||||
<data android:mimeType="text/plain" /> |
||||
</intent> |
||||
</queries> |
||||
|
||||
</manifest> |
@ -0,0 +1,284 @@ |
||||
OGN5dS5jb20= |
||||
c2cwMC54eXo= |
||||
aXRyYWZmaWNuZXQuY29t |
||||
eGlhb3FpYW5nNTIw |
||||
MTIzeGlhb3FpYW5n |
||||
eGlhb3FpYW5neHM= |
||||
eGlhb3FpYW5nNTIw |
||||
MzM1eHM= |
||||
eGN4czk= |
||||
eGN4czUyMA== |
||||
c2h1YmFvYW4= |
||||
c2h1YmFvd2FuZzEyMw== |
||||
c2h1YmFvYW4= |
||||
aGFpdGFuZzEyMw== |
||||
eXV6aGFpd3VsYQ== |
||||
cG8xOA== |
||||
Ymwtbm92ZWw= |
||||
NXRucw== |
||||
c2hhb3NodWdl |
||||
amluamlzaHV3dQ== |
||||
NDJ3Zw== |
||||
eWlxdXNodQ== |
||||
c2h1YmFvd2FuZzEyMw== |
||||
M2hlYmFv |
||||
MzNoZWJhbw== |
||||
bHVvcWl1enc= |
||||
bXlzaHVnZQ== |
||||
c3NzeHN3 |
||||
eWl0ZQ== |
||||
Y3Vpd2VpanV1 |
||||
Y3Vpd2VpanV4cw== |
||||
Y3Vpd2VpanV4 |
||||
eGlhb3FpYW5nd3g= |
||||
YXN6dw== |
||||
YXN6dzY= |
||||
c2FuaGFveHM= |
||||
ODdzaHV3dQ== |
||||
NDh3eA== |
||||
bG9uZ3Rlbmcy |
||||
NnF3eA== |
||||
bG9uZ3Rlbmd4cw== |
||||
aGF4ZHU= |
||||
M3R3eA== |
||||
aGF4d3g1 |
||||
NjZsZXdlbg== |
||||
eGJhbnpodQ== |
||||
aGR5cA== |
||||
ZHliejk= |
||||
ZGl5aWJhbnpodTk= |
||||
ZGl5aWJhbnpodQ== |
||||
ZGl5aWJhbnpodTc= |
||||
YnoyMjI= |
||||
d29kZWFwaTAwMQ== |
||||
dGFuZ3poZWthbg== |
||||
YmF4aWFueHM= |
||||
eGlhb3NodW9zaGVuemhhbg== |
||||
ZGFtb2tl |
||||
emh3ZW5wZw== |
||||
eXV6aGFpZ2U= |
||||
d21wOA== |
||||
OXhpYW53ZW4= |
||||
bmFucmVudmlw |
||||
cmV5b28= |
||||
eWZ4aWFvc2h1b2U= |
||||
c2Fuaml1enc= |
||||
N3Fpbmc3 |
||||
cWR4aWFvc2h1bw== |
||||
Y2hpbmVzZXpq |
||||
MzlzaHViYW8= |
||||
a3l4czU= |
||||
NTZtcw== |
||||
bml1c2hh |
||||
bWt4czY= |
||||
MjIyMjJ4cw== |
||||
OTVkdXNodQ== |
||||
YmFuemh1MjI= |
||||
d3JsdHh0 |
||||
dHVkb3V0eHQ= |
||||
cm5neHM= |
||||
OTl3ZW5rdQ== |
||||
bGFvc2lqaXhz |
||||
ZnVzaHV6aGFpMQ== |
||||
cG8xOA== |
||||
czUyMTc= |
||||
c2FuaGFveHM= |
||||
NTJrc2h1 |
||||
NDhyeA== |
||||
ZWNub3ZlbA== |
||||
bGllaHVvenc= |
||||
eGlhb3FpYW5nd3g= |
||||
NTJrc2h1 |
||||
NDh3eA== |
||||
NTJrc2h1 |
||||
MDB1aQ== |
||||
MDFieg== |
||||
c2h1YmFvMQ== |
||||
ZG54aWFvc2h1b2E= |
||||
am5zaHViYQ== |
||||
MThzaHV3dQ== |
||||
bGV4cw== |
||||
MzM1eHM= |
||||
dXB1 |
||||
ZnVndW9kdQ== |
||||
ODB0eHQ= |
||||
YWFyZWFk |
||||
eWlkdWR1MQ== |
||||
YmFuemh1d2FuZw== |
||||
cWloYW9xaWhhbw== |
||||
OHhpYW54cw== |
||||
amluamlzaHV3dQ== |
||||
d21wOA== |
||||
ZXl1c2h1d3U= |
||||
NTB4c2Y= |
||||
aGF4d3g1 |
||||
cG93YW5qdWFu |
||||
d2luMTBjaXR5 |
||||
eWV5ZXhzdw== |
||||
bXlzaHVnZQ== |
||||
eGlhbmd0eHN3 |
||||
Y3Vpd2VpanV4 |
||||
MzY2eHN3 |
||||
aHVheXVld2Vua3U= |
||||
eW91ZGlhbmxlbg== |
||||
c291Nzg= |
||||
bGFucm91Mg== |
||||
cXFib29r |
||||
eW91d3V4cw== |
||||
cnVpbGlzYWxl |
||||
MzY1bXd3 |
||||
ZnV3ZW5o |
||||
bGVzYmw= |
||||
YXd1Ym9vaw== |
||||
bGl5dXhpYW5nMjAyMA== |
||||
OTJwb3Bv |
||||
ZnVzaHV0dWFu |
||||
ODhkYW5tZWk= |
||||
ZG14cw== |
||||
eXVsaW56aGFueWU= |
||||
M2hlYmFv |
||||
eGd1YWd1YXhz |
||||
ZGl5aWJhbnpodTY= |
||||
aXJlYWR4cw== |
||||
c2h1YmFvOTY= |
||||
ZGl5aWJhbnpodTU1NQ== |
||||
c2Fuaml1enc= |
||||
N3Fpbmc3 |
||||
NjZsZXdlbg== |
||||
a3l4czU= |
||||
MjIyMjJ4cw== |
||||
c2hhb3NodWdl |
||||
amlsaW41NQ== |
||||
bWt4czY= |
||||
amluc2h1bG91 |
||||
eGlhbndhbmdz |
||||
eWlkdWR1 |
||||
cWR0eHQ= |
||||
MTZib29rMQ== |
||||
am1zaHV3dQ== |
||||
MzY2eHN3 |
||||
ZHliejk= |
||||
c2hvdWRhOA== |
||||
ZnlxMTg= |
||||
eWlzaHVn |
||||
eXV6aGFpd3VsYQ== |
||||
MTFiYW56aHU= |
||||
MTIzeGlhb3FpYW5n |
||||
ZGl5aWJhbnpodTk= |
||||
ZGl5aWJhbnpodQ== |
||||
MzY2eHN3 |
||||
ODdzaHV3dQ== |
||||
NnF3eA== |
||||
emhlbmh1bnhpYW9zaHVv |
||||
bG9uZ3Rlbmc1Mg== |
||||
eGlueGluZ3hpYW5nemhpZmE= |
||||
ZHliejk= |
||||
ZHVvemhla2Fu |
||||
MTIzeGlhb3FpYW5n |
||||
MzM1eHM= |
||||
am1zaHV3dQ== |
||||
c2hhb3NodWdl |
||||
bGF3ZW54cw== |
||||
cnVzaHV3dQ== |
||||
MzY2eHN3 |
||||
NTB4c2Y= |
||||
bGV3ZW41NQ== |
||||
aGFpdGFuZzEyMw== |
||||
aGViYW81MjA= |
||||
bHVvcWl1enc= |
||||
c3NzeHN3 |
||||
c2h1c2h1d3V4cw== |
||||
cm5neHM= |
||||
cWR4aWFvc2h1bw== |
||||
dHl1ZQ== |
||||
Y2hlNDM= |
||||
bG9uZ3Rlbmcy |
||||
amZ5eHNo |
||||
aGV0dTI= |
||||
bGFvc2lqaXhz |
||||
bG9uZ3Rlbmd4cw== |
||||
bGllaHVvenc= |
||||
c2h1YmFvYW4= |
||||
eHNodW9zaHVv |
||||
NTIxZGFubWVp |
||||
YmFuemh1MjI= |
||||
cWtzaHU= |
||||
eWZ4aWFvc2h1b2U= |
||||
a3lnc28= |
||||
c2h1bG91YmE= |
||||
NXRucw== |
||||
N3Fpbmc3 |
||||
bWlhb2R1NQ== |
||||
eXVzaHV3ZW4= |
||||
YWFyZWFk |
||||
cXRzaHU= |
||||
MTdzaHV3dQ== |
||||
c2h1YmFvMnM= |
||||
YnowMDE= |
||||
ZGFtb2dl |
||||
MTMxdGI= |
||||
aXhpYW9z |
||||
bXlzaHVnZQ== |
||||
OXhpYW53ZW4= |
||||
ZHVvemhla2Fu |
||||
MTIwdw== |
||||
c2h1c2h1d3U1MjA= |
||||
c2h1YmFvMnM= |
||||
YWd4c3c= |
||||
OTR4c3c= |
||||
cG8xOA== |
||||
eWFvY2hpeHM= |
||||
eGlhb3FpYW5neHM= |
||||
Ym9va2Js |
||||
c2Fuaml1eHM= |
||||
d29kZXNodWJhbw== |
||||
em9uZ2NhaXhpYW9zaHVvMg== |
||||
OWI4OTEzOTRkZjVi |
||||
MThub3ZlbA== |
||||
YWFib29r |
||||
YjF0eHQ= |
||||
eXVjYWl6dw== |
||||
Yzl0eHQ= |
||||
ZGl5aWJhbnpodTU1NQ== |
||||
MzBtYw== |
||||
eGlueXVzaHV3dQ== |
||||
c2h1YmFvd2FuZzEyMw== |
||||
YWd4cw== |
||||
YmlxdWdlbmw= |
||||
c2hpcWlzaHV3dQ== |
||||
c2lsdWtl |
||||
ZGl5aWJhbnpodTg= |
||||
ZGl5aWJhbnpodTk= |
||||
aGV0dW54cw== |
||||
OTl3ZW5rdQ== |
||||
aGFpdGFuZ3NodXd1 |
||||
OTd5ZA== |
||||
eXV6aGFpd3UxMQ== |
||||
Y3Vpd2VpanV4cw== |
||||
Y2JpcXU= |
||||
NTIxZGFubWVp |
||||
c2h1YmFvMzM= |
||||
c2FuaGFvMQ== |
||||
dGlhbm1lbmd3ZW5rdQ== |
||||
eXVzaHV3dTUyMA== |
||||
c2h1YmFvMjIy |
||||
c2h1YmFvd2FuZzEyMw== |
||||
eXVib29r |
||||
Y2JpcXU= |
||||
MWxld2Vu |
||||
MTV4c3c= |
||||
eG5jd3h3 |
||||
c2h1YmFvd2FuZzEyMw== |
||||
c2FuaGFveHM= |
||||
eXV3YW5nc2hl |
||||
YmlxdXRz |
||||
bGFtZWl4cw== |
||||
eGJhbnpodQ== |
||||
cWR4aWFvc2h1bw== |
||||
bWh0bGE= |
||||
OTl3ZW5rdQ== |
||||
eGlhb3FpYW5nNTIw |
||||
dGlhbm1lbmd3ZW5rdQ== |
||||
YWlmdXNodQ== |
||||
bWlhb2R1NQ== |
||||
bWlmZW5neHM= |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 246 KiB |
After Width: | Height: | Size: 312 KiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 132 KiB |
After Width: | Height: | Size: 287 KiB |
@ -0,0 +1 @@ |
||||
{"arm64-v8a":"690c212d9bbad4b09b9e1ba450b273bb","armeabi-v7a":"4dbb88e5229abef7d84138218772f872","x86":"3f2421e040147da48abb07cfc6c7c87e","x86_64":"730a71ef4f03a27d1c8c8a77e7d09ff5","version":"96.0.4664.104"} |
@ -0,0 +1,48 @@ |
||||
[ |
||||
{ |
||||
"bookSourceComment": "", |
||||
"bookSourceGroup": "听书", |
||||
"bookSourceName": "消消乐听书", |
||||
"bookSourceType": 1, |
||||
"bookSourceUrl": "https://www.kaixin7days.com", |
||||
"customOrder": 0, |
||||
"enabled": true, |
||||
"enabledExplore": true, |
||||
"exploreUrl": "@js:var header = JSON.parsesource.getLoginHeader()\nvar json = ''\nvar j = null\nif (header != null) {\n json = java.connect('https://www.kaixin7days.com/book-service/bookMgt/getBookCategroy,{\"method\":\"POST\",\"body\":{}}', header).body()\n j = JSON.parse(json)\n}\nif (j == null || j.statusCode != 200) {\n json = java.connect('https://www.kaixin7days.com/visitorLogin,{\"method\":\"POST\", \"body\":{} }').body()\n j = JSON.parse(json)\n var accessToken = {\n Authorization: 'Bearer ' + j.content.accessToken\n }\n header = JSON.stringify(accessToken)\n source.putLoginHeader(header)\n json = java.connect('https://www.kaixin7days.com/book-service/bookMgt/getBookCategroy,{\"method\":\"POST\",\"body\":{} }', header).body()\n j = JSON.parse(json)\n}\nvar fls = j.content\nvar fx = []\nfor (var i = 0; i < fls.length; i++) {\n fx.push({\n title: fls[i].categoryName,\n url: '/book-service/bookMgt/getAllBookByCategroyId,{\"method\":\"POST\",\"body\":{\"categoryIds\": \"' + fls[i].associationCategoryIDs + '\",\"pageNum\": {{page}},\"pageSize\": 100}}'\n })\n}\nJSON.stringify(fx)", |
||||
"searchUrl": "https://www.kaixin7days.com/book-service/bookMgt/findBookName,{\"method\":\"POST\",\"body\":{\"title\": \"searchKey\",\"pageNum\": {{searchPage}},\"pageSize\": 100}}", |
||||
"lastUpdateTime": 1630656684531, |
||||
"loginCheckJs": "var strRes = result\nvar c = JSON.parse(result.body())\nif (c.statusCode == 301) {\n var loginInfo = source.getLoginInfo()\n var dl = null\n if (loginInfo) {\n dl = java.connect('https://www.kaixin7days.com/login,{\"method\":\"POST\",\"body\":' + loginInfo + '}').body()\n } else {\n dl = java.connect('https://www.kaixin7days.com/visitorLogin,{\"method\":\"POST\",\"body\":{}}').body()\n }\n c = JSON.parse(dl)\n var accessToken = {\n Authorization: \"Bearer \" + c.content.accessToken\n }\n var header = JSON.stringify(accessToken)\n source.putLoginHeader(header)\n strRes = java.connect(url, header)\n}\nstrRes", |
||||
"loginUi": "[{\"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\"}]", |
||||
"loginUrl": "var loginInfo = source.getLoginInfo()\nvar json = java.connect('https://www.kaixin7days.com/login,{\"method\":\"POST\",\"body\":' + loginInfo + '}').body()\nvar loginRes = JSON.parse(json)\nvar header = null\nif (loginRes.statusCode == 200) {\n var accessToken = {\n Authorization: \"Bearer \" + loginRes.content.accessToken\n }\n header = JSON.stringify(accessToken)\n source.putLoginHeader(header)\n}\nheader", |
||||
"respondTime": 180000, |
||||
"ruleBookInfo": {}, |
||||
"ruleContent": { |
||||
"content": "", |
||||
"payAction": "var header = JSON.parse(source.getLoginHeader()); var bookId = book.getVariableMap().get('bookId');var chapterId = java.get('chapterId');\n'http://www.shuidi.online/?name=' + book.getName() + '&type=2&cover=' + book.getCoverUrl() + '&chapterId=' + chapterId + '&chapter=203&allNumber=' + book.getTotalChapterNum() + '&bookId=' + bookId + '&chapterIds=' + chapterId + '&number=' + chapter.getIndex() + '&accessToken=' + header.Authorization.substring(7) + '#/pay'" |
||||
}, |
||||
"ruleExplore": { |
||||
"author": "$.author", |
||||
"bookList": "$.content.content", |
||||
"bookUrl": "$.id@js:java.put('bookId', result);'https://www.kaixin7days.com/book-service/bookMgt/getAllChapterByBookId,{ \"method\": \"POST\",\"body\": {\"bookId\": \"'+result+'\",\"pageNum\": \"1\",\"pageSize\": \"10000\"} }'", |
||||
"coverUrl": "$.cover@js:var cover = JSON.parse(result);'https://www.shuidi.online/fileMgt/getPicture?filePath='+cover.storeFilePath", |
||||
"intro": "$.desc", |
||||
"lastChapter": "$.newestChapter", |
||||
"name": "$.title" |
||||
}, |
||||
"ruleSearch": { |
||||
"author": "$.author", |
||||
"bookList": "$.content.content", |
||||
"bookUrl": "$.id@js:java.put('bookId', result);'https://www.kaixin7days.com/book-service/bookMgt/getAllChapterByBookId,{ \"method\": \"POST\",\"body\": {\"bookId\": \"'+result+'\",\"pageNum\": \"1\",\"pageSize\": \"10000\"} }'", |
||||
"coverUrl": "$.cover@js:var cover = JSON.parse(result);'https://www.shuidi.online/fileMgt/getPicture?filePath='+cover.storeFilePath", |
||||
"intro": "$.desc", |
||||
"lastChapter": "$.newestChapter", |
||||
"name": "$.title" |
||||
}, |
||||
"ruleToc": { |
||||
"chapterList": "$.content.content", |
||||
"chapterName": "$.chapterTitle", |
||||
"chapterUrl": "$.id@js:java.put('chapterId', result);'https://www.shuidi.online/fileMgt/getAudioByChapterId?bookId=' + java.get('bookId') + '&chapterId=' + result + \"&pageNum=1&pageSize=50&keyId={{var header = JSON.parse(source.getLoginHeader());var keyId = '1632746188011002';var ks = java.md5Encode(keyId + java.get('chapterId') + header.Authorization);keyId + '&keySecret=' + ks}\" + '}'" |
||||
}, |
||||
"weight": 0 |
||||
} |
||||
] |
@ -0,0 +1,5 @@ |
||||
{ |
||||
"UploadUrl": "http://sy.miaogongzi.cc/shuyuan,{\"method\":\"POST\",\"body\": {\"file\": \"fileRequest\"},\"type\": \"multipart/form-data\"}", |
||||
"DownloadUrlRule": "$.data@js:if (result == '') \n '' \n else \n 'https://shuyuan.miaogongzi.cc/shuyuan/' + result", |
||||
"summary": "有效期2天" |
||||
} |
@ -0,0 +1,30 @@ |
||||
[ |
||||
{ |
||||
"id": -100, |
||||
"name": "1.百度", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{(speakSpeed + 5) / 10 + 4}}&per=4127&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=11&vol=5&aue=6&pit=3&_res_tag_=audio\"\n}", |
||||
"contentType": "audio/wav" |
||||
}, |
||||
{ |
||||
"id": -29, |
||||
"name": "2.阿里云语音", |
||||
"url": "https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts,{\"method\": \"POST\",\"body\": {\"appkey\":\"{{source.getLoginInfoMap().get('AppKey')}}\",\"text\":\"{{speakText}}\",\"format\":\"mp3\",\"volume\":100,\"speech_rate\":{{String((speakSpeed) * 20 - 400)}} }}", |
||||
"contentType": "audio/mpeg", |
||||
"loginUrl": "var loginInfo = source.getLoginInfoMap();\nvar accessKeyId = loginInfo.get('AccessKeyId');\nvar accessKeySecret = loginInfo.get('AccessKeySecret');\nvar timestamp = java.timeFormatUTC(new Date().getTime(), \"yyyy-MM-dd'T'HH:mm:ss'Z'\", 0);\nvar aly = new JavaImporter(Packages.javax.crypto.Mac, Packages.javax.crypto.spec.SecretKeySpec, Packages.javax.xml.bind.DatatypeConverter, Packages.java.net.URLEncoder, Packages.java.lang.String, Packages.android.util.Base64);\nwith (aly) {\n function percentEncode(value) {\n return URLEncoder.encode(value, \"UTF-8\").replace(\"+\", \"%20\")\n .replace(\"*\", \"%2A\").replace(\"%7E\", \"~\")\n }\n\n function sign(stringToSign, accessKeySecret) {\n var mac = Mac.getInstance('HmacSHA1');\n mac.init(new SecretKeySpec(String(accessKeySecret + '&').getBytes(\"UTF-8\"), \"HmacSHA1\"));\n var signData = mac.doFinal(String(stringToSign).getBytes(\"UTF-8\"));\n var signBase64 = Base64.encodeToString(signData, Base64.NO_WRAP);\n var signUrlEncode = percentEncode(signBase64);\n return signUrlEncode;\n }\n}\nvar query = 'AccessKeyId=' + accessKeyId + '&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=' + java.randomUUID() + '&SignatureVersion=1.0&Timestamp=' + percentEncode(timestamp) + '&Version=2019-02-28';\nvar signStr = sign('GET&' + percentEncode('/') + '&' + percentEncode(query), accessKeySecret);\nvar queryStringWithSign = \"Signature=\" + signStr + \"&\" + query;\nvar body = java.ajax('http://nls-meta.cn-shanghai.aliyuncs.com/?' + queryStringWithSign)\nvar res = JSON.parse(body)\nif (res.Message) {\n throw new Error(res.Message)\n}\nvar header = { \"X-NLS-Token\": res.Token.Id };\nsource.putLoginHeader(JSON.stringify(header))", |
||||
"loginUi": [ |
||||
{ |
||||
"name": "AppKey", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"name": "AccessKeyId", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"name": "AccessKeySecret", |
||||
"type": "text" |
||||
} |
||||
], |
||||
"loginCheckJs": "var response = result;\nif (response.headers().get(\"Content-Type\") != \"audio/mpeg\") {\n var body = JSON.parse(response.body().string())\n if (body.status == 40000001) {\n source.login()\n java.getHeaderMap().putAll(source.getHeaderMap(true))\n response = java.getResponse()\n } else {\n throw body.message\n }\n}\nresponse" |
||||
} |
||||
] |
@ -0,0 +1,42 @@ |
||||
[ |
||||
{ |
||||
"customOrder": 1, |
||||
"enableJs": true, |
||||
"enabled": true, |
||||
"singleUrl": true, |
||||
"sourceGroup": "legado", |
||||
"sourceIcon": "https://cdn.jsdelivr.net/gh/gedoor/legado@master/app/src/main/res/mipmap-hdpi/ic_launcher.png", |
||||
"sourceName": "使用说明", |
||||
"sourceUrl": "https://www.yuque.com/legado" |
||||
}, |
||||
{ |
||||
"customOrder": 2, |
||||
"enableJs": true, |
||||
"enabled": true, |
||||
"singleUrl": true, |
||||
"sourceGroup": "legado", |
||||
"sourceIcon": "http://mmbiz.qpic.cn/mmbiz_png/hpfMV8hEuL2eS6vnCxvTzoOiaCAibV6exBzJWq9xMic9xDg3YXAick87tsfafic0icRwkQ5ibV0bJ84JtSuxhPuEDVquA/0?wx_fmt=png", |
||||
"sourceName": "小说拾遗", |
||||
"sourceUrl": "snssdk1128://user/profile/562564899806367" |
||||
}, |
||||
{ |
||||
"customOrder": 3, |
||||
"enableJs": true, |
||||
"enabled": true, |
||||
"singleUrl": true, |
||||
"sourceGroup": "legado", |
||||
"sourceIcon": "https://Cloud.miaogongzi.site/images/icon.png", |
||||
"sourceName": "Meow云", |
||||
"sourceUrl": "https://pan.miaogongzi.net" |
||||
}, |
||||
{ |
||||
"customOrder": 4, |
||||
"enableJs": true, |
||||
"enabled": true, |
||||
"singleUrl": true, |
||||
"sourceGroup": "legado", |
||||
"sourceIcon": "https://cdn.jsdelivr.net/gh/gedoor/legado@master/app/src/main/res/mipmap-hdpi/ic_launcher.png", |
||||
"sourceName": "烏雲净化", |
||||
"sourceUrl": "https://www.lanzoux.com/b0bw8jwoh" |
||||
} |
||||
] |
@ -0,0 +1,26 @@ |
||||
[ |
||||
{ |
||||
"themeName": "典雅蓝", |
||||
"isNightTheme": false, |
||||
"primaryColor": "#03A9F4", |
||||
"accentColor": "#AD1457", |
||||
"backgroundColor": "#F5F5F5", |
||||
"bottomBackground": "#EEEEEE" |
||||
}, |
||||
{ |
||||
"themeName": "黑白", |
||||
"isNightTheme": true, |
||||
"primaryColor": "#303030", |
||||
"accentColor": "#E0E0E0", |
||||
"backgroundColor": "#424242", |
||||
"bottomBackground": "#424242" |
||||
}, |
||||
{ |
||||
"themeName": "A屏黑", |
||||
"isNightTheme": true, |
||||
"primaryColor": "#000000", |
||||
"accentColor": "#FFFFFF", |
||||
"backgroundColor": "#000000", |
||||
"bottomBackground": "#000000" |
||||
} |
||||
] |