mirror of https://github.com/NekoX-Dev/NekoX.git
应用内更新
This commit is contained in:
parent
14eab97190
commit
8cba28feff
|
@ -0,0 +1,200 @@
|
|||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
canaryBuild:
|
||||
name: Canary Build
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[D]') && !contains(github.event.head_commit.message, '[RELEASE]') && !contains(github.event.head_commit.message, '[N]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: gradle-${{ hashFiles('**/*.gradle') }}
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Run Gradle Build
|
||||
run: |
|
||||
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
|
||||
./gradlew assembleMinApi21Release
|
||||
echo ::set-env name=APK_FILE::$(find TMessagesProj/build/outputs/apk -name "*arm64-v8a*.apk")
|
||||
# - uses: actions/upload-artifact@v1
|
||||
# with:
|
||||
# name: NekoX Canary
|
||||
# path: ${{ env.APK_FILE }}
|
||||
- name: Upload Canary Apk
|
||||
uses: appleboy/telegram-action@master
|
||||
with:
|
||||
to: ${{ secrets.TELEGRAM_TO }}
|
||||
token: ${{ secrets.TELEGRAM_TOKEN }}
|
||||
document: ${{ env.APK_FILE }}
|
||||
nativeBuild:
|
||||
name: Native Build
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event.head_commit.message, '[N]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: native-${{ hashFiles('**/*.gradle') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- run: git submodule update --init --recursive
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/boringssl/build
|
||||
key: boringssl-${{ hashFiles('TMessagesProj/jni/boringssl/.git') }}
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/ffmpeg/build
|
||||
key: ffmpeg-${{ hashFiles('TMessagesProj/jni/ffmpeg/.git') }}
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Build native libraries
|
||||
run: |
|
||||
|
||||
cd TMessagesProj/jni
|
||||
|
||||
while :
|
||||
do
|
||||
sudo apt-get install -y ninja-build && break
|
||||
sleep 5
|
||||
done
|
||||
|
||||
export NDK=$ANDROID_HOME/ndk-bundle
|
||||
export NINJA_PATH=/usr/bin/ninja
|
||||
export PATH=`echo $ANDROID_HOME/cmake/*/bin`:$PATH
|
||||
|
||||
[ -d "ffmpeg/build" ] || ./build_ffmpeg_clang.sh
|
||||
|
||||
./patch_ffmpeg.sh
|
||||
|
||||
./patch_boringssl.sh
|
||||
|
||||
[ -d "boringssl/build" ] || ./build_boringssl.sh
|
||||
|
||||
- name: assemble
|
||||
run: |
|
||||
sudo bash <<EOF
|
||||
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}" &&
|
||||
./gradlew assembleAfatFoss
|
||||
EOF
|
||||
ls TMessagesProj/build/outputs/apk
|
||||
echo ::set-env name=APK_FILE::$(find TMessagesProj/build/outputs/apk -name "*universal*")
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: NekoX-Foss
|
||||
path: ${{ env.APK_FILE }}
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Boringssl Library
|
||||
path: "TMessagesProj/jni/boringssl/build"
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Ffmpeg Library
|
||||
path: "TMessagesProj/jni/ffmpeg/build"
|
||||
fossBuild:
|
||||
name: Foss Build
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event.head_commit.message, '[RELEASE]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: native-${{ hashFiles('**/*.gradle') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- run: git submodule update --init --recursive
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/boringssl/build
|
||||
key: boringssl-${{ hashFiles('TMessagesProj/jni/boringssl/.git') }}
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/ffmpeg/build
|
||||
key: ffmpeg-${{ hashFiles('TMessagesProj/jni/ffmpeg/.git') }}
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
- name: Build native libraries
|
||||
run: |
|
||||
|
||||
cd TMessagesProj/libs
|
||||
|
||||
go env -w GOPATH=$HOME/go
|
||||
export GOPATH=$HOME/go
|
||||
export PATH=$PATH:$GOPATH/bin
|
||||
|
||||
go get -u github.com/golang/protobuf/protoc-gen-go
|
||||
go get -v golang.org/x/mobile/cmd/...
|
||||
go get -v go.starlark.net/starlark
|
||||
go get -v github.com/refraction-networking/utls
|
||||
go get -v github.com/gorilla/websocket
|
||||
go get -v -insecure v2ray.com/core
|
||||
go get github.com/2dust/AndroidLibV2rayLite
|
||||
|
||||
gomobile init
|
||||
|
||||
rm libv2ray.aar
|
||||
env GO111MODULE=off gomobile bind -v -ldflags='-s -w' github.com/2dust/AndroidLibV2rayLite
|
||||
|
||||
cd ../jni
|
||||
|
||||
while :
|
||||
do
|
||||
sudo apt-get install -y ninja-build && break
|
||||
sleep 5
|
||||
done
|
||||
|
||||
export NDK=$ANDROID_HOME/ndk-bundle
|
||||
export NINJA_PATH=/usr/bin/ninja
|
||||
export PATH=`echo $ANDROID_HOME/cmake/*/bin`:$PATH
|
||||
|
||||
[ -d "ffmpeg/build" ] || ./build_ffmpeg_clang.sh
|
||||
|
||||
./patch_ffmpeg.sh
|
||||
|
||||
./patch_boringssl.sh
|
||||
|
||||
[ -d "boringssl/build" ] || ./build_boringssl.sh
|
||||
|
||||
- name: assemble
|
||||
run: |
|
||||
sudo bash <<EOF
|
||||
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
|
||||
./gradlew ss-libev:assembleRelease &&
|
||||
./gradlew ssr-libev:assembleRelease &&
|
||||
rm -rf TMessagesProj/libs/*-libev-release.aar &&
|
||||
find . -name "*-libev-release.aar" -exec mv {} TMessagesProj/libs \; &&
|
||||
./gradlew assembleAfatFoss
|
||||
EOF
|
||||
ls TMessagesProj/build/outputs/apk
|
||||
echo ::set-env name=APK_FILE::$(find TMessagesProj/build/outputs/apk -name "*universal*")
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: NekoX-Foss
|
||||
path: ${{ env.APK_FILE }}
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: V2ray Library
|
||||
path: "TMessagesProj/libs/libv2ray.aar"
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Boringssl Library
|
||||
path: "TMessagesProj/jni/boringssl/build"
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Ffmpeg Library
|
||||
path: "TMessagesProj/jni/ffmpeg/build"
|
|
@ -1,36 +0,0 @@
|
|||
name: Canary Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
canaryBuild:
|
||||
name: Canary Build
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[S]') && !contains(github.event.head_commit.message, '[RELEASE]') && !contains(github.event.head_commit.message, '[N]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: gradle-${{ hashFiles('**/*.gradle') }}
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Run Gradle Build
|
||||
run: |
|
||||
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
|
||||
./gradlew assembleMinApi21Release
|
||||
echo ::set-env name=APK_FILE::$(find TMessagesProj/build/outputs/apk -name "*arm64-v8a*.apk")
|
||||
# - uses: actions/upload-artifact@v1
|
||||
# with:
|
||||
# name: NekoX Canary
|
||||
# path: ${{ env.APK_FILE }}
|
||||
- name: Upload Canary Apk
|
||||
uses: appleboy/telegram-action@master
|
||||
with:
|
||||
to: ${{ secrets.TELEGRAM_TO }}
|
||||
token: ${{ secrets.TELEGRAM_TOKEN }}
|
||||
document: ${{ env.APK_FILE }}
|
|
@ -1,105 +0,0 @@
|
|||
name: Foss Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
fossBuild:
|
||||
name: Foss Build
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event.head_commit.message, '[RELEASE]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: native-${{ hashFiles('**/*.gradle') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- run: git submodule update --init --recursive
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/boringssl/build
|
||||
key: boringssl-${{ hashFiles('TMessagesProj/jni/boringssl/.git') }}
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/ffmpeg/build
|
||||
key: ffmpeg-${{ hashFiles('TMessagesProj/jni/ffmpeg/.git') }}
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
- name: Build native libraries
|
||||
run: |
|
||||
|
||||
cd TMessagesProj/libs
|
||||
|
||||
go env -w GOPATH=$HOME/go
|
||||
export GOPATH=$HOME/go
|
||||
export PATH=$PATH:$GOPATH/bin
|
||||
|
||||
go get -u github.com/golang/protobuf/protoc-gen-go
|
||||
go get -v golang.org/x/mobile/cmd/...
|
||||
go get -v go.starlark.net/starlark
|
||||
go get -v github.com/refraction-networking/utls
|
||||
go get -v github.com/gorilla/websocket
|
||||
go get -v -insecure v2ray.com/core
|
||||
go get github.com/2dust/AndroidLibV2rayLite
|
||||
|
||||
gomobile init
|
||||
|
||||
rm libv2ray.aar
|
||||
env GO111MODULE=off gomobile bind -v -ldflags='-s -w' github.com/2dust/AndroidLibV2rayLite
|
||||
|
||||
cd ../jni
|
||||
|
||||
while :
|
||||
do
|
||||
sudo apt-get install -y ninja-build && break
|
||||
sleep 5
|
||||
done
|
||||
|
||||
export NDK=$ANDROID_HOME/ndk-bundle
|
||||
export NINJA_PATH=/usr/bin/ninja
|
||||
export PATH=`echo $ANDROID_HOME/cmake/*/bin`:$PATH
|
||||
|
||||
[ -d "ffmpeg/build" ] || ./build_ffmpeg_clang.sh
|
||||
|
||||
./patch_ffmpeg.sh
|
||||
|
||||
./patch_boringssl.sh
|
||||
|
||||
[ -d "boringssl/build" ] || ./build_boringssl.sh
|
||||
|
||||
- name: assemble
|
||||
run: |
|
||||
sudo bash <<EOF
|
||||
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
|
||||
./gradlew ss-libev:assembleRelease &&
|
||||
./gradlew ssr-libev:assembleRelease &&
|
||||
rm -rf TMessagesProj/libs/*-libev-release.aar &&
|
||||
find . -name "*-libev-release.aar" -exec mv {} TMessagesProj/libs \; &&
|
||||
./gradlew assembleAfatFoss
|
||||
EOF
|
||||
ls TMessagesProj/build/outputs/apk
|
||||
echo ::set-env name=APK_FILE::$(find TMessagesProj/build/outputs/apk -name "*universal*")
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: NekoX-Foss
|
||||
path: ${{ env.APK_FILE }}
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: V2ray Library
|
||||
path: "TMessagesProj/libs/libv2ray.aar"
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Boringssl Library
|
||||
path: "TMessagesProj/jni/boringssl/build"
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Ffmpeg Library
|
||||
path: "TMessagesProj/jni/ffmpeg/build"
|
|
@ -1,75 +0,0 @@
|
|||
name: Native Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
nativeBuild:
|
||||
name: Native Build
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event.head_commit.message, '[N]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: native-${{ hashFiles('**/*.gradle') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- run: git submodule update --init --recursive
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/boringssl/build
|
||||
key: boringssl-${{ hashFiles('TMessagesProj/jni/boringssl/.git') }}
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: TMessagesProj/jni/ffmpeg/build
|
||||
key: ffmpeg-${{ hashFiles('TMessagesProj/jni/ffmpeg/.git') }}
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Build native libraries
|
||||
run: |
|
||||
|
||||
cd TMessagesProj/jni
|
||||
|
||||
while :
|
||||
do
|
||||
sudo apt-get install -y ninja-build && break
|
||||
sleep 5
|
||||
done
|
||||
|
||||
export NDK=$ANDROID_HOME/ndk-bundle
|
||||
export NINJA_PATH=/usr/bin/ninja
|
||||
export PATH=`echo $ANDROID_HOME/cmake/*/bin`:$PATH
|
||||
|
||||
[ -d "ffmpeg/build" ] || ./build_ffmpeg_clang.sh
|
||||
|
||||
./patch_ffmpeg.sh
|
||||
|
||||
./patch_boringssl.sh
|
||||
|
||||
[ -d "boringssl/build" ] || ./build_boringssl.sh
|
||||
|
||||
- name: assemble
|
||||
run: |
|
||||
sudo bash <<EOF
|
||||
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}" &&
|
||||
./gradlew assembleAfatFoss
|
||||
EOF
|
||||
ls TMessagesProj/build/outputs/apk
|
||||
echo ::set-env name=APK_FILE::$(find TMessagesProj/build/outputs/apk -name "*universal*")
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: NekoX-Foss
|
||||
path: ${{ env.APK_FILE }}
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Boringssl Library
|
||||
path: "TMessagesProj/jni/boringssl/build"
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: Ffmpeg Library
|
||||
path: "TMessagesProj/jni/ffmpeg/build"
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
- name: assembleRelease
|
||||
run: |
|
||||
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
|
||||
./gradlew TMessagesPro:assembleRelease \
|
||||
./gradlew TMessagesProj:assembleRelease \
|
||||
TMessagesProj:assembleReleaseNoGcm \
|
||||
TMessagesProj:bundleAfatRelease
|
||||
- name: Upload apks
|
||||
|
@ -41,6 +41,24 @@ jobs:
|
|||
ref=${ref/"refs/tags/"/}
|
||||
msg="${{ github.event.head_commit.message }}"
|
||||
ghr -delete -n "$ref" -b "$msg" "$ref" apks/
|
||||
rm -rf $HOME/.ssh
|
||||
mkdir -p $HOME/.ssh
|
||||
echo "${{ secrets.SSH_KEY }}" > $HOME/.ssh/id_rsa
|
||||
chmod 600 $HOME/.ssh/id_rsa
|
||||
mv build/update.json apks
|
||||
cd apks
|
||||
rm *universal*
|
||||
xz *.apk
|
||||
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
|
||||
git init
|
||||
git config --global user.name "世界"
|
||||
git config --global user.email "i@nekox.me"
|
||||
git remote add github "git@github.com:NekoX-Dev/Resources.git"
|
||||
git remote add gitlab "git@gitlab.com:NekoX/Resources.git"
|
||||
git add . --all
|
||||
git commit -m 喵
|
||||
git push github master -f
|
||||
git push gitlab master -f
|
||||
- uses: r0adkll/upload-google-play@master
|
||||
with:
|
||||
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_ACCOUNT_SERVICE }}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import cn.hutool.core.io.FileUtil
|
||||
import cn.hutool.json.JSONObject
|
||||
import cn.hutool.system.SystemUtil
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
@ -9,6 +13,22 @@ configurations {
|
|||
compile.exclude module: 'support-v4'
|
||||
}
|
||||
|
||||
buildscript {
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
classpath 'cn.hutool:hutool-all:5.3.2'
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.core:core:1.3.0-rc01'
|
||||
|
@ -19,7 +39,7 @@ dependencies {
|
|||
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
|
||||
compileOnly 'com.android.support:multidex:1.0.3'
|
||||
|
||||
compileOnly 'org.checkerframework:checker-qual:3.3.0'
|
||||
compileOnly 'org.checkerframework:checker-qual:3.4.0'
|
||||
compileOnly 'org.checkerframework:checker-compat-qual:2.5.5'
|
||||
implementation 'com.googlecode.mp4parser:isoparser:1.1.22'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
|
@ -36,24 +56,46 @@ dependencies {
|
|||
implementation 'org.dizitart:nitrite:3.4.1'
|
||||
implementation 'net.lingala.zip4j:zip4j:2.5.2'
|
||||
|
||||
implementation 'cn.hutool:hutool-core:5.3.2'
|
||||
implementation 'cn.hutool:hutool-crypto:5.3.2'
|
||||
implementation 'cn.hutool:hutool-all:5.3.2'
|
||||
implementation 'org.tukaani:xz:1.8'
|
||||
|
||||
|
||||
implementation files('libs/libv2ray.aar')
|
||||
implementation files('libs/ss-libev-release.aar')
|
||||
implementation files('libs/ssr-libev-release.aar')
|
||||
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
|
||||
compileOnly 'com.google.firebase:firebase-messaging:20.1.6'
|
||||
compileOnly 'com.google.firebase:firebase-crashlytics:17.0.0'
|
||||
def fcmVersion = '20.1.4'
|
||||
|
||||
releaseImplementation 'com.google.firebase:firebase-messaging:20.1.6'
|
||||
//noinspection GradleDependency
|
||||
compileOnly "com.google.firebase:firebase-messaging:$fcmVersion"
|
||||
compileOnly "com.google.firebase:firebase-crashlytics:17.0.0"
|
||||
compileOnly 'com.google.android.play:core:1.7.2'
|
||||
|
||||
//noinspection GradleDependency
|
||||
releaseImplementation "com.google.firebase:firebase-messaging:$fcmVersion"
|
||||
releaseImplementation 'com.google.firebase:firebase-crashlytics:17.0.0'
|
||||
releaseImplementation 'com.google.android.play:core:1.7.2'
|
||||
|
||||
}
|
||||
|
||||
def verName = "6.1.1.0-rc03"
|
||||
def verCode = 29
|
||||
|
||||
task writeUpdateInfo {
|
||||
|
||||
def info = new JSONObject()
|
||||
|
||||
info.set("version", verName)
|
||||
info.set("versionCode", verCode)
|
||||
info.set("defaultApkName","NekoX-afat-armeabi-v7a-release.apk.xz")
|
||||
|
||||
FileUtil.writeUtf8String(info.toStringPretty(), new File("build/update.json"))
|
||||
|
||||
}
|
||||
|
||||
tasks.findByName("preBuild").finalizedBy(writeUpdateInfo)
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.3'
|
||||
|
@ -65,8 +107,8 @@ android {
|
|||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
|
||||
versionName "6.1.1.0-rc03"
|
||||
versionCode = 29
|
||||
versionName verName
|
||||
versionCode verCode
|
||||
|
||||
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']
|
||||
|
||||
|
@ -246,7 +288,7 @@ android {
|
|||
def tgVoipDexClassesPath = "org/telegram/messenger/voip"
|
||||
def dxUtilPath = "${sdkDirectory.path}/build-tools/${buildToolsVersion}/dx"
|
||||
|
||||
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||
if (SystemUtil.getOsInfo().isWindows()) {
|
||||
dxUtilPath += ".bat"
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ import tw.nekomimi.nekogram.NekoXSettingActivity;
|
|||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.PrivacyUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.UpdateUtil;
|
||||
|
||||
public class LaunchActivity extends Activity implements ActionBarLayout.ActionBarLayoutDelegate, NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate {
|
||||
|
||||
|
@ -799,6 +800,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
FileLog.e(e);
|
||||
}
|
||||
MediaController.getInstance().setBaseActivity(this, true);
|
||||
UpdateUtil.checkUpdate(this);
|
||||
}
|
||||
|
||||
private void checkSystemBarColors() {
|
||||
|
|
|
@ -55,6 +55,7 @@ import androidx.core.content.FileProvider;
|
|||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.checkerframework.common.subtyping.qual.Bottom;
|
||||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
|
@ -124,9 +125,14 @@ import java.util.Set;
|
|||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.NekoSettingsActivity;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.NekoXSettingActivity;
|
||||
import tw.nekomimi.nekogram.parts.UpdateChecksKt;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
|
||||
public class SettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, ImageUpdater.ImageUpdaterDelegate {
|
||||
|
||||
|
@ -501,10 +507,41 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
} else if (position == numberRow) {
|
||||
presentFragment(new ActionIntroActivity(ActionIntroActivity.ACTION_TYPE_CHANGE_PHONE_NUMBER));
|
||||
} else if (position == versionRow) {
|
||||
TextInfoPrivacyCell cell = (TextInfoPrivacyCell) view;
|
||||
pressCount++;
|
||||
if (pressCount == 8) {
|
||||
NekoXConfig.developerModeEntrance = true;
|
||||
Toast.makeText(getParentActivity(), "¯\\_(ツ)_/¯", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
BottomBuilder builder = new BottomBuilder(getParentActivity());
|
||||
builder.addTitle(cell.getTextView().getText().toString(), false);
|
||||
builder.addItem(LocaleController.getString("CopyDetails", R.string.CopyDetails), R.drawable.baseline_content_copy_24, (it) -> {
|
||||
builder.dismiss();
|
||||
AndroidUtilities.addToClipboard(cell.getTextView().getText().toString());
|
||||
AlertUtil.showToast(LocaleController.getString("TextCopied", R.string.TextCopied));
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
builder.addItem(LocaleController.getString("CheckUpdate", R.string.CheckUpdate), R.drawable.baseline_system_update_24, (it) -> {
|
||||
builder.dismiss();
|
||||
UpdateChecksKt.checkUpdate(SettingsActivity.this);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
if (NekoXConfig.developerModeEntrance) {
|
||||
builder.addItem(LocaleController.getString("DeveloperSettings", R.string.DeveloperSettings),R.drawable.baseline_developer_mode_24,(it) -> {
|
||||
builder.dismiss();
|
||||
BottomBuilder devBuilder = new BottomBuilder(getParentActivity());
|
||||
devBuilder.addTitle("**Your telegram account may be banned**","We are not responsible for any improper use of developer features.");
|
||||
devBuilder.addItem(LocaleController.getString("Continue",R.string.Continue),R.drawable.baseline_warning_24,true,(__) -> {
|
||||
devBuilder.dismiss();
|
||||
presentFragment(new NekoXSettingActivity());
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
devBuilder.addCancelItem();
|
||||
devBuilder.show();
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -532,8 +569,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
LocaleController.getString("DebugMenuClearMediaCache", R.string.DebugMenuClearMediaCache),
|
||||
LocaleController.getString("DebugMenuCallSettings", R.string.DebugMenuCallSettings),
|
||||
LocaleController.getString("DebugMenuReadAllDialogs", R.string.DebugMenuReadAllDialogs),
|
||||
SharedConfig.pauseMusicOnRecord ? LocaleController.getString("DebugMenuDisablePauseMusic", R.string.DebugMenuDisablePauseMusic) : LocaleController.getString("DebugMenuEnablePauseMusic", R.string.DebugMenuEnablePauseMusic),
|
||||
NekoXConfig.developerModeEntrance ? (NekoXConfig.developerMode ? LocaleController.getString("DisableDeveloperMode", R.string.DisableDeveloperMode) : LocaleController.getString("EnableDeveloperMode", R.string.EnableDeveloperMode)) : null
|
||||
SharedConfig.pauseMusicOnRecord ? LocaleController.getString("DebugMenuDisablePauseMusic", R.string.DebugMenuDisablePauseMusic) : LocaleController.getString("DebugMenuEnablePauseMusic", R.string.DebugMenuEnablePauseMusic)
|
||||
};
|
||||
builder.setItems(items, (dialog, which) -> {
|
||||
if (which == 0) {
|
||||
|
@ -567,8 +603,6 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
MessagesStorage.getInstance(currentAccount).readAllDialogs(-1);
|
||||
} else if (which == 9) {
|
||||
SharedConfig.togglePauseMusicOnRecord();
|
||||
} else if (which == 10) {
|
||||
NekoXConfig.toggleDeveloperMode();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||
|
@ -595,9 +629,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
};
|
||||
|
||||
searchListView.setVerticalScrollBarEnabled(false);
|
||||
searchListView.setLayoutManager(new
|
||||
|
||||
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
|
||||
searchListView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
|
||||
searchListView.setGlowColor(Theme.getColor(Theme.key_avatar_backgroundActionBarBlue));
|
||||
frameLayout.addView(searchListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
|
||||
searchListView.setAdapter(searchAdapter);
|
||||
|
@ -652,9 +684,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
});
|
||||
searchListView.setVisibility(View.GONE);
|
||||
|
||||
emptyView = new
|
||||
|
||||
EmptyTextProgressView(context);
|
||||
emptyView = new EmptyTextProgressView(context);
|
||||
emptyView.showTextView();
|
||||
emptyView.setTextSize(18);
|
||||
emptyView.setVisibility(View.GONE);
|
||||
|
@ -662,9 +692,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
emptyView.setPadding(0, AndroidUtilities.dp(50), 0, 0);
|
||||
frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
topView = new
|
||||
|
||||
TopView(context);
|
||||
topView = new TopView(context);
|
||||
topView.setBackgroundColor(Theme.getColor(Theme.key_avatar_backgroundActionBarBlue));
|
||||
frameLayout.addView(topView);
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class BottomBuilder(val ctx: Context) {
|
|||
|
||||
val headerCell = if (bigTitle) HeaderCell(ctx, Theme.key_dialogTextBlue2, 21, 15, subTitle != null) else HeaderCell(ctx)
|
||||
|
||||
headerCell.setText(title)
|
||||
headerCell.setText(if (title is String) AndroidUtilities.replaceTags(title) else title)
|
||||
|
||||
subTitle?.also {
|
||||
|
||||
|
@ -202,13 +202,13 @@ class BottomBuilder(val ctx: Context) {
|
|||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun addRadioItems(text: Array<String>, value: (Int,String) -> Boolean, valueText: ((Int,String) -> String)? = null, listener: (index: Int, text: String, cell: RadioButtonCell) -> Unit): List<RadioButtonCell> {
|
||||
fun addRadioItems(text: Array<String>, value: (Int, String) -> Boolean, valueText: ((Int, String) -> String)? = null, listener: (index: Int, text: String, cell: RadioButtonCell) -> Unit): List<RadioButtonCell> {
|
||||
|
||||
val list = mutableListOf<RadioButtonCell>()
|
||||
|
||||
text.forEachIndexed { index, textI ->
|
||||
|
||||
list.add(addRadioItem(textI, value(index,textI), valueText?.invoke(index,textI)) { cell ->
|
||||
list.add(addRadioItem(textI, value(index, textI), valueText?.invoke(index, textI)) { cell ->
|
||||
|
||||
listener(index, textI, cell)
|
||||
|
||||
|
@ -273,7 +273,8 @@ class BottomBuilder(val ctx: Context) {
|
|||
|
||||
}
|
||||
|
||||
fun addItem(text: String, icon: Int = 0, red: Boolean = false, listener: (cell: TextCell) -> Unit): TextCell {
|
||||
@JvmOverloads
|
||||
fun addItem(text: String, icon: Int = 0, red: Boolean = false, listener: ((cell: TextCell) -> Unit)?): TextCell {
|
||||
|
||||
return TextCell(ctx).apply {
|
||||
|
||||
|
@ -283,7 +284,7 @@ class BottomBuilder(val ctx: Context) {
|
|||
|
||||
setOnClickListener {
|
||||
|
||||
listener(this)
|
||||
if (listener == null) dismiss() else listener(this)
|
||||
|
||||
}
|
||||
|
||||
|
@ -325,7 +326,7 @@ class BottomBuilder(val ctx: Context) {
|
|||
setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14f)
|
||||
setTextColor(Theme.getColor(Theme.key_dialogTextBlack))
|
||||
setHintTextColor(Theme.getColor(Theme.key_dialogTextBlue4))
|
||||
hintText?.also { hint = it }
|
||||
hintText?.also { hint = it }
|
||||
isSingleLine = true
|
||||
isFocusable = true
|
||||
setBackgroundDrawable(null)
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
package tw.nekomimi.nekogram;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.IntentSender;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.play.core.appupdate.AppUpdateManager;
|
||||
import com.google.android.play.core.appupdate.AppUpdateManagerFactory;
|
||||
import com.google.android.play.core.install.InstallStateUpdatedListener;
|
||||
import com.google.android.play.core.install.model.AppUpdateType;
|
||||
import com.google.android.play.core.install.model.InstallStatus;
|
||||
import com.google.android.play.core.install.model.UpdateAvailability;
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics;
|
||||
import com.google.firebase.iid.FirebaseInstanceId;
|
||||
|
||||
|
@ -14,26 +21,27 @@ import org.telegram.messenger.BuildConfig;
|
|||
import org.telegram.messenger.BuildVars;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.GcmPushListenerService;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.utils.UIUtil;
|
||||
|
||||
public class ExternalGcm {
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static boolean noGcm = !"release".equals(BuildConfig.BUILD_TYPE);
|
||||
private static boolean noGcm = !"release".equals(BuildConfig.BUILD_TYPE);
|
||||
|
||||
private static boolean hasPlayServices;
|
||||
private static Boolean hasPlayServices;
|
||||
|
||||
public static void initPlayServices() {
|
||||
|
||||
if (noGcm) return;
|
||||
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (hasPlayServices = checkPlayServices()) {
|
||||
if (checkPlayServices()) {
|
||||
final String currentPushString = SharedConfig.pushString;
|
||||
if (!TextUtils.isEmpty(currentPushString)) {
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) {
|
||||
|
@ -74,34 +82,81 @@ public class ExternalGcm {
|
|||
|
||||
}
|
||||
|
||||
private static boolean checkPlayServices() {
|
||||
public static boolean checkPlayServices() {
|
||||
if (noGcm) return false;
|
||||
if (hasPlayServices != null) return hasPlayServices;
|
||||
try {
|
||||
int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(ApplicationLoader.applicationContext);
|
||||
return resultCode == ConnectionResult.SUCCESS;
|
||||
hasPlayServices = resultCode == ConnectionResult.SUCCESS;
|
||||
} catch (Exception e) {
|
||||
hasPlayServices = false;
|
||||
FileLog.e(e);
|
||||
}
|
||||
return true;
|
||||
return hasPlayServices;
|
||||
}
|
||||
|
||||
public static void sendRegistrationToServer() {
|
||||
if (noGcm) return;
|
||||
if (!checkPlayServices()) return;
|
||||
GcmPushListenerService.sendRegistrationToServer(SharedConfig.pushString);
|
||||
}
|
||||
|
||||
public static void reportLog(@NotNull String report) {
|
||||
|
||||
if (noGcm) return;
|
||||
|
||||
if (!checkPlayServices()) return;
|
||||
UIUtil.runOnIoDispatcher(() -> FirebaseCrashlytics.getInstance().log(report));
|
||||
|
||||
}
|
||||
|
||||
public static void recordException(@NotNull Throwable throwable) {
|
||||
|
||||
if (noGcm) return;
|
||||
|
||||
if (!checkPlayServices()) return;
|
||||
UIUtil.runOnIoDispatcher(() -> FirebaseCrashlytics.getInstance().recordException(throwable));
|
||||
}
|
||||
|
||||
public static void checkUpdate(Activity ctx) {
|
||||
if (!checkPlayServices()) return;
|
||||
|
||||
AppUpdateManager manager = AppUpdateManagerFactory.create(ctx);
|
||||
|
||||
InstallStateUpdatedListener listener = (installState) -> {
|
||||
|
||||
if (installState.installStatus() == InstallStatus.DOWNLOADED) {
|
||||
|
||||
BottomBuilder builder = new BottomBuilder(ctx);
|
||||
|
||||
builder.addTitle(LocaleController.getString("UpdateDownloaded", R.string.UpdateDownloaded), false);
|
||||
|
||||
builder.addItem(LocaleController.getString("Update", R.string.Update), R.drawable.baseline_system_update_24, false, (it) -> {
|
||||
|
||||
manager.completeUpdate();
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
});
|
||||
|
||||
builder.addItem(LocaleController.getString("Later", R.string.Later), R.drawable.baseline_watch_later_24, false, null);
|
||||
|
||||
builder.show();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
manager.registerListener(listener);
|
||||
|
||||
manager.getAppUpdateInfo().addOnSuccessListener((appUpdateInfo) -> {
|
||||
|
||||
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
|
||||
|
||||
if (appUpdateInfo.availableVersionCode() <= BuildConfig.VERSION_CODE) return;
|
||||
|
||||
try {
|
||||
|
||||
manager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.FLEXIBLE, ctx, 114514);
|
||||
|
||||
} catch (IntentSender.SendIntentException ignored) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ public class NekoXConfig {
|
|||
|
||||
public static String FAQ_URL = "https://telegra.ph/NekoX-FAQ-03-31";
|
||||
|
||||
private static SharedPreferences preferences = NitritesKt.openMainSharedPreference("nekox_config");
|
||||
public static SharedPreferences preferences = NitritesKt.openMainSharedPreference("nekox_config");
|
||||
|
||||
public static boolean developerModeEntrance;
|
||||
public static boolean developerMode = preferences.getBoolean("developer_mode", false);
|
||||
|
@ -23,6 +23,15 @@ public class NekoXConfig {
|
|||
|
||||
preferences.edit().putBoolean("developer_mode", developerMode = !developerMode).apply();
|
||||
|
||||
if (!developerMode) {
|
||||
|
||||
preferences.edit()
|
||||
.putBoolean("disable_flag_secure", disableFlagSecure = false)
|
||||
.putBoolean("disable_screenshot_detection", disableScreenshotDetection = false)
|
||||
.apply();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void toggleDisableFlagSecure() {
|
||||
|
@ -98,10 +107,10 @@ public class NekoXConfig {
|
|||
preferences.edit()
|
||||
.putString("custom_dc_v4", customDcIpv4)
|
||||
.putString("custom_dc_v6", customDcIpv6)
|
||||
.putInt("custom_dc_port",customDcPort)
|
||||
.putInt("custom_dc_layer",customDcLayer)
|
||||
.putString("custom_dc_public_key",customDcPublicKey)
|
||||
.putLong("custom_dc_fingerprint",customDcFingerprint)
|
||||
.putInt("custom_dc_port", customDcPort)
|
||||
.putInt("custom_dc_layer", customDcLayer)
|
||||
.putString("custom_dc_public_key", customDcPublicKey)
|
||||
.putLong("custom_dc_fingerprint", customDcFingerprint)
|
||||
.apply();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package tw.nekomimi.nekogram;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
|
@ -25,7 +24,6 @@ import org.telegram.ui.Cells.NotificationsCheckCell;
|
|||
import org.telegram.ui.Cells.ShadowSectionCell;
|
||||
import org.telegram.ui.Cells.TextCheckCell;
|
||||
import org.telegram.ui.Cells.TextDetailSettingsCell;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.RecyclerListView;
|
||||
|
@ -49,8 +47,8 @@ public class NekoXSettingActivity extends BaseFragment {
|
|||
|
||||
private int developerSettingsRow;
|
||||
|
||||
private int enableRow;
|
||||
private int fetchAndExportLangRow;
|
||||
|
||||
private int disableFlagSecureRow;
|
||||
private int disableScreenshotDetectionRow;
|
||||
|
||||
|
@ -61,7 +59,6 @@ public class NekoXSettingActivity extends BaseFragment {
|
|||
return true;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
|
@ -101,12 +98,13 @@ public class NekoXSettingActivity extends BaseFragment {
|
|||
listView.setOnItemClickListener((view, position, x, y) -> {
|
||||
|
||||
if (position == fetchAndExportLangRow) {
|
||||
|
||||
fetchAndExportLang();
|
||||
|
||||
}
|
||||
|
||||
if (position == disableFlagSecureRow) {
|
||||
if (position == enableRow) {
|
||||
NekoXConfig.toggleDeveloperMode();
|
||||
updateRows();
|
||||
} else if (position == disableFlagSecureRow) {
|
||||
NekoXConfig.toggleDisableFlagSecure();
|
||||
if (view instanceof TextCheckCell) {
|
||||
((TextCheckCell) view).setChecked(NekoXConfig.disableFlagSecure);
|
||||
|
@ -136,6 +134,7 @@ public class NekoXSettingActivity extends BaseFragment {
|
|||
|
||||
developerSettingsRow = rowCount++;
|
||||
|
||||
enableRow = rowCount++;
|
||||
fetchAndExportLangRow = rowCount++;
|
||||
|
||||
disableFlagSecureRow = rowCount++;
|
||||
|
@ -258,16 +257,26 @@ public class NekoXSettingActivity extends BaseFragment {
|
|||
case 3: {
|
||||
TextCheckCell textCell = (TextCheckCell) holder.itemView;
|
||||
textCell.setEnabled(true, null);
|
||||
if (position == disableFlagSecureRow) {
|
||||
textCell.setTextAndCheck("Disable Flag Secure", NekoXConfig.disableFlagSecure, true);
|
||||
} else if (position == disableScreenshotDetectionRow) {
|
||||
textCell.setTextAndCheck("Disable Screenshot Detection", NekoXConfig.disableScreenshotDetection, false);
|
||||
if (position == enableRow) {
|
||||
textCell.setTextAndCheck("Enable", NekoXConfig.developerMode, true);
|
||||
} else {
|
||||
if (!NekoXConfig.developerMode) {
|
||||
textCell.setEnabled(false);
|
||||
}
|
||||
if (position == disableFlagSecureRow) {
|
||||
textCell.setTextAndCheck("Disable Flag Secure", NekoXConfig.disableFlagSecure, true);
|
||||
} else if (position == disableScreenshotDetectionRow) {
|
||||
textCell.setTextAndCheck("Disable Screenshot Detection", NekoXConfig.disableScreenshotDetection, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
TextSettingsCell textCell = (TextSettingsCell) holder.itemView;
|
||||
if (!NekoXConfig.developerMode) {
|
||||
textCell.setEnabled(false);
|
||||
}
|
||||
if (position == fetchAndExportLangRow) {
|
||||
textCell.setText("Export Builtin Languages", true);
|
||||
}
|
||||
|
@ -279,10 +288,8 @@ public class NekoXSettingActivity extends BaseFragment {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(RecyclerView.ViewHolder holder) {
|
||||
int position = holder.getAdapterPosition();
|
||||
return position == fetchAndExportLangRow ||
|
||||
position == disableFlagSecureRow ||
|
||||
position == disableScreenshotDetectionRow;
|
||||
int type = holder.getItemViewType();
|
||||
return type == 2 || type == 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -312,10 +319,6 @@ public class NekoXSettingActivity extends BaseFragment {
|
|||
view = new TextDetailSettingsCell(mContext);
|
||||
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
break;
|
||||
case 7:
|
||||
view = new TextInfoPrivacyCell(mContext);
|
||||
view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
|
||||
break;
|
||||
}
|
||||
view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
|
||||
return new RecyclerListView.Holder(view);
|
||||
|
|
|
@ -23,27 +23,10 @@ import kotlin.random.Random
|
|||
|
||||
class VmessLoader {
|
||||
|
||||
private val point: V2RayPoint = Libv2ray.newV2RayPoint(EmptyCallback(), true)
|
||||
private val point = Libv2ray.newV2RayPoint(EmptyCallback(), true)
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
val public = VmessBean().apply {
|
||||
|
||||
address = "nekox.me"
|
||||
port = 443
|
||||
configType = V2RayConfig.EConfigType.Vmess
|
||||
id = "73670f86-6046-4ffd-b468-6cd73cea1f29"
|
||||
security = "none"
|
||||
network = "ws"
|
||||
streamSecurity = "tls"
|
||||
requestHost = "nekox.me"
|
||||
path = "/internet"
|
||||
|
||||
remarks = LocaleController.getString("NekoXProxy", R.string.NekoXProxy)
|
||||
|
||||
}
|
||||
|
||||
fun parseVmess1Link(server: String): VmessBean {
|
||||
|
||||
val lnk = ("https://" + server.substringAfter(VMESS1_PROTOCOL)).toHttpUrl()
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
package tw.nekomimi.nekogram.parts
|
||||
|
||||
import android.content.IntentSender.SendIntentException
|
||||
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
|
||||
import com.google.android.play.core.install.InstallStateUpdatedListener
|
||||
import com.google.android.play.core.install.model.AppUpdateType
|
||||
import com.google.android.play.core.install.model.InstallStatus
|
||||
import com.google.android.play.core.install.model.UpdateAvailability
|
||||
import org.json.JSONObject
|
||||
import org.telegram.messenger.BuildConfig
|
||||
import org.telegram.messenger.LocaleController
|
||||
import org.telegram.messenger.R
|
||||
import org.telegram.ui.SettingsActivity
|
||||
import tw.nekomimi.nekogram.BottomBuilder
|
||||
import tw.nekomimi.nekogram.ExternalGcm
|
||||
import tw.nekomimi.nekogram.NekoXConfig
|
||||
import tw.nekomimi.nekogram.utils.*
|
||||
import java.util.*
|
||||
|
||||
fun SettingsActivity.checkUpdate() {
|
||||
|
||||
val ctx = parentActivity
|
||||
|
||||
val progress = AlertUtil.showProgress(ctx)
|
||||
|
||||
progress.show()
|
||||
|
||||
UIUtil.runOnIoDispatcher {
|
||||
|
||||
if (ExternalGcm.checkPlayServices()) {
|
||||
|
||||
progress.uUpdate(LocaleController.getString("Checking", R.string.Checking) + " (Play Store)")
|
||||
|
||||
val manager = AppUpdateManagerFactory.create(ctx)
|
||||
|
||||
manager.registerListener(InstallStateUpdatedListener {
|
||||
|
||||
if (it.installStatus() == InstallStatus.DOWNLOADED) {
|
||||
|
||||
val builder = BottomBuilder(ctx)
|
||||
|
||||
builder.addTitle(LocaleController.getString("UpdateDownloaded", R.string.UpdateDownloaded), false)
|
||||
|
||||
builder.addItem(LocaleController.getString("Update", R.string.Update), R.drawable.baseline_system_update_24, false) {
|
||||
|
||||
manager.completeUpdate()
|
||||
|
||||
}
|
||||
|
||||
builder.addItem(LocaleController.getString("Later", R.string.Later), R.drawable.baseline_watch_later_24, false, null)
|
||||
|
||||
builder.show()
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
manager.appUpdateInfo.addOnSuccessListener {
|
||||
|
||||
progress.dismiss()
|
||||
|
||||
if (it.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && it.availableVersionCode() > BuildConfig.VERSION_CODE) {
|
||||
|
||||
try {
|
||||
|
||||
manager.startUpdateFlowForResult(it, AppUpdateType.FLEXIBLE, ctx, 114514)
|
||||
|
||||
} catch (ignored: SendIntentException) { }
|
||||
|
||||
} else {
|
||||
|
||||
AlertUtil.showToast(LocaleController.getString("NoUpdate", R.string.NoUpdate))
|
||||
|
||||
}
|
||||
|
||||
}.addOnFailureListener {
|
||||
|
||||
progress.uDismiss()
|
||||
|
||||
AlertUtil.showToast(it.message ?: it.javaClass.simpleName)
|
||||
|
||||
}
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}
|
||||
|
||||
progress.uUpdate(LocaleController.getString("Checking", R.string.Checking) + " (Repo)")
|
||||
|
||||
val ex = LinkedList<Throwable>()
|
||||
|
||||
UpdateUtil.updateUrls.forEach { url ->
|
||||
|
||||
runCatching {
|
||||
|
||||
val updateInfo = JSONObject(HttpUtil.get("$url/update.json"))
|
||||
|
||||
val code = updateInfo.getInt("versionCode")
|
||||
|
||||
progress.uDismiss()
|
||||
|
||||
if (code > BuildConfig.VERSION_CODE) UIUtil.runOnUIThread {
|
||||
|
||||
val builder = BottomBuilder(ctx)
|
||||
|
||||
builder.addTitle(LocaleController.getString("UpdateAvailable", R.string.UpdateAvailable), updateInfo.getString("version"))
|
||||
|
||||
builder.addItem(LocaleController.getString("Update", R.string.Update), R.drawable.baseline_system_update_24, false) {
|
||||
|
||||
UpdateUtil.doUpdate(ctx, code, updateInfo.getString("defaultApkName"))
|
||||
|
||||
builder.dismiss()
|
||||
|
||||
NekoXConfig.preferences.edit().remove("ignored_update_at").remove("ignore_update_at").apply()
|
||||
|
||||
}
|
||||
|
||||
builder.addItem(LocaleController.getString("Later", R.string.Later), R.drawable.baseline_watch_later_24, false) {
|
||||
|
||||
builder.dismiss()
|
||||
|
||||
NekoXConfig.preferences.edit().putLong("ignored_update_at", System.currentTimeMillis()).apply()
|
||||
|
||||
}
|
||||
|
||||
builder.addItem(LocaleController.getString("Ignore", R.string.Ignore), R.drawable.baseline_block_24, true) {
|
||||
|
||||
builder.dismiss()
|
||||
|
||||
NekoXConfig.preferences.edit().putInt("ignore_update", code).apply()
|
||||
|
||||
}
|
||||
|
||||
builder.show()
|
||||
|
||||
} else {
|
||||
|
||||
AlertUtil.showToast(LocaleController.getString("NoUpdate", R.string.NoUpdate))
|
||||
|
||||
}
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}.onFailure {
|
||||
|
||||
ex.add(it)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
progress.uDismiss()
|
||||
|
||||
AlertUtil.showToast(ex.map { it.message ?: it.javaClass.simpleName }.joinToString("\n"))
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -29,11 +29,19 @@ object AlertUtil {
|
|||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun showSimpleAlert(ctx: Context?, text: String, listener: ((AlertDialog.Builder) -> Unit)? = null) = UIUtil.runOnUIThread(Runnable {
|
||||
fun showSimpleAlert(ctx: Context, text: String, listener: ((AlertDialog.Builder) -> Unit)? = null) {
|
||||
|
||||
val builder = AlertDialog.Builder(ctx ?: ApplicationLoader.applicationContext)
|
||||
|
||||
builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX))
|
||||
showSimpleAlert(ctx,null, text, listener)
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showSimpleAlert(ctx: Context,title: String?, text: String, listener: ((AlertDialog.Builder) -> Unit)? = null) = UIUtil.runOnUIThread(Runnable {
|
||||
|
||||
val builder = AlertDialog.Builder(ctx)
|
||||
|
||||
builder.setTitle(title ?: LocaleController.getString("NekoX", R.string.NekoX))
|
||||
builder.setMessage(text)
|
||||
|
||||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK)) { _, _ ->
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package tw.nekomimi.nekogram.utils
|
||||
|
||||
import android.os.Build
|
||||
import org.telegram.messenger.ApplicationLoader
|
||||
import org.telegram.messenger.BuildVars
|
||||
import org.telegram.messenger.FileLog
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
|
||||
object FileUtil {
|
||||
|
||||
|
@ -86,6 +88,30 @@ object FileUtil {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun getAbi() = try {
|
||||
if (Build.CPU_ABI.equals("x86_64", ignoreCase = true)) {
|
||||
"x86_64"
|
||||
} else if (Build.CPU_ABI.equals("arm64-v8a", ignoreCase = true)) {
|
||||
"arm64-v8a"
|
||||
} else if (Build.CPU_ABI.equals("armeabi-v7a", ignoreCase = true)) {
|
||||
"armeabi-v7a"
|
||||
} else if (Build.CPU_ABI.equals("armeabi", ignoreCase = true)) {
|
||||
"armeabi"
|
||||
} else if (Build.CPU_ABI.equals("x86", ignoreCase = true)) {
|
||||
"x86"
|
||||
} else {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.e("Unsupported arch: " + Build.CPU_ABI)
|
||||
}
|
||||
"armeabi"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
FileLog.e(e)
|
||||
"armeabi"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun extLib(name: String): File {
|
||||
|
||||
|
@ -93,21 +119,18 @@ object FileUtil {
|
|||
|
||||
if (!execFile.isFile) {
|
||||
|
||||
execFile = File(ApplicationLoader.getDataDirFixed(), "cache/lib/lib$name.so")
|
||||
System.loadLibrary(name)
|
||||
|
||||
if (!execFile.isFile) {
|
||||
|
||||
val abi = when (execFile.parentFile!!.name) {
|
||||
execFile = File(ApplicationLoader.getDataDirFixed(), "cache/lib/${execFile.name}")
|
||||
|
||||
"arm64", "aarch64" -> "arm64-v8a"
|
||||
"x86", "i386", "i486", "i586", "i686" -> "x86"
|
||||
"x86_64", "amd64" -> "x86_64"
|
||||
else -> "armeabi-v7a"
|
||||
if (!execFile.isFile) {
|
||||
|
||||
saveNonAsset("lib/${getAbi()}/${execFile.name}", execFile);
|
||||
|
||||
}
|
||||
|
||||
saveNonAsset("lib/$abi/${execFile.name}", execFile);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -127,11 +150,11 @@ object FileUtil {
|
|||
|
||||
saveTo.parentFile?.also { initDir(it) }
|
||||
|
||||
val assets = ApplicationLoader.applicationContext.assets
|
||||
saveTo.createNewFile()
|
||||
|
||||
saveTo.outputStream().use {
|
||||
(ApplicationLoader::class.java.getResourceAsStream(path) ?: error("not found")).use {
|
||||
|
||||
IoUtil.copy(FileInputStream(assets.openNonAssetFd(path).fileDescriptor), it)
|
||||
IoUtil.copy(it, saveTo)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package tw.nekomimi.nekogram.utils
|
|||
import cn.hutool.core.collection.CollUtil
|
||||
import cn.hutool.core.util.ArrayUtil
|
||||
import cn.hutool.core.util.StrUtil
|
||||
import org.telegram.ui.ActionBar.AlertDialog
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
@ -142,4 +143,7 @@ operator fun AtomicLong.getValue(thisRef: Any?, property: KProperty<*>): Long =
|
|||
operator fun AtomicLong.setValue(thisRef: Any?, property: KProperty<*>, value: Long) = set(value)
|
||||
|
||||
operator fun <T> AtomicReference<T>.getValue(thisRef: Any?, property: KProperty<*>): T = get()
|
||||
operator fun <T> AtomicReference<T>.setValue(thisRef: Any?, property: KProperty<*>, value: T) = set(value)
|
||||
operator fun <T> AtomicReference<T>.setValue(thisRef: Any?, property: KProperty<*>, value: T) = set(value)
|
||||
|
||||
fun AlertDialog.uUpdate(message: String) = UIUtil.runOnUIThread { setMessage(message) }
|
||||
fun AlertDialog.uDismiss() = UIUtil.runOnUIThread { dismiss() }
|
|
@ -462,7 +462,7 @@ object ProxyUtil {
|
|||
|
||||
} catch (ex: NoSuchMethodError) {
|
||||
|
||||
AlertUtil.showSimpleAlert(ctx, "很抱歉, 這是一個已知的問題, 但您現在無法掃碼, 因爲您正在使用糟糕的Android系統, 直到 Google Zxing 為您的設備做出優化.")
|
||||
AlertUtil.showSimpleAlert(ctx,"很抱歉, 這是一個已知的問題, 但您現在無法掃碼, 因爲您正在使用糟糕的Android系統, 直到 Google Zxing 為您的設備做出優化.")
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.core.content.FileProvider
|
||||
import org.telegram.messenger.BuildConfig
|
||||
import org.telegram.messenger.ContactsController
|
||||
import org.telegram.ui.LaunchActivity
|
||||
import java.io.File
|
||||
|
||||
|
@ -14,7 +14,7 @@ object ShareUtil {
|
|||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun shareText(ctx: Context,text: String,choose: Boolean = false) {
|
||||
fun shareText(ctx: Context, text: String, choose: Boolean = false) {
|
||||
|
||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
|
@ -23,7 +23,7 @@ object ShareUtil {
|
|||
|
||||
if (!choose) {
|
||||
|
||||
intent.setClass(ctx,LaunchActivity::class.java)
|
||||
intent.setClass(ctx, LaunchActivity::class.java)
|
||||
ctx.startActivity(intent)
|
||||
|
||||
} else {
|
||||
|
@ -64,4 +64,42 @@ object ShareUtil {
|
|||
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
fun openFile(ctx: Context, fileToOpen: File) {
|
||||
|
||||
val uri = if (Build.VERSION.SDK_INT >= 24) {
|
||||
|
||||
FileProvider.getUriForFile(ctx, BuildConfig.APPLICATION_ID + ".provider", fileToOpen)
|
||||
|
||||
} else {
|
||||
|
||||
Uri.fromFile(fileToOpen)
|
||||
|
||||
}
|
||||
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
|
||||
}
|
||||
|
||||
if (fileToOpen.extension.isBlank()) {
|
||||
|
||||
intent.type = "application/octet-stream"
|
||||
|
||||
} else {
|
||||
|
||||
intent.type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileToOpen.extension)
|
||||
|
||||
}
|
||||
|
||||
intent.data = uri
|
||||
|
||||
ctx.startActivity(intent)
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,8 @@ object UIUtil {
|
|||
@JvmStatic
|
||||
fun runOnUIThread(runnable: Runnable) = ApplicationLoader.applicationHandler.post(runnable)
|
||||
|
||||
fun runOnUIThread(runnable: () -> Unit) = ApplicationLoader.applicationHandler.post(runnable)
|
||||
|
||||
@JvmStatic
|
||||
fun runOnIoDispatcher(runnable: Runnable) {
|
||||
|
||||
|
@ -21,4 +23,14 @@ object UIUtil {
|
|||
|
||||
}
|
||||
|
||||
fun runOnIoDispatcher(runnable: () -> Unit) {
|
||||
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
|
||||
runnable()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
package tw.nekomimi.nekogram.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import cn.hutool.core.io.IoUtil
|
||||
import cn.hutool.core.io.StreamProgress
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import okhttp3.internal.closeQuietly
|
||||
import org.json.JSONObject
|
||||
import org.telegram.messenger.BuildConfig
|
||||
import org.telegram.messenger.LocaleController
|
||||
import org.telegram.messenger.R
|
||||
import org.tukaani.xz.XZInputStream
|
||||
import tw.nekomimi.nekogram.BottomBuilder
|
||||
import tw.nekomimi.nekogram.ExternalGcm
|
||||
import tw.nekomimi.nekogram.NekoXConfig
|
||||
import java.io.File
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
object UpdateUtil {
|
||||
|
||||
val updateUrls = arrayOf(
|
||||
"https://gitee.com/nekoshizuku/nekox-resources/raw/master",
|
||||
"https://gitlab.com/NekoX/Resources/-/raw/master",
|
||||
"https://raw.githubusercontent.com/NekoX-Dev/Resources/master"
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun checkUpdate(ctx: Activity) = UIUtil.runOnIoDispatcher {
|
||||
|
||||
if (ExternalGcm.checkPlayServices()) {
|
||||
|
||||
ExternalGcm.checkUpdate(ctx)
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() - NekoXConfig.preferences.getLong("ignored_update_at", -1) > 1 * 60 * 60 * 1000L) {
|
||||
|
||||
// ignored
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}
|
||||
|
||||
updateUrls.forEach { url ->
|
||||
|
||||
runCatching {
|
||||
|
||||
val updateInfo = JSONObject(HttpUtil.get("$url/update.json"))
|
||||
|
||||
val code = updateInfo.getInt("versionCode")
|
||||
|
||||
if (code > BuildConfig.VERSION_CODE.coerceAtLeast(NekoXConfig.preferences.getInt("ignore_update", -1))) UIUtil.runOnUIThread {
|
||||
|
||||
val builder = BottomBuilder(ctx)
|
||||
|
||||
builder.addTitle(LocaleController.getString("UpdateAvailable", R.string.UpdateAvailable), updateInfo.getString("version"))
|
||||
|
||||
builder.addItem(LocaleController.getString("Update", R.string.Update), R.drawable.baseline_system_update_24, false) {
|
||||
|
||||
doUpdate(ctx, code, updateInfo.getString("defaultApkName"))
|
||||
|
||||
builder.dismiss()
|
||||
|
||||
NekoXConfig.preferences.edit().remove("ignored_update_at").remove("ignore_update_at").apply()
|
||||
|
||||
}
|
||||
|
||||
builder.addItem(LocaleController.getString("Later", R.string.Later), R.drawable.baseline_watch_later_24, false) {
|
||||
|
||||
builder.dismiss()
|
||||
|
||||
NekoXConfig.preferences.edit().putLong("ignored_update_at", System.currentTimeMillis()).apply()
|
||||
|
||||
}
|
||||
|
||||
builder.addItem(LocaleController.getString("Ignore", R.string.Ignore), R.drawable.baseline_block_24, true) {
|
||||
|
||||
builder.dismiss()
|
||||
|
||||
NekoXConfig.preferences.edit().putInt("ignore_update", code).apply()
|
||||
|
||||
}
|
||||
|
||||
builder.show()
|
||||
|
||||
}
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun doUpdate(ctx: Activity, targetVer: Int, defFileName: String) {
|
||||
|
||||
val pro = AlertUtil.showProgress(ctx)
|
||||
pro.setCanCacnel(false)
|
||||
pro.show()
|
||||
|
||||
fun update(message: String) = UIUtil.runOnUIThread { pro.setMessage(message) }
|
||||
fun dismiss() = UIUtil.runOnUIThread { pro.dismiss() }
|
||||
|
||||
var exception: Exception? = null
|
||||
|
||||
UIUtil.runOnIoDispatcher {
|
||||
|
||||
val fileName = "NekoX-${BuildConfig.FLAVOR}-${Build.CPU_ABI}-${BuildConfig.BUILD_TYPE}.apk.xz"
|
||||
|
||||
var response: Response? = null
|
||||
|
||||
runCatching {
|
||||
|
||||
for (url in updateUrls) {
|
||||
|
||||
try {
|
||||
|
||||
response = HttpUtil.okHttpClient.newCall(Request.Builder().url("$url/$fileName").build()).execute()
|
||||
|
||||
if (response!!.code != 200) error("HTTP ${response!!.code} :${response!!.body!!.string()}")
|
||||
|
||||
break
|
||||
|
||||
} catch (e: Exception) {
|
||||
|
||||
exception = e
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
|
||||
for (url in updateUrls) {
|
||||
|
||||
try {
|
||||
|
||||
response = HttpUtil.okHttpClient.newCall(Request.Builder().url("$url/$defFileName").build()).execute()
|
||||
|
||||
if (response!!.code != 200) error("HTTP ${response!!.code} :${response!!.body!!.string()}")
|
||||
|
||||
break
|
||||
|
||||
} catch (e: Exception) {
|
||||
|
||||
exception = e
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}.onFailure {
|
||||
|
||||
dismiss()
|
||||
|
||||
AlertUtil.showSimpleAlert(ctx, LocaleController.getString("DownloadFailed", R.string.DownloadFailed), it.toString())
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
|
||||
dismiss()
|
||||
|
||||
AlertUtil.showSimpleAlert(ctx, LocaleController.getString("DownloadFailed", R.string.DownloadFailed), exception!!.toString())
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}
|
||||
|
||||
val body = response!!.body!!
|
||||
|
||||
val size = body.contentLength()
|
||||
|
||||
val target = File(ctx.externalCacheDir, "nekox-$targetVer.apk")
|
||||
|
||||
update("Downloading...")
|
||||
|
||||
if (target.isFile) {
|
||||
|
||||
runCatching {
|
||||
|
||||
ZipInputStream(target.inputStream()).use { it.nextEntry }
|
||||
|
||||
dismiss()
|
||||
|
||||
ShareUtil.openFile(ctx, target)
|
||||
|
||||
return@runOnIoDispatcher
|
||||
|
||||
}.onFailure {
|
||||
|
||||
target.delete()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
runCatching {
|
||||
|
||||
val input = XZInputStream(body.byteStream())
|
||||
|
||||
FileUtil.initFile(target)
|
||||
|
||||
target.outputStream().use {
|
||||
|
||||
IoUtil.copy(input, it, IoUtil.DEFAULT_BUFFER_SIZE, object : StreamProgress {
|
||||
|
||||
override fun progress(progressSize: Long) {
|
||||
|
||||
update("$progressSize / $size ( ${((progressSize / size) * 100).toInt()}% )")
|
||||
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
|
||||
update("0 / $size")
|
||||
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
|
||||
update("Finish")
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
input.closeQuietly()
|
||||
|
||||
dismiss()
|
||||
|
||||
ShareUtil.openFile(ctx, target)
|
||||
|
||||
}.onFailure {
|
||||
|
||||
dismiss()
|
||||
|
||||
AlertUtil.showSimpleAlert(ctx, LocaleController.getString("DownloadFailed", R.string.DownloadFailed), it.toString())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#ff000000"
|
||||
android:pathData="M7,5h10v2h2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99L7,1c-1.1,0 -2,0.9 -2,2v4h2L7,5zM15.41,16.59L20,12l-4.59,-4.59L14,8.83 17.17,12 14,15.17l1.41,1.42zM10,15.17L6.83,12 10,8.83 8.59,7.41 4,12l4.59,4.59L10,15.17zM17,19L7,19v-2L5,17v4c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-4h-2v2z" />
|
||||
</vector>
|
|
@ -0,0 +1,143 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="CustomApi">API Kustom</string>
|
||||
<string name="UseCustomApiNotice">Gunakan api kustom untuk masuk, ini mungkin membantu jika anda tidak dapat mendaftar atau masuk.\n\nCatatan: fcm tidak akan bekerja jika anda menggunakan versi rilisan.</string>
|
||||
<string name="CustomApiNo">Jangan gunakan API kustom</string>
|
||||
<string name="CustomApiOfficial">Telegram Android</string>
|
||||
<string name="CustomApiTGX">Telegram X Android</string>
|
||||
<string name="CustomApiInput">Manual input</string>
|
||||
<string name="CustomBackend">Kustom Backend</string>
|
||||
<string name="CustomBackendNotice">Fungsi ini hanya tersedia untuk pengguna profesional, jika Anda tidak tahu apa yang mewakili opsi-opsi berikut, abaikan saja.</string>
|
||||
<string name="CustomBackendProduction">Official Production DataCenter</string>
|
||||
<string name="CustomBackendTestDC">Official Test DataCenter</string>
|
||||
<string name="CustomBackendIpv4">Ipv4 Address</string>
|
||||
<string name="CustomBackendIpv6">Ipv6 Address</string>
|
||||
<string name="CustomBackendLayer">Layer</string>
|
||||
<string name="CustomBackendPublicKey">Public Key</string>
|
||||
<string name="CustomBackendFingerprint">Key Fingerprint</string>
|
||||
<string name="CachePath">Direktori cache</string>
|
||||
<string name="AllowFlashCall">Izinkan panggilan cepat</string>
|
||||
<string name="ChangeTranslateProvider">Ubah Penyedia</string>
|
||||
<string name="ProviderYandex">Yandex.Terjemahan</string>
|
||||
<string name="GoogleCloudTransKey">Google Cloud Translate Key</string>
|
||||
<string name="GoogleCloudTransKeyNotice">Jika anda menyiapkan Google Cloud Trans Key, API terjemahan awan akan digunakan, alih-alih mengirimkan formulir palsu ke versi web saat menerjemahkan (lalu lintas yang lebih cepat, stabil, dan hemat).</string>
|
||||
<string name="TransToLang">Bahasa target terjemahan</string>
|
||||
<string name="TransInputToLang">Input bahasa target</string>
|
||||
<string name="More">Lainnya</string>
|
||||
<string name="NekoXUpdatesChannel">Channel Pembaruan NekoX</string>
|
||||
<string name="ShowIdAndDc">Tampilkan ID / DC di profil</string>
|
||||
<string name="UseDefaultTheme">Gunakan tema default *</string>
|
||||
<string name="NightMode">Mode Malam</string>
|
||||
<string name="PrivacyNotice">Peringatan privasi</string>
|
||||
<string name="PrivacyNoticePhoneVisible">Terdeteksi bahwa nomor ponsel anda dapat dilihat oleh siapa saja, yang dapat menyebabkan peretas yang dimiliki pemerintah dapat menemukan identitas anda yang sebenarnya, harap matikan!</string>
|
||||
<string name="PrivacyNoticeAddByPhone">Terdeteksi bahwa anda tidak mematikan pengaturan \"Izinkan menemukan saya melalui nomor telepon\", yang dapat menyebabkan peretas yang dimiliki pemerintah menemukan identitas anda yang sebenarnya, harap matikan!</string>
|
||||
<string name="PrivacyNoticeP2p">Terdeteksi bahwa anda belum mematikan pengaturan \"Izinkan panggilan P2p\", yang dapat menyebabkan peretas yang dimiliki pemerintah menemukan identitas anda yang sebenarnya, harap matikan!</string>
|
||||
<string name="PrivacyNotice2fa">Terdeteksi bahwa anda belum menetapkan kata sandi, yang dapat menyebabkan peretas yang dimiliki pemerintah menemukan identitas anda yang sebenarnya, harap setel!</string>
|
||||
<string name="ApplySuggestion">Oke, Terapkan</string>
|
||||
<string name="DoNotRemindAgain">Jangan Ingatkan lagi</string>
|
||||
<string name="InstantViewTransWithWeb">Tidak dapat menerjemahkan InstantView menggunakan penerjemah web</string>
|
||||
<string name="RemoveTitleEmoji">Hapus emoji dari judul Nekogram X</string>
|
||||
<string name="NekoXProxy">NekoX Publik Proxy</string>
|
||||
<string name="PublicPrefix">Publik</string>
|
||||
<string name="DisableChatAction">Jangan kirim status input saya</string>
|
||||
<string name="FakeScreenshot">Simulasikan tangkapan layar</string>
|
||||
<string name="Import">Impor</string>
|
||||
<string name="FilterNameUsers">Pengguna</string>
|
||||
<string name="FilterNameUsersDescription">Hanya pesan dari obrolan pribadi</string>
|
||||
<string name="FilterNameContacts">Kontak</string>
|
||||
<string name="FilterNameContactsDescription">Hanya pesan dari pengguna yang disimpan</string>
|
||||
<string name="FilterNameGroups">Grup</string>
|
||||
<string name="FilterNameGroupsDescription">Hanya pesan dari obrolan grup</string>
|
||||
<string name="FilterNameChannels">Channel</string>
|
||||
<string name="FilterNameChannelsDescription">Hanya pesan dari channel</string>
|
||||
<string name="FilterNameBots">Bot</string>
|
||||
<string name="FilterNameBotsDescription">Hanya pesan dari bot</string>
|
||||
<string name="FilterNameUnmuted">Tidak dibisukan</string>
|
||||
<string name="FilterNameUnmutedDescription">Hanya pesan dari obrolan yang tidak dibisukan</string>
|
||||
<string name="FilterNameUnread2">Belum dibaca</string>
|
||||
<string name="FilterNameUnreadDescription">Hanya pesan yang belum dibaca</string>
|
||||
<string name="FilterNameUnmutedAndUnread">Tidak dibisukan & Belum dibaca</string>
|
||||
<string name="FilterNameUnmutedAndUnreadDescription">Hanya pesan yang belum dibaca dari chat yang tidak dibisukan</string>
|
||||
<string name="IgnoreMutedCount">Abaikan hitungan pesan dibisukan / belum dibaca di tab folder</string>
|
||||
<string name="DialogsSettings">Pengaturan Obrolan</string>
|
||||
<string name="SortMenu">Pengaturan Urutan Obrolan</string>
|
||||
<string name="SortByUnread">Urutkan berdasarkan Belum dibaca</string>
|
||||
<string name="SortByUnmuted">Urutkan berdasarkan Tidak Dibisukan</string>
|
||||
<string name="SortByUser">Urutkan berdasarkan Pengguna</string>
|
||||
<string name="SortByContacts">Urutkan berdasarkan Kontak</string>
|
||||
<string name="NekoXPushService">Layanan Push NekoX</string>
|
||||
<string name="EnablePushAlert">Harap aktifkan \"Layanan Push NekoX\"</string>
|
||||
<string name="DisablePushAlert">Harap nonaktifkan \"Layanan Push NekoX\"</string>
|
||||
<string name="MIUIPermissionNote">Untuk pengguna MIUI, harap aktifkan izin mulai otomatis untuk NekoX untuk menerima pemberitahuan secara normal.</string>
|
||||
<string name="DisableUndo">Nonaktifkan Batalkan</string>
|
||||
<string name="DisableSystemAccount">Nonaktifkan Akun Sistem</string>
|
||||
<string name="FilterMenu">Menu Filter Obrolan</string>
|
||||
<string name="DisableProxyWhenVpnEnabled">Nonaktifkan proxy saat VPN diaktifkan</string>
|
||||
<string name="SkipOpenLinkConfirm">Lewati konfirmasi saat membuka tautan</string>
|
||||
<string name="DeleteAllInChat">Hapus semua pesan dalam obrolan</string>
|
||||
<string name="DeleteAllInChatAlert">Peringatan! Ini akan menghapus **semua pesan** di obrolan ini untuk **semua** peserta.</string>
|
||||
<string name="UnblockAll">Buka Semua Blokiran</string>
|
||||
<string name="UnblockAllWarn">Anda yakin ingin membuka blokir untuk **semua pengguna dan bot**?</string>
|
||||
<string name="BlockedListEmpty">Anda belum memblokir siapa pun :)</string>
|
||||
<string name="ProxyTypeVmess">Vmess Proxy</string>
|
||||
<string name="AddProxySocks5">Tambahkan Socks5 Proxy</string>
|
||||
<string name="AddProxyTelegram">Tambahkan MTProto Proxy</string>
|
||||
<string name="AddProxyVmess">Tambahkan Vmess Proxy</string>
|
||||
<string name="AddProxySS">Tambahkan Shadowsocks Proxy</string>
|
||||
<string name="AddProxySSR">Tambahkan ShadowsocksR Proxy</string>
|
||||
<string name="EditProxy">Edit Proxy</string>
|
||||
<string name="ShareProxy">Bagikan Proxy</string>
|
||||
<string name="ProxyDelete">Hapus Proxy</string>
|
||||
<string name="ProxyInfoVmess">Pengaturan Vmess Proxy</string>
|
||||
<string name="VmessUserId">ID pengguna</string>
|
||||
<string name="VmessAlterId">Ubah ID</string>
|
||||
<string name="VmessSecurity">Keamanan</string>
|
||||
<string name="VmessNetwork">Jaringan</string>
|
||||
<string name="VmessHeadType">Head Type</string>
|
||||
<string name="VmessRequestHost">Permintaan Host / Keamanan QUIC</string>
|
||||
<string name="VmessPath">Path / Kunci QUIC</string>
|
||||
<string name="VmessTls">Gunakan TLS</string>
|
||||
<string name="ProxyInfoSS">Pengaturan Shadowsocks Proxy</string>
|
||||
<string name="SSPassword">Kata sandi</string>
|
||||
<string name="SSMethod">Metode Enkripsi</string>
|
||||
<string name="ProxyInfoSSR">Pengaturan ShadowsocksR Proxy</string>
|
||||
<string name="SSRProtocol">Protokol</string>
|
||||
<string name="SSRProtocolParams">Parameter protokol</string>
|
||||
<string name="SSRObfs">Obfs</string>
|
||||
<string name="SSRObfsParam">Parameter Obfs</string>
|
||||
<string name="ProxyRemarks">Catatan</string>
|
||||
<string name="RetestPing">Test ulang ping ke semua server</string>
|
||||
<string name="ReorderByPing">Susun ulang server dari ping</string>
|
||||
<string name="ExportProxies">Ekspor server ke berkas</string>
|
||||
<string name="ImportProxies">Impor server dari berkas</string>
|
||||
<string name="ImportProxyList">Impor server proxy</string>
|
||||
<string name="ProxySubscription">Berlangganan Proxy</string>
|
||||
<string name="ProxySubDetails">Detail Berlangganan</string>
|
||||
<string name="SubscriptionUrls">Url</string>
|
||||
<string name="SubscriptionUpdating">Memperbarui Langganan</string>
|
||||
<string name="SubscriptionDelete">Hapus Langganan</string>
|
||||
<string name="ExportStickers">Ekspor Stiker</string>
|
||||
<string name="ImportStickers">Impor stiker dari berkas</string>
|
||||
<string name="ImportStickersList">Impor stiker</string>
|
||||
<string name="StickerSets">Set Stiker</string>
|
||||
<string name="InvalidStickersFile">File stiker tidak valid: </string>
|
||||
<string name="InvalidProxyFile">File daftar proxy tidak valid: </string>
|
||||
<string name="ImportedProxies">Impor proxy server: </string>
|
||||
<string name="ErrorsInImport">Kesalahan impor: </string>
|
||||
<string name="NoProxy">Anda belum menambahkan server proxy.</string>
|
||||
<string name="DeleteAllServer">Hapus semua server</string>
|
||||
<string name="DeleteUnavailableServer">Hapus server yang tidak tersedia</string>
|
||||
<string name="DeleteAllServerConfirm">Anda yakin ingin **menghapus semua server**?</string>
|
||||
<string name="DeleteUnavailableServerConfirm">Anda yakin ingin **menghapus semua server tidak tersedia**?</string>
|
||||
<string name="MinApi21Required">Maaf, anda memerlukan setidaknya Android 5 (API 21).</string>
|
||||
<string name="ImportProxyFromClipboard">Impor Dari Papan Klip</string>
|
||||
<string name="BrokenLink">Tidak Dikenal / Tautan Rusak</string>
|
||||
<string name="ShareQRCode">Kode QR</string>
|
||||
<string name="ScanQRCode">Pindai Kode QR</string>
|
||||
<string name="NoQrFound">Tidak ditemukan Kode QR</string>
|
||||
<string name="EnableDeveloperMode">Aktifkan Mode Pengembang</string>
|
||||
<string name="DisableDeveloperMode">Nonaktifkan Mode Pengembang</string>
|
||||
<string name="DeveloperSettings">Pengaturan Pengembang</string>
|
||||
<string name="LoginSettings">Pengaturan Login</string>
|
||||
<string name="NekoXFaq">NekoX FAQ</string>
|
||||
</resources>
|
|
@ -1,20 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="CustomApi">API personalizada</string>
|
||||
<string name="UseCustomApiNotice">Efetue login usando a API personalizada. Se você não conseguir se registrar ou efetuar login, isso pode ajudar.\n\nNota: o fcm não vai funcionar se você estiver usando a versão de final.</string>
|
||||
<string name="CustomApiNo">Não use a API personalizada</string>
|
||||
<string name="CustomApiOfficial">Telegram Android</string>
|
||||
<string name="CustomApiTGX">Telegram Android X</string>
|
||||
<string name="CustomApiInput">Entrada manual</string>
|
||||
<string name="CustomBackend">Back-end personalizado</string>
|
||||
<string name="CustomBackendNotice">Essa função é fornecida apenas para usuários experientes; se você não souber o que as elas representam, apenas ignore.</string>
|
||||
<string name="CustomBackendProduction">Data Center de Produção Oficial</string>
|
||||
<string name="CustomBackendTestDC">DataCenter Oficial de Teste</string>
|
||||
<string name="CustomBackendIpv4">Endereço Ipv4</string>
|
||||
<string name="CustomBackendIpv6">Endereço Ipv6</string>
|
||||
<string name="CustomBackendLayer">Camada</string>
|
||||
<string name="CustomBackendPublicKey">Chave pública</string>
|
||||
<string name="CustomBackendFingerprint">Chave Impressão digital</string>
|
||||
<string name="CachePath">Diretório de cache</string>
|
||||
<string name="AllowFlashCall">Permitir chamada rápida</string>
|
||||
<string name="ChangeTranslateProvider">Alterar Provedor</string>
|
||||
<string name="ProviderYandex">Yandex.Translate</string>
|
||||
<string name="GoogleCloudTransKey">Chave de tradução do Google Cloud</string>
|
||||
<string name="GoogleCloudTransKeyNotice">Se você configurar um Google Cloud Trans Key, a API de conversão em nuvem será chamada em vez de enviar um formulário falso para a versão da Web durante a tradução (tráfego mais rápido, estável e leve).</string>
|
||||
<string name="TransToLang">Idioma de destino para tradução</string>
|
||||
<string name="TransInputToLang">Idioma de destino da tradução para envio de mensagens</string>
|
||||
<string name="More">Mais</string>
|
||||
<string name="NekoXUpdatesChannel">Canal de atualizações do NekoX</string>
|
||||
<string name="ShowIdAndDc">Mostrar ID / DC no perfil</string>
|
||||
<string name="UseDefaultTheme">Usar o tema padrão *</string>
|
||||
<string name="NightMode">Modo Noturno</string>
|
||||
<string name="PrivacyNotice">Aviso de privacidade</string>
|
||||
<string name="PrivacyNoticePhoneVisible">Identificamos que seu número de celular está visível para qualquer pessoa, o que pode fazer com que hackers controlados pelo governo encontrem sua verdadeira identidade. Por favor, desative!</string>
|
||||
<string name="PrivacyNoticeAddByPhone">Identificamos que você não desativou a opção \"Permitir que me encontrem através do número de telefone\", o que pode fazer com que um hacker controlado pelo governo encontre sua verdadeira identidade. Por favor, desative!</string>
|
||||
<string name="PrivacyNoticeP2p">Identificamos que você não desativou a configuração \"Permitir chamadas P2p\", o que pode fazer com que hackers controlados pelo governo encontrem sua verdadeira identidade, desligue-a!</string>
|
||||
<string name="PrivacyNotice2fa">Foi detectado que você não definiu uma senha, o que pode fazer com que os hackers controlados pelo governo encontrem sua verdadeira identidade, por favor, defina uma!</string>
|
||||
<string name="ApplySuggestion">OK, Aplicar</string>
|
||||
<string name="DoNotRemindAgain">Não lembre novamente</string>
|
||||
<string name="InstantViewTransWithWeb">Não é possível traduzir InstantView com o tradutor web</string>
|
||||
<string name="RemoveTitleEmoji">Remover emoji no título</string>
|
||||
<string name="NekoXProxy">Proxy Público do NekoX</string>
|
||||
<string name="PublicPrefix">Público</string>
|
||||
<string name="DisableChatAction">Não enviar meu status de entrada</string>
|
||||
<string name="FakeScreenshot">Simular captura de tela</string>
|
||||
<string name="Import">Importar</string>
|
||||
<string name="FilterNameUsers">Usuários</string>
|
||||
<string name="FilterNameUsersDescription">Apenas mensagens de conversas privadas</string>
|
||||
<string name="FilterNameContacts">Contatos</string>
|
||||
|
@ -84,6 +111,16 @@
|
|||
<string name="ExportProxies">Exportar servidores para arquivo</string>
|
||||
<string name="ImportProxies">Importar servidores do arquivo</string>
|
||||
<string name="ImportProxyList">Importar servidores proxy</string>
|
||||
<string name="ProxySubscription">Assinatura do Proxy</string>
|
||||
<string name="ProxySubDetails">Detalhes da assinatura</string>
|
||||
<string name="SubscriptionUrls">URLs</string>
|
||||
<string name="SubscriptionUpdating">Atualização da assinatura</string>
|
||||
<string name="SubscriptionDelete">Excluir assinatura</string>
|
||||
<string name="ExportStickers">Exportar Stickers</string>
|
||||
<string name="ImportStickers">Importar stickers de arquivo</string>
|
||||
<string name="ImportStickersList">Importar Stickers</string>
|
||||
<string name="StickerSets">Pacote de Sticker</string>
|
||||
<string name="InvalidStickersFile">Arquivo de stickers inválido: </string>
|
||||
<string name="InvalidProxyFile">Arquivo de lista de proxy inválido: </string>
|
||||
<string name="ImportedProxies">Servidores proxy importados: </string>
|
||||
<string name="ErrorsInImport">Erros de importação: </string>
|
||||
|
|
|
@ -10,6 +10,15 @@
|
|||
<string name="CustomApiTGX">Telegram Android X</string>
|
||||
<string name="CustomApiInput">Manual input</string>
|
||||
|
||||
<string name="CheckUpdate">Check Update</string>
|
||||
<string name="NoUpdate">No update found</string>
|
||||
<string name="UpdateAvailable">New update available</string>
|
||||
<string name="Download">Download</string>
|
||||
<string name="DownloadFailed">Download Failed</string>
|
||||
<string name="Install">Install</string>
|
||||
<string name="Ignore">Ignore</string>
|
||||
<string name="UpdateDownloaded">An update has just been downloaded.</string>
|
||||
|
||||
<string name="CustomBackend">Custom Backend</string>
|
||||
<string name="CustomBackendNotice">This function is only provided for expert users, if you don\'t know what the following options represent, just ignore it.</string>
|
||||
<string name="CustomBackendProduction">Official Production DataCenter</string>
|
||||
|
|
|
@ -9,7 +9,7 @@ buildscript {
|
|||
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72"
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Fri May 01 23:57:46 CST 2020
|
||||
#Mon May 04 18:56:10 CST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-rc-4-all.zip
|
||||
|
|
Loading…
Reference in New Issue