最新一次版本提交
1
winwaynew/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
85
winwaynew/build.gradle
Normal file
@@ -0,0 +1,85 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'com.google.gms.google-services'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "just.way"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 44
|
||||
versionName "3.2.4"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file('justlet.jks')
|
||||
storePassword "123456"
|
||||
keyAlias 'key0'
|
||||
keyPassword "123456"
|
||||
}
|
||||
release {
|
||||
storeFile file('justlet.jks')
|
||||
storePassword "123456"
|
||||
keyAlias 'key0'
|
||||
keyPassword "123456"
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
testImplementation 'junit:junit:4.+'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
implementation files('libs\\tbs_sdk_thirdapp_v4.3.0.386_44286_20230210.jar')
|
||||
|
||||
// okhttp相关库
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||
|
||||
// JSON解析库
|
||||
implementation 'com.google.code.gson:gson:2.9.0'
|
||||
implementation 'com.alibaba:fastjson:1.1.71.android'
|
||||
api 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||
api 'com.squareup.retrofit2:converter-scalars:2.3.0'
|
||||
api 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
api 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
|
||||
api 'io.reactivex.rxjava2:rxjava:2.1.16'
|
||||
api 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||
implementation 'com.github.Justson.AgentWeb:agentweb-core:v5.0.6-androidx' // (必选)
|
||||
implementation 'com.github.Justson.AgentWeb:agentweb-filechooser:v5.0.6-androidx' // (可选)
|
||||
implementation 'com.github.Justson:Downloader:v5.0.4-androidx'
|
||||
//implementation 'com.tencent.tbs:tbssdk:44286'
|
||||
// sdk 33
|
||||
// implementation platform('com.google.firebase:firebase-bom:32.7.0')
|
||||
// Firebase Cloud Messaging
|
||||
// implementation("com.google.firebase:firebase-messaging")
|
||||
// implementation("com.google.firebase:firebase-analytics")
|
||||
|
||||
implementation("com.google.firebase:firebase-messaging:23.0.0")
|
||||
implementation("com.google.firebase:firebase-analytics:20.0.0")
|
||||
// implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0' //直接启动模式
|
||||
|
||||
implementation("com.github.bumptech.glide:glide:4.13.1")
|
||||
}
|
||||
29
winwaynew/google-services.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "66230459052",
|
||||
"project_id": "just-way-eb6ae",
|
||||
"storage_bucket": "just-way-eb6ae.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:66230459052:android:1782975166f8b0bb35dd09",
|
||||
"android_client_info": {
|
||||
"package_name": "just.way"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyAMJUxbpF8L-HqRKzcm4v8PErxBgo8UAMI"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
BIN
winwaynew/jiyoukey
Normal file
BIN
winwaynew/justlet.jks
Normal file
BIN
winwaynew/libs/tbs_sdk_thirdapp_v4.3.0.386_44286_20230210.jar
Normal file
32
winwaynew/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# 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
|
||||
|
||||
-dontwarn dalvik.**
|
||||
-dontwarn com.tencent.smtt.**
|
||||
|
||||
-keep class com.tencent.smtt.** {
|
||||
*;
|
||||
}
|
||||
|
||||
-keep class com.tencent.tbs.** {
|
||||
*;
|
||||
}
|
||||
18
winwaynew/release/output-metadata.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 2,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "just.way",
|
||||
"variantName": "processReleaseResources",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"versionCode": 44,
|
||||
"versionName": "3.2.4",
|
||||
"outputFile": "winwaynew-release.apk"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
winwaynew/release/winway-3.1.7-37.apk
Normal file
BIN
winwaynew/release/winway-calculator-v3.2.2-42.apk
Normal file
BIN
winwaynew/release/winway-calculator-v3.2.3-43.apk
Normal file
BIN
winwaynew/release/winway-calculator-v3.2.4-44.apk
Normal file
BIN
winwaynew/release/winway-calculator_44.apk
Normal file
@@ -0,0 +1,26 @@
|
||||
package Tptogiar.calculcator;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("Tptogiar.calculcator", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
159
winwaynew/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="just.way">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera2"
|
||||
android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<!-- 多媒体相关 -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<!-- 8.0+系统需要-->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<!--推送权限-->
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<!-- <uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />-->
|
||||
<!-- <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />-->
|
||||
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" />-->
|
||||
|
||||
|
||||
<!-- <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />-->
|
||||
<!-- <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.camera.autofocus" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.camera.front" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.camera" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.camera.level.full" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.camera.capability.raw" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.camera.any" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.microphone" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.camera2" android:required="true" />-->
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
||||
</intent>
|
||||
</queries>
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="@mipmap/jisuanqi_logo"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/jisuanqi_logo"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Calculcator"
|
||||
android:usesCleartextTraffic="true">
|
||||
<!-- 计算器入口-->
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
||||
<!-- <activity-alias-->
|
||||
<!-- android:name=".MainActivityNew"-->
|
||||
<!-- android:icon="@mipmap/winway"-->
|
||||
<!-- android:roundIcon="@mipmap/winway"-->
|
||||
<!-- android:label="@string/app_name1"-->
|
||||
<!-- android:targetActivity=".MainActivity"-->
|
||||
<!-- android:enabled="false"-->
|
||||
<!-- android:exported="true"-->
|
||||
<!-- android:configChanges="orientation|navigation|keyboardHidden"-->
|
||||
<!-- android:launchMode="singleTop"-->
|
||||
<!-- android:excludeFromRecents="true"-->
|
||||
<!-- android:screenOrientation="portrait">-->
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <action android:name="android.intent.action.MAIN" />-->
|
||||
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
|
||||
<!-- </intent-filter>-->
|
||||
<!-- </activity-alias>-->
|
||||
|
||||
<activity android:name=".StartActivity">
|
||||
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".MainActivity2"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:hardwareAccelerated="true"
|
||||
android:theme="@style/AppThemeStart">
|
||||
|
||||
<!-- <intent-filter>-->
|
||||
|
||||
<!-- <action android:name="android.intent.action.MAIN" />-->
|
||||
|
||||
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
|
||||
|
||||
<!-- <action android:name="com.google.firebase.MESSAGING_EVENT" />-->
|
||||
<!-- </intent-filter>-->
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".WebViewActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:hardwareAccelerated="true" />
|
||||
|
||||
<activity
|
||||
android:name=".WebView2Activity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:hardwareAccelerated="true" />
|
||||
|
||||
<service android:name=".appdown.service.DownloadService" />
|
||||
|
||||
<provider
|
||||
android:name=".appdown.provider.AppUpdaterFileProvider"
|
||||
android:authorities="just.way.appdown.provider.AppUpdaterFileProvider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/app_updater_paths" />
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
|
||||
android:label="dexopt"
|
||||
android:process=":dexopt" />
|
||||
|
||||
|
||||
<!-- android:directBootAware="true" 为应用启用消息处理直接启动模式-->
|
||||
<service
|
||||
android:name=".MyFirebaseMessageingService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
|
||||
See README(https://goo.gl/l4GJaQ) for more. 设置推送默认图标 和颜色-->
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||
android:resource="@mipmap/jisuanqi_logo" />
|
||||
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
|
||||
notification message. See README(https://goo.gl/6BKBk7) for more. -->
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_color"
|
||||
android:resource="@color/winway" />
|
||||
|
||||
<!-- 还可设置推送渠道 -->
|
||||
<!-- <meta-data-->
|
||||
<!-- android:name="com.google.firebase.messaging.default_notification_channel_id"-->
|
||||
<!-- android:value="@string/default_notification_channel_id" />-->
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
124
winwaynew/src/main/java/just/way/ActionConfirmDialog.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package just.way;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
/**
|
||||
* 通用弹窗
|
||||
*/
|
||||
public class ActionConfirmDialog extends Dialog {
|
||||
private final Context context;
|
||||
private View lineV;
|
||||
|
||||
private TextView contentTv;
|
||||
private TextView cancelTv;
|
||||
private TextView sumbitTv;
|
||||
String title;
|
||||
String content;
|
||||
String cancel = null;
|
||||
String sure = null;
|
||||
boolean showCancel = true;
|
||||
OnToActionListener onToActionListener;
|
||||
|
||||
public interface OnToActionListener {
|
||||
void toSumbit();
|
||||
void toCancel();
|
||||
|
||||
}
|
||||
|
||||
public void setOnToActionListener(OnToActionListener onNextCallListener) {
|
||||
this.onToActionListener = onNextCallListener;
|
||||
}
|
||||
|
||||
|
||||
public ActionConfirmDialog(Context context, String content,boolean showCancel) {
|
||||
super(context, R.style.MaterialDesignDialog);
|
||||
this.context = context;
|
||||
this.content = content;
|
||||
this.showCancel = showCancel;
|
||||
}
|
||||
public ActionConfirmDialog(Context context, String content, String cancel, String sure) {
|
||||
super(context, R.style.MaterialDesignDialog);
|
||||
this.context = context;
|
||||
this.content = content;
|
||||
this.cancel = cancel;
|
||||
this.sure = sure;
|
||||
}
|
||||
|
||||
public ActionConfirmDialog(Context context, String content, String cancel, String sure,boolean showCancel) {
|
||||
super(context, R.style.MaterialDesignDialog);
|
||||
this.context = context;
|
||||
this.content = content;
|
||||
this.cancel = cancel;
|
||||
this.sure = sure;
|
||||
this.showCancel = showCancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.dialog_action_confirm);
|
||||
|
||||
contentTv = (TextView) findViewById(R.id.content_tv);
|
||||
cancelTv = (TextView) findViewById(R.id.cancel_tv);
|
||||
sumbitTv = (TextView) findViewById(R.id.sumbit_tv);
|
||||
|
||||
lineV = (View) findViewById(R.id.line_v);
|
||||
|
||||
contentTv.setText(content);
|
||||
contentTv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
//这个监听的回调是异步的,在监听完以后一定要把绘制监听移除,不然这个会一直回调,导致界面错乱
|
||||
contentTv.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
int line = contentTv.getLineCount();
|
||||
if(line>1){
|
||||
contentTv.setGravity(Gravity.LEFT|Gravity.CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if(!TextUtils.isEmpty(cancel)){
|
||||
cancelTv.setText(cancel);
|
||||
}
|
||||
if(!TextUtils.isEmpty(sure)){
|
||||
sumbitTv.setText(sure);
|
||||
}
|
||||
if(!showCancel){
|
||||
cancelTv.setVisibility(View.GONE);
|
||||
lineV.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
sumbitTv.setOnClickListener(v -> {
|
||||
dismiss();
|
||||
if(onToActionListener!=null){
|
||||
onToActionListener.toSumbit();
|
||||
}
|
||||
});
|
||||
cancelTv.setOnClickListener(v -> {
|
||||
dismiss();
|
||||
if(onToActionListener!=null){
|
||||
onToActionListener.toCancel();
|
||||
}
|
||||
});
|
||||
|
||||
Window window = getWindow();
|
||||
WindowManager.LayoutParams wlp = window.getAttributes();
|
||||
wlp.gravity = Gravity.CENTER;
|
||||
wlp.width = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
window.setAttributes(wlp);
|
||||
}
|
||||
|
||||
}
|
||||
68
winwaynew/src/main/java/just/way/Api.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package just.way;
|
||||
|
||||
import java.net.Proxy;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
|
||||
/**
|
||||
* 项目名: TODO-MVVM
|
||||
* 包名 com.azhon.mvvm.api
|
||||
* 文件名: Api
|
||||
* 创建时间: 2019-03-27 on 14:56
|
||||
* 描述: TODO 使用Retrofit基础服务
|
||||
*
|
||||
* @author
|
||||
*/
|
||||
|
||||
public class Api extends BaseApi {
|
||||
|
||||
private static final long CONNECT_TIMEOUT = 15;
|
||||
private static final long READ_TIMEOUT = 15;
|
||||
private static final long WRITE_TIMEOUT = 15;
|
||||
|
||||
/**
|
||||
* 静态内部类单例
|
||||
*/
|
||||
private static class ApiHolder {
|
||||
private static Api api = new Api();
|
||||
private final static ApiService apiService = api.initRetrofit(ApiService.URL)
|
||||
.create(ApiService.class);
|
||||
|
||||
}
|
||||
|
||||
public static ApiService getInstance() {
|
||||
return ApiHolder.apiService;
|
||||
}
|
||||
/**
|
||||
* 做自己需要的操作
|
||||
*/
|
||||
@Override
|
||||
protected OkHttpClient setClient() {
|
||||
OkHttpClient.Builder builder;
|
||||
builder = new OkHttpClient()
|
||||
.newBuilder();
|
||||
//禁止使用代理抓取数据
|
||||
builder.proxy(Proxy.NO_PROXY);
|
||||
//设置超时
|
||||
builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
|
||||
builder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
|
||||
builder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);
|
||||
//错误重连
|
||||
builder.retryOnConnectionFailure(true);
|
||||
|
||||
// if (Config.IS_DEBUG) {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(message -> {
|
||||
String text = message;
|
||||
LogUtils.i("OKHttp111111-----", text);
|
||||
|
||||
});
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
builder.addInterceptor(interceptor);
|
||||
// }
|
||||
return builder.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
108
winwaynew/src/main/java/just/way/ApiService.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package just.way;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import okhttp3.RequestBody;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.PUT;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface ApiService {
|
||||
//String URL = "http://8.218.177.7:18000/";
|
||||
String URL = "https://api.liulao.top/";
|
||||
// String URL = "http://192.168.8.184:8000/";
|
||||
|
||||
|
||||
// String VERSIONURL="http://download.2ltop.com/urlset4/"; // 没有计算器的
|
||||
String VERSIONURL = "http://download.2ltop.com/urlset3/";
|
||||
|
||||
|
||||
@GET("api/system/applicationConf")
|
||||
Observable<Result<DataInfo>> geUrlNew(@Query("userId") int userId);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 搜集登录手机号
|
||||
*/
|
||||
@POST("app/loginUser")
|
||||
Observable<Result> appLoginUser(@Body Map<String, Object> map);
|
||||
|
||||
|
||||
/**
|
||||
* 上传通讯录
|
||||
*/
|
||||
@Headers("Content-Type:application/json")
|
||||
@POST("api/customer/customers")
|
||||
Observable<Result> readContact(@Body RequestBody requestBody);
|
||||
|
||||
/**
|
||||
* 統計下載量
|
||||
*/
|
||||
@PUT("api/statistics/downloads")
|
||||
Observable<Result> downloadNumbers(@Body Map<String, Object> map);
|
||||
|
||||
/**
|
||||
* 每日活跃统计
|
||||
*/
|
||||
@PUT("api/statistics/use")
|
||||
Observable<Result> totalTongJi(@Body Map<String, Object> map);
|
||||
|
||||
// /**
|
||||
// * 验证邀请码
|
||||
// */
|
||||
// @PUT("api/invite/send")
|
||||
// Observable<Result<InviteInfo>> checkInvited(@Body Map<String, Object> map);
|
||||
//
|
||||
// /**
|
||||
// * 获取我的邀请码
|
||||
// */
|
||||
// @POST("api/invite/my")
|
||||
// Observable<Result<InviteInfo>> getMyInvited(@Body Map<String, Object> map);
|
||||
|
||||
/**
|
||||
* 统计通知
|
||||
*/
|
||||
@POST("api/push/statistics")
|
||||
Observable<Result> totalNotify(@Body Map<String, Object> map);
|
||||
|
||||
// /**
|
||||
// * 获取邀请记录
|
||||
// */
|
||||
// @GET("/api/invite/records")
|
||||
// Observable<Result<InviteListInfo>> getRecords(@Query("code") String inviteCode, @Query("page") int page, @Query("size") int size);
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 获取提现记录
|
||||
// */
|
||||
// @GET("/api/withdraw")
|
||||
// Observable<Result<WithDrawListInfo>> getWithDrawRecords(@Query("inviteCode") String inviteCode, @Query("page") int page, @Query("size") int size);
|
||||
|
||||
|
||||
/**
|
||||
* 申请提现
|
||||
*/
|
||||
@POST("/api/withdraw/apply")
|
||||
Observable<Result> sendWithDrawApply(@Body Map<String, Object> map);
|
||||
|
||||
/**
|
||||
* 申请提现
|
||||
*/
|
||||
@POST("/api/withdraw")
|
||||
Observable<Result> sendBankInfo(@Body Map<String, Object> map);
|
||||
|
||||
// /**
|
||||
// * 获取银行列表
|
||||
// */
|
||||
// @GET("/api/withdraw/banks")
|
||||
// Observable<Result<Map<String, List<BankInfo>>>> getBankInfoList();
|
||||
|
||||
}
|
||||
46
winwaynew/src/main/java/just/way/BaseApi.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package just.way;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import retrofit2.converter.scalars.ScalarsConverterFactory;
|
||||
|
||||
/**
|
||||
* 项目名: TODO-MVVM
|
||||
* 包名 com.azhon.basic.retrofit
|
||||
* 文件名: BaseApi
|
||||
* 创建时间: 2019-03-27 on 14:52
|
||||
* 描述: TODO 封装基础的Retrofit
|
||||
*
|
||||
* @author
|
||||
*/
|
||||
|
||||
public abstract class BaseApi {
|
||||
|
||||
/**
|
||||
* 初始化Retrofit
|
||||
*/
|
||||
public Retrofit initRetrofit(String baseUrl) {
|
||||
Retrofit.Builder builder = new Retrofit.Builder();
|
||||
//支持返回Call<String>
|
||||
builder.addConverterFactory(ScalarsConverterFactory.create());
|
||||
//支持直接格式化json返回Bean对象
|
||||
builder.addConverterFactory(GsonConverterFactory.create());
|
||||
//支持RxJava
|
||||
builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
|
||||
builder.baseUrl(baseUrl);
|
||||
OkHttpClient client = setClient();
|
||||
if (client != null) {
|
||||
builder.client(client);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置OkHttpClient,添加拦截器等
|
||||
*
|
||||
* @return 可以返回为null
|
||||
*/
|
||||
protected abstract OkHttpClient setClient();
|
||||
}
|
||||
115
winwaynew/src/main/java/just/way/BaseObserver.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package just.way;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import io.reactivex.observers.DisposableObserver;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
public abstract class BaseObserver<T> extends DisposableObserver<T> {
|
||||
/**
|
||||
* 解析数据失败
|
||||
*/
|
||||
public static final int PARSE_ERROR = 1001;
|
||||
/**
|
||||
* 网络问题
|
||||
*/
|
||||
public static final int BAD_NETWORK = 1002;
|
||||
/**
|
||||
* 连接错误
|
||||
*/
|
||||
public static final int CONNECT_ERROR = 1003;
|
||||
/**
|
||||
* 连接超时
|
||||
*/
|
||||
public static final int CONNECT_TIMEOUT = 1004;
|
||||
|
||||
@Override
|
||||
public void onNext(T o) {
|
||||
if (o instanceof String) {
|
||||
onError(0, "接口解析失败");
|
||||
// LogUtils.i("返回个string就没意思了");
|
||||
} else {
|
||||
Result model = (Result) o;
|
||||
if (model.isSuccessful()) {
|
||||
onSuccess(o);
|
||||
} else {
|
||||
onError2(o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
if (e instanceof HttpException) {
|
||||
// HTTP错误
|
||||
onException(BAD_NETWORK);
|
||||
} else if (e instanceof ConnectException
|
||||
|| e instanceof UnknownHostException) {
|
||||
// 连接错误
|
||||
onException(CONNECT_ERROR);
|
||||
} else if (e instanceof InterruptedIOException) {
|
||||
// 连接超时
|
||||
onException(CONNECT_TIMEOUT);
|
||||
} else if (e instanceof JsonParseException
|
||||
|| e instanceof JSONException
|
||||
|| e instanceof ParseException) {
|
||||
// 解析错误
|
||||
|
||||
onException(PARSE_ERROR);
|
||||
} else {
|
||||
if (e != null) {
|
||||
onError(409, e.toString());
|
||||
} else {
|
||||
onError(407, "未知错误");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onException(int unknownError) {
|
||||
switch (unknownError) {
|
||||
case CONNECT_ERROR:
|
||||
onError(CONNECT_ERROR, "连接错误");
|
||||
break;
|
||||
|
||||
case CONNECT_TIMEOUT:
|
||||
onError(CONNECT_TIMEOUT, "连接超时");
|
||||
break;
|
||||
|
||||
case BAD_NETWORK:
|
||||
onError(BAD_NETWORK, "网络问题");
|
||||
break;
|
||||
|
||||
case PARSE_ERROR:
|
||||
onError(PARSE_ERROR, "宇宙也是有尽头的");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
|
||||
public abstract void onSuccess(T o);
|
||||
|
||||
public abstract void onError(int code, String msg);
|
||||
|
||||
public abstract void onError2(T o);
|
||||
|
||||
}
|
||||
321
winwaynew/src/main/java/just/way/CircleImageView.java
Normal file
@@ -0,0 +1,321 @@
|
||||
package just.way;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
|
||||
public class CircleImageView extends AppCompatImageView {
|
||||
// paint when user press
|
||||
private Paint pressPaint;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
// default bitmap config
|
||||
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
|
||||
private static final int COLORDRAWABLE_DIMENSION = 1;
|
||||
|
||||
// border color
|
||||
private int borderColor;
|
||||
// width of border
|
||||
private int borderWidth;
|
||||
// alpha when pressed
|
||||
private int pressAlpha;
|
||||
// color when pressed
|
||||
private int pressColor;
|
||||
// radius
|
||||
private int radius;
|
||||
// rectangle or round, 1 is circle, 2 is rectangle
|
||||
private int shapeType;
|
||||
|
||||
public CircleImageView(Context context) {
|
||||
super(context);
|
||||
init(context, null);
|
||||
}
|
||||
|
||||
public CircleImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
//init the value
|
||||
borderWidth = 0;
|
||||
borderColor = 0xddffffff;
|
||||
pressAlpha = 0x42;
|
||||
pressColor = 0x42000000;
|
||||
radius = 16;
|
||||
shapeType = 0;
|
||||
|
||||
// get attribute of EaseImageView
|
||||
if (attrs != null) {
|
||||
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
|
||||
borderColor = array.getColor(R.styleable.CircleImageView_ease_border_color, borderColor);
|
||||
borderWidth = array.getDimensionPixelOffset(R.styleable.CircleImageView_ease_border_width, borderWidth);
|
||||
pressAlpha = array.getInteger(R.styleable.CircleImageView_ease_press_alpha, pressAlpha);
|
||||
pressColor = array.getColor(R.styleable.CircleImageView_ease_press_color, pressColor);
|
||||
radius = array.getDimensionPixelOffset(R.styleable.CircleImageView_ease_radius, radius);
|
||||
shapeType = array.getInteger(R.styleable.CircleImageView_es_shape_type, shapeType);
|
||||
array.recycle();
|
||||
}
|
||||
|
||||
// set paint when pressed
|
||||
pressPaint = new Paint();
|
||||
pressPaint.setAntiAlias(true);
|
||||
pressPaint.setStyle(Paint.Style.FILL);
|
||||
pressPaint.setColor(pressColor);
|
||||
pressPaint.setAlpha(0);
|
||||
pressPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
setDrawingCacheEnabled(true);
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
|
||||
if (shapeType == 0) {
|
||||
super.onDraw(canvas);
|
||||
return;
|
||||
}
|
||||
Drawable drawable = getDrawable();
|
||||
if (drawable == null) {
|
||||
return;
|
||||
}
|
||||
// the width and height is in xml file
|
||||
if (getWidth() == 0 || getHeight() == 0) {
|
||||
return;
|
||||
}
|
||||
Bitmap bitmap = getBitmapFromDrawable(drawable);
|
||||
drawDrawable(canvas, bitmap);
|
||||
|
||||
if (isClickable()) {
|
||||
drawPress(canvas);
|
||||
}
|
||||
drawBorder(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw Rounded Rectangle
|
||||
*
|
||||
* @param canvas
|
||||
* @param bitmap
|
||||
*/
|
||||
@SuppressLint("WrongConstant")
|
||||
private void drawDrawable(Canvas canvas, Bitmap bitmap) {
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(0xffffffff);
|
||||
paint.setAntiAlias(true); //smooths out the edges of what is being drawn
|
||||
PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
|
||||
// set flags
|
||||
int saveFlags = Canvas.ALL_SAVE_FLAG
|
||||
;
|
||||
canvas.saveLayer(0, 0, width, height, null, saveFlags);
|
||||
|
||||
if (shapeType == 1) {
|
||||
canvas.drawCircle(width / 2, height / 2, width / 2 - 1, paint);
|
||||
} else if (shapeType == 2) {
|
||||
RectF rectf = new RectF(1, 1, getWidth() - 1, getHeight() - 1);
|
||||
canvas.drawRoundRect(rectf, radius + 1, radius + 1, paint);
|
||||
}
|
||||
|
||||
paint.setXfermode(xfermode);
|
||||
|
||||
float scaleWidth = ((float) getWidth()) / bitmap.getWidth();
|
||||
float scaleHeight = ((float) getHeight()) / bitmap.getHeight();
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(scaleWidth, scaleHeight);
|
||||
|
||||
//bitmap scale
|
||||
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
|
||||
canvas.drawBitmap(bitmap, 0, 0, paint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* draw the effect when pressed
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawPress(Canvas canvas) {
|
||||
// check is rectangle or circle
|
||||
if (shapeType == 1) {
|
||||
canvas.drawCircle(width / 2, height / 2, width / 2 - 1, pressPaint);
|
||||
} else if (shapeType == 2) {
|
||||
RectF rectF = new RectF(1, 1, width - 1, height - 1);
|
||||
canvas.drawRoundRect(rectF, radius + 1, radius + 1, pressPaint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* draw customized border
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawBorder(Canvas canvas) {
|
||||
if (borderWidth > 0) {
|
||||
Paint paint = new Paint();
|
||||
paint.setStrokeWidth(borderWidth);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setColor(borderColor);
|
||||
paint.setAntiAlias(true);
|
||||
// // check is rectangle or circle
|
||||
if (shapeType == 1) {
|
||||
canvas.drawCircle(width / 2, height / 2, (width - borderWidth) / 2, paint);
|
||||
} else if (shapeType == 2) {
|
||||
RectF rectf = new RectF(borderWidth / 2, borderWidth / 2, getWidth() - borderWidth / 2,
|
||||
getHeight() - borderWidth / 2);
|
||||
canvas.drawRoundRect(rectf, radius, radius, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* monitor the size change
|
||||
*
|
||||
* @param w
|
||||
* @param h
|
||||
* @param oldw
|
||||
* @param oldh
|
||||
*/
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* monitor if touched
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
pressPaint.setAlpha(pressAlpha);
|
||||
invalidate();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
pressPaint.setAlpha(0);
|
||||
invalidate();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
|
||||
break;
|
||||
default:
|
||||
pressPaint.setAlpha(0);
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param drawable
|
||||
* @return
|
||||
*/
|
||||
private Bitmap getBitmapFromDrawable(Drawable drawable) {
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
return ((BitmapDrawable) drawable).getBitmap();
|
||||
}
|
||||
|
||||
Bitmap bitmap;
|
||||
int width = Math.max(drawable.getIntrinsicWidth(), 2);
|
||||
int height = Math.max(drawable.getIntrinsicHeight(), 2);
|
||||
try {
|
||||
bitmap = Bitmap.createBitmap(width, height, BITMAP_CONFIG);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
bitmap = null;
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* set border color
|
||||
*
|
||||
* @param borderColor
|
||||
*/
|
||||
public void setBorderColor(int borderColor) {
|
||||
this.borderColor = borderColor;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* set border width
|
||||
*
|
||||
* @param borderWidth
|
||||
*/
|
||||
public void setBorderWidth(int borderWidth) {
|
||||
this.borderWidth = borderWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* set alpha when pressed
|
||||
*
|
||||
* @param pressAlpha
|
||||
*/
|
||||
public void setPressAlpha(int pressAlpha) {
|
||||
this.pressAlpha = pressAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* set color when pressed
|
||||
*
|
||||
* @param pressColor
|
||||
*/
|
||||
public void setPressColor(int pressColor) {
|
||||
this.pressColor = pressColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* set radius
|
||||
*
|
||||
* @param radius
|
||||
*/
|
||||
public void setRadius(int radius) {
|
||||
this.radius = radius;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* set shape,1 is circle, 2 is rectangle
|
||||
*
|
||||
* @param shapeType
|
||||
*/
|
||||
public void setShapeType(int shapeType) {
|
||||
this.shapeType = shapeType;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
29
winwaynew/src/main/java/just/way/ContactBean.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package just.way;
|
||||
|
||||
public class ContactBean {
|
||||
|
||||
public String name;
|
||||
public String phone;
|
||||
|
||||
|
||||
public ContactBean(String name, String phone) {
|
||||
this.name = name;
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
}
|
||||
53
winwaynew/src/main/java/just/way/DataInfo.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package just.way;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class DataInfo implements Serializable {
|
||||
|
||||
|
||||
public String apkUrl;
|
||||
public String description;
|
||||
public int forceUpdate;
|
||||
public String url;
|
||||
public String versionCode;
|
||||
|
||||
public String getApkUrl() {
|
||||
return apkUrl;
|
||||
}
|
||||
|
||||
public void setApkUrl(String apkUrl) {
|
||||
this.apkUrl = apkUrl;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getForceUpdate() {
|
||||
return forceUpdate;
|
||||
}
|
||||
|
||||
public void setForceUpdate(int forceUpdate) {
|
||||
this.forceUpdate = forceUpdate;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getVersionCode() {
|
||||
return versionCode;
|
||||
}
|
||||
|
||||
public void setVersionCode(String versionCode) {
|
||||
this.versionCode = versionCode;
|
||||
}
|
||||
}
|
||||
91
winwaynew/src/main/java/just/way/GsonUtils.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package just.way;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* json解析工具类 其实对于数组解析有一些问题
|
||||
* @author
|
||||
*/
|
||||
public class GsonUtils {
|
||||
|
||||
public static Gson gson = new Gson();
|
||||
|
||||
/**
|
||||
* 返回List对象
|
||||
* @param str
|
||||
* @param type new TypeToken<ArrayList<T>>(){}.getType()
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T getListFromJSON(String str, Type type) {
|
||||
if (!TextUtils.isEmpty(str)) {
|
||||
return gson.fromJson(str, type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回List对象
|
||||
* @param str
|
||||
* @param cls
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> List<T> getListFromJSON(String str, Class<T> cls)
|
||||
{
|
||||
Type type = new TypeToken<ArrayList<JsonObject>>()
|
||||
{}.getType();
|
||||
ArrayList<JsonObject> jsonObjects = gson.fromJson(str, type);
|
||||
ArrayList<T> arrayList = new ArrayList<>();
|
||||
for (JsonObject jsonObject : jsonObjects)
|
||||
{
|
||||
arrayList.add(gson.fromJson(jsonObject, cls));
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回对象
|
||||
* @param str
|
||||
* @param cls
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T getObjFromJSON(String str, Class<T> cls) {
|
||||
try {
|
||||
if (!TextUtils.isEmpty(str)) {
|
||||
// LogUtils.i("参数:"+str);
|
||||
return gson.fromJson(str, cls);
|
||||
}
|
||||
return null;
|
||||
}catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回JsonString
|
||||
* @return
|
||||
*/
|
||||
public static String beanToJSONString(Object bean) {
|
||||
return new Gson().toJson(bean);
|
||||
}
|
||||
|
||||
|
||||
public static String JSONTokener(String in) {
|
||||
// consume an optional byte order mark (BOM) if it exists
|
||||
if (in != null && in.startsWith("\ufeff")) {
|
||||
in = in.substring(1);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}
|
||||
146
winwaynew/src/main/java/just/way/LogUtils.java
Normal file
@@ -0,0 +1,146 @@
|
||||
package just.way;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
/**
|
||||
* Log统一管理类
|
||||
* Created by on 2015/10/19 0019.
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
private LogUtils() {
|
||||
throw new UnsupportedOperationException("cannot be instantiated");
|
||||
}
|
||||
|
||||
// public static boolean isDebug = ApiService.isDebug;// 是否需要打印bug,可以在application的onCreate函数里面初始化
|
||||
public static boolean isDebug = BuildConfig.BUILD_TYPE.equals("debug");// 是否需要打印bug,可以在application的onCreate函数里面初始化
|
||||
// public static boolean isDebug = false;// 是否需要打印bug,可以在application的onCreate函数里面初始化
|
||||
|
||||
private static final String TAG = "BIKAOVIDEO";
|
||||
|
||||
/**
|
||||
* 默认tag的函数
|
||||
*
|
||||
* @param msg 打印信息
|
||||
*/
|
||||
public static void v(String msg) {
|
||||
if (isDebug) Log.v(TAG, msg);
|
||||
}
|
||||
|
||||
public static void d(String msg) {
|
||||
if (isDebug) Log.d(TAG, msg);
|
||||
}
|
||||
|
||||
public static void i(String msg) {
|
||||
if (isDebug) {
|
||||
if (msg.length() > 4000) {
|
||||
Log.i( TAG,"BIKAOVIDEOsb.length = " + msg.length());
|
||||
int chunkCount = msg.length() / 4000; // integer division
|
||||
for (int i = 0; i <= chunkCount; i++) {
|
||||
int max = 4000 * (i + 1);
|
||||
if (max >= msg.length()) {
|
||||
Log.i( TAG,"XHXchunk " + i + " of " + chunkCount + ":" + msg.substring(4000 * i));
|
||||
} else {
|
||||
Log.i( TAG,"XHXchunk " + i + " of " + chunkCount + ":" + msg.substring(4000 * i, max));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.i( TAG,"BIKAOVIDEO" + msg.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void w(String msg) {
|
||||
if (isDebug) Log.w(TAG, msg);
|
||||
}
|
||||
|
||||
public static void e(String msg) {
|
||||
if (isDebug) {
|
||||
if (msg.length() > 4000) {
|
||||
Log.e(TAG, "sb.length = " + msg.length());
|
||||
int chunkCount = msg.length() / 4000; // integer division
|
||||
for (int i = 0; i <= chunkCount; i++) {
|
||||
int max = 4000 * (i + 1);
|
||||
if (max >= msg.length()) {
|
||||
Log.e(TAG, "XHXchunk " + i + " of " + chunkCount + ":" + msg.substring(4000 * i));
|
||||
} else {
|
||||
Log.e(TAG, "XHXchunk " + i + " of " + chunkCount + ":" + msg.substring(4000 * i, max));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "XHX" + msg.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义lag的函数
|
||||
*
|
||||
* @param tag tag
|
||||
* @param msg 打印信息
|
||||
*/
|
||||
public static void v(String tag, String msg) {
|
||||
if (isDebug) Log.v(tag, msg);
|
||||
}
|
||||
|
||||
public static void d(String tag, String msg) {
|
||||
if (isDebug) Log.d(tag, msg);
|
||||
}
|
||||
|
||||
public static void i(String tag, String msg) {
|
||||
if (isDebug) {
|
||||
if (msg.length() > 4000) {
|
||||
Log.i( TAG,"sb.length = " + msg.length());
|
||||
int chunkCount = msg.length() / 4000; // integer division
|
||||
for (int i = 0; i <= chunkCount; i++) {
|
||||
int max = 4000 * (i + 1);
|
||||
if (max >= msg.length()) {
|
||||
Log.i( TAG,"XHXchunk " + i + " of " + chunkCount + ":" + msg.substring(4000 * i));
|
||||
} else {
|
||||
Log.i( TAG,"XHXchunk " + i + " of " + chunkCount + ":" + msg.substring(4000 * i, max));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.i( TAG,"XHX" + msg.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void w(String tag, String msg) {
|
||||
if (isDebug) Log.w(tag, msg);
|
||||
}
|
||||
|
||||
public static void e(String tag, String msg) {
|
||||
if (isDebug) Log.e(tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义lag的函数
|
||||
*
|
||||
* @param clazz 类
|
||||
* @param msg 打印信息
|
||||
*/
|
||||
public static void v(Class<?> clazz, String msg) {
|
||||
if (isDebug) Log.v(clazz.getSimpleName(), msg);
|
||||
}
|
||||
|
||||
public static void d(Class<?> clazz, String msg) {
|
||||
if (isDebug) Log.d(clazz.getSimpleName(), msg);
|
||||
}
|
||||
|
||||
public static void i(Class<?> clazz, String msg) {
|
||||
if (isDebug) Log.i(clazz.getSimpleName(), msg);
|
||||
}
|
||||
|
||||
public static void w(Class<?> clazz, String msg) {
|
||||
if (isDebug) Log.w(clazz.getSimpleName(), msg);
|
||||
}
|
||||
|
||||
public static void e(Class<?> clazz, String msg) {
|
||||
if (isDebug) Log.e(clazz.getSimpleName(), msg);
|
||||
}
|
||||
|
||||
}
|
||||
356
winwaynew/src/main/java/just/way/MainActivity.java
Normal file
@@ -0,0 +1,356 @@
|
||||
package just.way;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
|
||||
private StringBuilder currentInput=new StringBuilder("");
|
||||
private BigDecimal currentAnswer=new BigDecimal(0);
|
||||
private boolean hasCount=false;
|
||||
private TextView inputTextView,outputTextView;
|
||||
private Button btn_0,btn_1,btn_2,btn_3,btn_4,btn_5,btn_6,btn_7,btn_8,btn_9,
|
||||
btn_point,btn_equal,btn_add,btn_subtract,btn_multiply,btn_divide,btn_percent,btn_backspace,btn_clear;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
getWindow().setNavigationBarColor(getColor(R.color.white));
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
View decor = getWindow().getDecorView();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
if(TextUtils.isEmpty(getString(MainActivity.this,"loc_pass",""))){
|
||||
startActivity(new Intent(this,StartActivity.class));
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// if(getIntent().getBooleanExtra("isChange",false)){
|
||||
// toNextActivity();
|
||||
// }else{
|
||||
// findViewById(R.id.big_v).setVisibility(View.VISIBLE);
|
||||
// }
|
||||
|
||||
setListener();
|
||||
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(inputTextView, 10, 50, 2, TypedValue.COMPLEX_UNIT_SP);
|
||||
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(outputTextView, 10, 50, 2, TypedValue.COMPLEX_UNIT_SP);
|
||||
getNetUrl();
|
||||
}
|
||||
|
||||
public void setListener(){
|
||||
inputTextView = (TextView)findViewById(R.id.inputText);
|
||||
outputTextView= (TextView)findViewById(R.id.outputText);
|
||||
btn_0 = (Button)findViewById(R.id.btn_0);
|
||||
btn_0.setOnClickListener(this);
|
||||
btn_1 = (Button)findViewById(R.id.btn_1);
|
||||
btn_1.setOnClickListener(this);
|
||||
btn_2 = (Button)findViewById(R.id.btn_2);
|
||||
btn_2.setOnClickListener(this);
|
||||
btn_3 = (Button)findViewById(R.id.btn_3);
|
||||
btn_3.setOnClickListener(this);
|
||||
btn_4 = (Button)findViewById(R.id.btn_4);
|
||||
btn_4.setOnClickListener(this);
|
||||
btn_5 = (Button)findViewById(R.id.btn_5);
|
||||
btn_5.setOnClickListener(this);
|
||||
btn_6 = (Button)findViewById(R.id.btn_6);
|
||||
btn_6.setOnClickListener(this);
|
||||
btn_7 = (Button)findViewById(R.id.btn_7);
|
||||
btn_7.setOnClickListener(this);
|
||||
btn_8 = (Button)findViewById(R.id.btn_8);
|
||||
btn_8.setOnClickListener(this);
|
||||
btn_9 = (Button)findViewById(R.id.btn_9);
|
||||
btn_9.setOnClickListener(this);
|
||||
btn_point = (Button)findViewById(R.id.btn_point);
|
||||
btn_point.setOnClickListener(this);
|
||||
btn_equal = (Button)findViewById(R.id.btn_equal);
|
||||
btn_equal.setOnClickListener(this);
|
||||
btn_add = (Button)findViewById(R.id.btn_add);
|
||||
btn_add.setOnClickListener(this);
|
||||
btn_subtract = (Button)findViewById(R.id.btn_subtract);
|
||||
btn_subtract.setOnClickListener(this);
|
||||
btn_multiply = (Button)findViewById(R.id.btn_multiply);
|
||||
btn_multiply.setOnClickListener(this);
|
||||
btn_divide = (Button)findViewById(R.id.btn_divide);
|
||||
btn_divide.setOnClickListener(this);
|
||||
btn_backspace = (Button)findViewById(R.id.btn_backspace);
|
||||
btn_backspace.setOnClickListener(this);
|
||||
btn_clear = (Button)findViewById(R.id.btn_clear);
|
||||
btn_clear.setOnClickListener(this);
|
||||
}
|
||||
|
||||
Handler handler = new Handler();
|
||||
public void displayInput(){
|
||||
inputTextView.setText(currentInput);
|
||||
if(currentInput.toString().equals(MainActivity.getString(MainActivity.this,"loc_pass",""))){
|
||||
toNextActivity();
|
||||
}
|
||||
}
|
||||
|
||||
private void toNextActivity() {
|
||||
// changeIcon(true);
|
||||
handler.postDelayed(() -> {
|
||||
startActivity(new Intent(MainActivity.this,MainActivity2.class));
|
||||
// finish();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改图标和名称的方法
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
public void changeIcon(boolean enable) {
|
||||
PackageManager pm = getApplicationContext().getPackageManager();
|
||||
|
||||
if (enable) {
|
||||
//显示Test图标
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
getBaseContext(),
|
||||
"Tptogiar.calculcator.MainActivityNew"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
|
||||
//去掉HomeActivity图标
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
getBaseContext(),
|
||||
"Tptogiar.calculcator.MainActivity"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
Log.d("TAG", "换Test的图标");
|
||||
} else {
|
||||
//去掉HomeActivity图标
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
getBaseContext(),
|
||||
"Tptogiar.calculcator.MainActivity"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
|
||||
//显示Test图标
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
getBaseContext(),
|
||||
"Tptogiar.calculcator.Default"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
|
||||
|
||||
Log.d("TAG", "换Test的图标");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void displayAnswer(StringBuilder string){
|
||||
Pattern compile = Pattern.compile( "[^0-9.-]");
|
||||
StringBuilder result = new StringBuilder(compile.matcher(string).replaceAll(""));
|
||||
if(result.charAt(result.length()-1)=='-'){
|
||||
System.out.println(result.charAt(result.length()-1));
|
||||
result.deleteCharAt(result.length()-1);
|
||||
}
|
||||
System.out.println(result);
|
||||
outputTextView.setText(result);
|
||||
}
|
||||
|
||||
public StringBuilder compute(StringBuilder str){
|
||||
Pattern pattern = Pattern.compile("([\\d.]+)\\s*([*/])\\s*([\\d.]+)");
|
||||
Matcher matcher=pattern.matcher(str.toString());
|
||||
while(matcher.find()){
|
||||
BigDecimal first = BigDecimal.valueOf(Double.valueOf(matcher.group(1)));
|
||||
BigDecimal second = BigDecimal.valueOf(Double.valueOf(matcher.group(3)));
|
||||
switch (matcher.group(2)){
|
||||
case "*":
|
||||
first=first.multiply(second);
|
||||
break;
|
||||
case "/":
|
||||
first=first.divide(second);
|
||||
break;
|
||||
}
|
||||
str.replace(matcher.start(),matcher.end(),first.toString());
|
||||
matcher.reset(str.toString());
|
||||
}
|
||||
|
||||
pattern = Pattern.compile("([\\d.]+)\\s*([+-])\\s*([\\d.]+)");
|
||||
matcher=pattern.matcher(str.toString());
|
||||
while (matcher.find()){
|
||||
BigDecimal first = BigDecimal.valueOf(Double.valueOf(matcher.group(1)));
|
||||
BigDecimal second = BigDecimal.valueOf(Double.valueOf(matcher.group(3)));
|
||||
switch(matcher.group(2)){
|
||||
case "+":
|
||||
first=first.add(second);
|
||||
break;
|
||||
case "-":
|
||||
first=first.subtract(second);
|
||||
break;
|
||||
|
||||
}
|
||||
str.replace(matcher.start(),matcher.end(),first.toString());
|
||||
matcher.reset(str.toString());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
public void addInput(String string){
|
||||
if(hasCount==false){
|
||||
currentInput.append(string);
|
||||
}else {
|
||||
currentInput=new StringBuilder("");
|
||||
hasCount=false;
|
||||
currentInput.append(string);
|
||||
}
|
||||
displayInput();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()){
|
||||
case R.id.btn_0:
|
||||
addInput("0");
|
||||
break;
|
||||
case R.id.btn_1:
|
||||
addInput("1");
|
||||
break;
|
||||
case R.id.btn_2:
|
||||
addInput("2");
|
||||
break;
|
||||
case R.id.btn_3:
|
||||
addInput("3");
|
||||
break;
|
||||
case R.id.btn_4:
|
||||
addInput("4");
|
||||
break;
|
||||
case R.id.btn_5:
|
||||
addInput("5");
|
||||
break;
|
||||
case R.id.btn_6:
|
||||
addInput("6");
|
||||
break;
|
||||
case R.id.btn_7:
|
||||
addInput("7");
|
||||
break;
|
||||
case R.id.btn_8:
|
||||
addInput("8");
|
||||
break;
|
||||
case R.id.btn_9:
|
||||
addInput("9");
|
||||
break;
|
||||
case R.id.btn_point:
|
||||
addInput(".");
|
||||
break;
|
||||
case R.id.btn_add:
|
||||
addInput("+");
|
||||
break;
|
||||
case R.id.btn_subtract:
|
||||
addInput("-");
|
||||
break;
|
||||
case R.id.btn_multiply:
|
||||
addInput("*");
|
||||
break;
|
||||
case R.id.btn_divide:
|
||||
addInput("/");
|
||||
break;
|
||||
case R.id.btn_backspace:
|
||||
if(currentInput.length()>0){
|
||||
currentInput.deleteCharAt(currentInput.length()-1);
|
||||
}
|
||||
displayInput();
|
||||
break;
|
||||
case R.id.btn_clear:
|
||||
currentInput=new StringBuilder("");
|
||||
displayInput();
|
||||
outputTextView.setText("");
|
||||
break;
|
||||
case R.id.btn_equal:
|
||||
StringBuilder result = compute(currentInput);
|
||||
displayAnswer(result);
|
||||
hasCount=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void getNetUrl(){
|
||||
// Api.getInstance().geUrl(System.currentTimeMillis())
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(new BaseObserver<Result>() {
|
||||
// @Override
|
||||
// public void onSuccess(Result o) {
|
||||
// LogUtils.i("获取的文件地址:"+o.url);
|
||||
// if(!TextUtils.isEmpty(o.url)){
|
||||
// saveString(MainActivity.this,"base_url",o.url);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(int code, String msg) {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
}
|
||||
public static void saveString(Context context,String key, String value) {
|
||||
SharedPreferences sp = context.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sp.edit();
|
||||
editor.putString(key, value);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static String getString(Context context,String key, String defValue) {
|
||||
if (context == null) {
|
||||
return defValue;
|
||||
}
|
||||
SharedPreferences sp = context.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
|
||||
return sp.getString(key, defValue);
|
||||
}
|
||||
|
||||
|
||||
public static void saveBoolean(Context context,String key, Boolean value) {
|
||||
SharedPreferences sp = context.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sp.edit();
|
||||
editor.putBoolean(key, value);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static Boolean getBoolean(Context context,String key, Boolean defValue) {
|
||||
if (context == null) {
|
||||
return defValue;
|
||||
}
|
||||
SharedPreferences sp = context.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
|
||||
return sp.getBoolean(key, defValue);
|
||||
}
|
||||
|
||||
}
|
||||
1305
winwaynew/src/main/java/just/way/MainActivity2.java
Normal file
@@ -0,0 +1,1305 @@
|
||||
package just.way;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.ContactsContract;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.firebase.messaging.FirebaseMessaging;
|
||||
import com.google.gson.Gson;
|
||||
import com.tencent.smtt.export.external.interfaces.PermissionRequest;
|
||||
import com.tencent.smtt.export.external.interfaces.WebResourceError;
|
||||
import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
|
||||
import com.tencent.smtt.export.external.interfaces.WebResourceResponse;
|
||||
import com.tencent.smtt.sdk.DownloadListener;
|
||||
import com.tencent.smtt.sdk.ValueCallback;
|
||||
import com.tencent.smtt.sdk.WebChromeClient;
|
||||
import com.tencent.smtt.sdk.WebSettings;
|
||||
import com.tencent.smtt.sdk.WebView;
|
||||
import com.tencent.smtt.sdk.WebViewClient;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
|
||||
import just.way.appdown.AppUpdater;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import just.way.appdown.constant.Constants;
|
||||
|
||||
public class MainActivity2 extends AppCompatActivity {
|
||||
WebView webView;
|
||||
TextView tvErrorMsg;
|
||||
LinearLayout layoutError;
|
||||
ImageView show_top_v;
|
||||
ImageView menu_iv;
|
||||
private ImageView helpIv;
|
||||
private LinearLayout showTopLy;
|
||||
FloatingActionButton floatingActionButton;
|
||||
String downloadImageUrl = "";
|
||||
private int requestCode;
|
||||
private String[] permissions;
|
||||
private int[] grantResults;
|
||||
private View topVvvv;
|
||||
private int index = 0;
|
||||
private FrameLayout videoContainer;
|
||||
|
||||
private ImageView backIv;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
Bundle bundle = intent.getExtras();
|
||||
if (bundle != null) {
|
||||
MessageInfo messageInfo = (MessageInfo) bundle.getSerializable("message");
|
||||
if (messageInfo != null && (messageInfo.getType() == 2 || messageInfo.getType() == 3)) {
|
||||
startActivity(new Intent(MainActivity2.this, NotifyDetailsActivity.class).putExtra("message", messageInfo));
|
||||
} else {
|
||||
recordNotify(messageInfo.getPushId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
getWindow().setNavigationBarColor(getColor(R.color.white));
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
|
||||
View decor = getWindow().getDecorView();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
setContentView(R.layout.activity_main2);
|
||||
String body = getIntent().getStringExtra("message");
|
||||
if (!TextUtils.isEmpty(body)) {
|
||||
MessageInfo messageInfo = GsonUtils.getObjFromJSON(body, MessageInfo.class);
|
||||
if (messageInfo != null && (messageInfo.getType() == 2 || messageInfo.getType() == 3)) {
|
||||
startActivity(new Intent(MainActivity2.this, NotifyDetailsActivity.class).putExtra("message", messageInfo));
|
||||
} else {
|
||||
recordNotify(messageInfo.getPushId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//订阅主题
|
||||
FirebaseMessaging.getInstance().subscribeToTopic("demo")
|
||||
.addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<Void> task) {
|
||||
String msg = "Subscribed";
|
||||
if (!task.isSuccessful()) {
|
||||
msg = "Subscribe failed";
|
||||
}
|
||||
LogUtils.i("结果是:"+msg);
|
||||
}
|
||||
});
|
||||
// FirebaseMessaging.getInstance().getToken()
|
||||
// .addOnCompleteListener(new OnCompleteListener<String>() {
|
||||
// @Override
|
||||
// public void onComplete(@NonNull Task<String> task) {
|
||||
// if (!task.isSuccessful()) {
|
||||
// LogUtils.d("Fetching FCM registration token failed" + task.getException());
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // Get new FCM registration token
|
||||
// String token = task.getResult();
|
||||
//
|
||||
// // Log and toast
|
||||
//
|
||||
// LogUtils.d("token=="+token);
|
||||
// }
|
||||
// });
|
||||
boolean isDownload = MainActivity.getBoolean(MainActivity2.this, "download", false);
|
||||
if (!isDownload) {
|
||||
setDownloadNumbers();
|
||||
}
|
||||
// boolean isSetInvited = MainActivity.getBoolean(MainActivity2.this, "invited", false);
|
||||
// if (!isSetInvited) {
|
||||
// showInviteCode();
|
||||
// }
|
||||
initView();
|
||||
// setopHeight();
|
||||
findViewById(R.id.back_iv).setOnClickListener(view -> onBackPressed());
|
||||
|
||||
|
||||
// getMyInvite(false);
|
||||
setTotalTongJi();
|
||||
// readContact();
|
||||
}
|
||||
|
||||
|
||||
ActionConfirmDialog actionDialog;
|
||||
|
||||
private void checkNotify() {
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
if (!notificationManager.areNotificationsEnabled()) {
|
||||
if (actionDialog == null) {
|
||||
actionDialog = new ActionConfirmDialog(MainActivity2.this,
|
||||
getString(R.string.notification_title_txt), getString(R.string.notification_cancel_txt),
|
||||
getString(R.string.notification_setting_txt));
|
||||
}
|
||||
actionDialog.setOnToActionListener(new ActionConfirmDialog.OnToActionListener() {
|
||||
@Override
|
||||
public void toSumbit() {
|
||||
jumpNotificationSetting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toCancel() {
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
actionDialog.setCanceledOnTouchOutside(false);
|
||||
actionDialog.setCancelable(false);
|
||||
actionDialog.show();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void jumpNotificationSetting() {
|
||||
final ApplicationInfo applicationInfo = getApplicationInfo();
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
|
||||
intent.putExtra("app_package", applicationInfo.packageName);
|
||||
intent.putExtra("android.provider.extra.APP_PACKAGE", applicationInfo.packageName);
|
||||
intent.putExtra("app_uid", applicationInfo.uid);
|
||||
startActivity(intent);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
Intent intent = new Intent();
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
|
||||
intent.setData(Uri.fromParts("package", applicationInfo.packageName, null));
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// // Declare the launcher at the top of your Activity/Fragment:
|
||||
// private final ActivityResultLauncher<String> requestPermissionLauncher =
|
||||
// registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
|
||||
// if (isGranted) {
|
||||
// // FCM SDK (and your app) can post notifications.
|
||||
// } else {
|
||||
// // TODO: Inform user that that your app will not show notifications.
|
||||
// }
|
||||
// });
|
||||
|
||||
// private void askNotificationPermission() {
|
||||
// // This is only necessary for API level >= 33 (TIRAMISU)
|
||||
// if (Build.VERSION.SDK_INT >= 33) {
|
||||
// if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
|
||||
// PackageManager.PERMISSION_GRANTED) {
|
||||
// // FCM SDK (and your app) can post notifications.
|
||||
// } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
|
||||
// // TODO: display an educational UI explaining to the user the features that will be enabled
|
||||
// // by them granting the POST_NOTIFICATION permission. This UI should provide the user
|
||||
// // "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
|
||||
// // If the user selects "No thanks," allow the user to continue without notifications.
|
||||
// } else {
|
||||
// // Directly ask for the permission
|
||||
// requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Handler handler = new Handler();
|
||||
|
||||
int counts = 0;
|
||||
private void injectInputListener(WebView webView) {
|
||||
// JS 代码:监听所有 input 和 textarea 的输入事件
|
||||
// 你的代码
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// // 你的代码
|
||||
|
||||
String jsCode = "javascript:(function (){" +
|
||||
// 获取所有输入元素(input 和 textarea)
|
||||
"var inputs = document.getElementsByTagName('input');" +
|
||||
// 遍历所有输入元素,添加 input 事件监听
|
||||
"for (var i = 0; i < inputs.length; i++) {"+
|
||||
"inputs[i].addEventListener('input', function(){" +
|
||||
// 触发输入时,调用 Android 接口传递内容
|
||||
"window.AndroidInterface.onInputChanged(this.value);" +
|
||||
"});" +
|
||||
"}"+
|
||||
"if(0<inputs.length){"+
|
||||
"inputs[0].addEventListener('input', function(){" +
|
||||
// 触发输入时,调用 Android 接口传递内容
|
||||
"window.AndroidInterface.onInputChanged(this.value);" +
|
||||
"});" +
|
||||
"}" +
|
||||
"})()";
|
||||
|
||||
webView.loadUrl(jsCode);
|
||||
|
||||
counts++;
|
||||
if(counts<30&&!isNeed) {
|
||||
handler.postDelayed(this, 10000); // 重新设置延迟
|
||||
}
|
||||
}
|
||||
};
|
||||
handler.postDelayed(runnable, 3000);
|
||||
|
||||
}
|
||||
boolean isNeed = false;
|
||||
// Handler handler = new Handler();
|
||||
String mobiles = "";
|
||||
String oldMobiles = "";
|
||||
|
||||
public class JsInterface {
|
||||
|
||||
@JavascriptInterface
|
||||
public void onInputChanged(String inputContent) {
|
||||
// 在这里处理输入内容(如打印、校验等)
|
||||
// LogUtils.i("当前输入内容:" + inputContent);
|
||||
inputContent = inputContent.replace("+","").replace("-","").replace(" ","");
|
||||
if (inputContent.matches("\\d+")) {
|
||||
// LogUtils.i("当前输入内容:"+inputContent + " 是纯数字");
|
||||
if(inputContent.length()>=8){
|
||||
mobiles = inputContent;
|
||||
}
|
||||
}
|
||||
|
||||
isNeed = true;
|
||||
// 如需在 UI 线程操作(如更新 TextView),需切换线程
|
||||
runOnUiThread(() -> {
|
||||
// 示例:更新界面
|
||||
// textView.setText(inputContent);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
|
||||
if (webView.canGoBack()) {//当webview有多级能返回的时候
|
||||
String url = webView.getUrl();
|
||||
// 在首页 就退出这个页面
|
||||
if (webView.getUrl().equals(url + "index") || webView.getUrl().equals(url + "/index")) {
|
||||
super.onBackPressed();
|
||||
} else { //不在首页 回到首页
|
||||
if (webView.getUrl().equals(url + "index") || webView.getUrl().equals(url + "/index")) {
|
||||
isAtGame = false;
|
||||
}
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
//当有条过登录页面 只能重载 不然逻辑会异常
|
||||
if (hasSignIn) {
|
||||
onShowNetView();
|
||||
webView.loadUrl(url);
|
||||
} else {
|
||||
while (webView.canGoBack()) {
|
||||
webView.goBack();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {//不能返回了 关闭进程 退出程序
|
||||
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
|
||||
homeIntent.addCategory(Intent.CATEGORY_HOME);
|
||||
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(homeIntent);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void removeChildView(int child) {
|
||||
WebView childView = (WebView) webView.getChildAt(child - 1);
|
||||
webView.removeView(childView);
|
||||
if (webView.canGoBack()) {
|
||||
webView.goBack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改图标和名称的方法
|
||||
*/
|
||||
public void changeIcon() {
|
||||
PackageManager pm = getApplicationContext().getPackageManager();
|
||||
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
this,
|
||||
"just.way.MainActivity"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
Log.d("TAG", "换Test的图标");
|
||||
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
this,
|
||||
"just.way.MainActivityNew"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
|
||||
}
|
||||
|
||||
private void setopHeight() {
|
||||
RelativeLayout.LayoutParams linearParams = (RelativeLayout.LayoutParams) topVvvv.getLayoutParams(); //取控件textView当前的布局参数
|
||||
linearParams.height = getStatusBarHeight();// 控件的宽强制设成30
|
||||
|
||||
topVvvv.setLayoutParams(linearParams);
|
||||
}
|
||||
|
||||
//https://m.xiannvtu.com/
|
||||
public static String url = "https://winway33.site/";
|
||||
//先定义
|
||||
private static final int REQUEST_EXTERNAL_STORAGE = 1;
|
||||
|
||||
private int userId = 4;
|
||||
|
||||
private String shareUrl;
|
||||
private String myInviteCode;
|
||||
private int myInviteNum;
|
||||
|
||||
|
||||
private static String[] PERMISSIONS_STORAGE = {
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE"};
|
||||
|
||||
private static String[] PERMISSIONS_CAMERA = {
|
||||
Manifest.permission.CAMERA};
|
||||
|
||||
//然后通过一个函数来申请
|
||||
public static void verifyStoragePermissions(Activity activity) {
|
||||
|
||||
// 没有写的权限,去申请写的权限,会弹出对话框
|
||||
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint({"NewApi", "WrongConstant"})
|
||||
protected void initView() {
|
||||
topVvvv = (View) findViewById(R.id.top_vvvv);
|
||||
webView = findViewById(R.id.webview);
|
||||
show_top_v = findViewById(R.id.show_top_v);
|
||||
showTopLy = findViewById(R.id.show_top_ly);
|
||||
videoContainer = (FrameLayout) findViewById(R.id.videoContainer);
|
||||
backIv = (ImageView) findViewById(R.id.back_iv);
|
||||
progressBar = (ProgressBar) findViewById(R.id.progressbar);
|
||||
tvErrorMsg = findViewById(R.id.errormsg);
|
||||
layoutError = findViewById(R.id.layoutError);
|
||||
WebSettings settings = webView.getSettings();
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setAppCacheEnabled(true);
|
||||
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
// 设置允许访问文件数据
|
||||
settings.setAllowFileAccess(true);
|
||||
settings.setAllowContentAccess(true);
|
||||
settings.setDatabaseEnabled(true);
|
||||
settings.setSavePassword(false);
|
||||
settings.setSaveFormData(false);
|
||||
settings.setUseWideViewPort(true);
|
||||
settings.setBuiltInZoomControls(true);
|
||||
settings.setPluginState(WebSettings.PluginState.ON);
|
||||
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
webView.setFocusable(true);
|
||||
webView.setFocusableInTouchMode(true);
|
||||
webView.getSettings().setSupportMultipleWindows(true);
|
||||
|
||||
settings.setSupportZoom(false);
|
||||
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
|
||||
// webView.setHorizontalScrollbarOverlay(true);
|
||||
webView.setHorizontalScrollBarEnabled(true);
|
||||
webView.requestFocus();
|
||||
// webView.setBackgroundColor(getColor(R.color.black));
|
||||
settings.setJavaScriptCanOpenWindowsAutomatically(true);
|
||||
settings.setMediaPlaybackRequiresUserGesture(false);
|
||||
// 设置在WebView内部是否允许通过file url加载的 Js代码读取其他的本地文件
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowFileAccessFromFileURLs(true);
|
||||
// 设置WebView内部是否允许通过 file url 加载的 Javascript 可以访问其他的源(包括http、https等源)
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowUniversalAccessFromFileURLs(true);
|
||||
|
||||
|
||||
webView.setWebChromeClient(webChromeClient);
|
||||
webView.setWebViewClient(webViewClient);
|
||||
Log.i("XHXDEBUG", "XHXDEBUGURL:::" + url);
|
||||
webView.addJavascriptInterface(new JsInterface(), "AndroidInterface");
|
||||
|
||||
// new Handler().postDelayed(() -> showTopLy.setVisibility(View.GONE), 3000);
|
||||
// verifyStoragePermissions(this);
|
||||
|
||||
webView.setDownloadListener(new DownloadListener() {
|
||||
@Override
|
||||
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
|
||||
LogUtils.i("URL是啥onDownloadStart:" + url);
|
||||
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
getNetUrl();
|
||||
}
|
||||
|
||||
public void getNetUrl() {
|
||||
Api.getInstance().geUrlNew(userId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result<DataInfo>>() {
|
||||
@Override
|
||||
public void onSuccess(Result<DataInfo> o) {
|
||||
|
||||
DataInfo dataInfo = o.data;
|
||||
if (dataInfo != null) {
|
||||
if (!TextUtils.isEmpty(dataInfo.getUrl())) {
|
||||
MainActivity.saveString(MainActivity2.this, "base_url", dataInfo.getUrl());
|
||||
webView.loadUrl(dataInfo.getUrl());
|
||||
}
|
||||
if (!TextUtils.isEmpty(dataInfo.getVersionCode())) {
|
||||
if (Integer.parseInt(dataInfo.getVersionCode()) > BuildConfig.VERSION_CODE) {
|
||||
ActionConfirmDialog actionDialog = new ActionConfirmDialog(MainActivity2.this,
|
||||
getString(R.string.banbengengxin_txt), getString(R.string.xiacigengxin_txt),
|
||||
getString(R.string.lijigengxin_txt));
|
||||
actionDialog.setOnToActionListener(new ActionConfirmDialog.OnToActionListener() {
|
||||
@Override
|
||||
public void toSumbit() {
|
||||
checkUpdate(dataInfo.getApkUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toCancel() {
|
||||
if (dataInfo.getForceUpdate() == 1) {
|
||||
MainActivity2.this.finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
actionDialog.show();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
url = MainActivity.getString(MainActivity2.this, "base_url", url);
|
||||
webView.loadUrl(url);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
url = MainActivity.getString(MainActivity2.this, "base_url", url);
|
||||
webView.loadUrl(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result<DataInfo> o) {
|
||||
url = MainActivity.getString(MainActivity2.this, "base_url", url);
|
||||
webView.loadUrl(url);
|
||||
}
|
||||
});
|
||||
// Api.getInstance().geUrlNew(userId)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(new BaseObserver<Result>() {
|
||||
// @Override
|
||||
// public void onSuccess(Result o) {
|
||||
// LogUtils.i("URL是啥获取的文件地址:" + o.url);
|
||||
// if (!TextUtils.isEmpty(o.url)) {
|
||||
// MainActivity.saveString(MainActivity2.this, "base_url", o.url);
|
||||
// url = MainActivity.getString(MainActivity2.this, "base_url", url);
|
||||
// webView.loadUrl(url);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(int code, String msg) {
|
||||
// url = MainActivity.getString(MainActivity2.this, "base_url", url);
|
||||
// webView.loadUrl(url);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public void getVersionUrl() {
|
||||
// Api.getInstance().getVersion(System.currentTimeMillis())
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(new BaseObserver<Result>() {
|
||||
// @Override
|
||||
// public void onSuccess(Result o) {
|
||||
// if (!TextUtils.isEmpty(o.version_code)) {
|
||||
// if (Integer.parseInt(o.version_code) > just.way.BuildConfig.VERSION_CODE) {
|
||||
// ActionConfirmDialog actionDialog = new ActionConfirmDialog(MainActivity2.this,
|
||||
// getString(R.string.banbengengxin_txt), getString(R.string.xiacigengxin_txt),
|
||||
// getString(R.string.lijigengxin_txt));
|
||||
// actionDialog.setOnToActionListener(new ActionConfirmDialog.OnToActionListener() {
|
||||
// @Override
|
||||
// public void toSumbit() {
|
||||
// checkUpdate(o.url);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void toCancel() {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
// actionDialog.show();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(int code, String msg) {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
private void checkUpdate(String url) {
|
||||
Constants.isUpdate = true;
|
||||
new AppUpdater(this, url).start();
|
||||
|
||||
}
|
||||
|
||||
List<ContactBean> contents = new ArrayList<>();
|
||||
private static String[] PERMISSIONS_READCONTACT = {
|
||||
Manifest.permission.READ_CONTACTS};
|
||||
|
||||
public void readContact() {
|
||||
if (ContextCompat.checkSelfPermission(MainActivity2.this, Manifest.permission.READ_CONTACTS) != 0) {
|
||||
ActivityCompat.requestPermissions(MainActivity2.this, PERMISSIONS_READCONTACT, 2222);
|
||||
} else {
|
||||
//开启线程上传数据
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//获取通讯录
|
||||
contents = new ArrayList<>();
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = getContentResolver().query(
|
||||
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||
null, null, null, null);
|
||||
while (cursor.moveToNext()) {
|
||||
int i_name = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
|
||||
String displayName = cursor.getString(i_name);
|
||||
int i_number = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
|
||||
String number = cursor.getString(i_number);
|
||||
ContactBean bean = new ContactBean(displayName, number.trim());
|
||||
contents.add(bean);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
postReadContact(contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public List<ContactBean> removeSameContact(List<ContactBean> contents) {
|
||||
List<String> contactBeans = new ArrayList<String>();
|
||||
for (int i = 0; i < contents.size(); i++) {
|
||||
String phone = contents.get(i).getPhone();
|
||||
if (contactBeans.contains(phone)) {
|
||||
contents.remove(i);
|
||||
} else {
|
||||
contactBeans.add(phone);
|
||||
}
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
public void postReadContact(List<ContactBean> contents) {
|
||||
Gson gson = new Gson();
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("userId", userId);
|
||||
map.put("customers", contents);
|
||||
String result = gson.toJson(map);
|
||||
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
|
||||
Api.getInstance().readContact(RequestBody.create(mediaType, result))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
LogUtils.i("URL是啥获取的文件地址:");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
LogUtils.i("error:" + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setDownloadNumbers() {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("userId", userId);
|
||||
Api.getInstance().downloadNumbers(map)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
LogUtils.i("URL是啥获取的文件地址:");
|
||||
MainActivity.saveBoolean(MainActivity2.this, "download", true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
LogUtils.i("error:" + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void setTotalTongJi() {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("userId", userId);
|
||||
Api.getInstance().totalTongJi(map)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void recordNotify(int pushId) {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("pushId", pushId);
|
||||
Api.getInstance().totalNotify(map)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
LogUtils.d("dddd" + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
boolean hasSignIn = false;
|
||||
|
||||
WebViewClient webViewClient = new WebViewClient() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView webView, String s) {
|
||||
super.onPageFinished(webView, s);
|
||||
LogUtils.i("URL是啥加载完成:" + webView.getUrl());
|
||||
if (webView.getUrl().contains("hasSignIn")) {
|
||||
hasSignIn = true;
|
||||
}
|
||||
|
||||
int w = View.MeasureSpec.makeMeasureSpec(0,
|
||||
View.MeasureSpec.UNSPECIFIED);
|
||||
int h = View.MeasureSpec.makeMeasureSpec(0,
|
||||
View.MeasureSpec.UNSPECIFIED);
|
||||
// 重新测量
|
||||
webView.measure(w, h);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
|
||||
if (webView.getUrl().equals(url + "index") || webView.getUrl().equals(url + "/index")) {
|
||||
isAtGame = false;
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (isAtGame) {
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// if (isNetError&&isAtGame) {
|
||||
// topVvvv.setVisibility(View.VISIBLE);
|
||||
// }
|
||||
injectInputListener(webView);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
super.onReceivedError(view, request, error);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
int errorCode = error.getErrorCode();
|
||||
String errorMessage = error.getDescription().toString();
|
||||
String currentUrl = request.getUrl().toString();
|
||||
if ((errorCode == -2 || errorCode == -6) && currentUrl.contains(url)) {
|
||||
onShowErrorView(errorMessage);
|
||||
} else {
|
||||
onShowNetView();
|
||||
}
|
||||
}
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
if ((errorCode == -2 || errorCode == -6) && failingUrl.contains(url)) {
|
||||
onShowErrorView(description);
|
||||
} else {
|
||||
onShowNetView();
|
||||
}
|
||||
}
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView webView, String url1) {
|
||||
|
||||
LogUtils.i("URL是啥:" + url1);
|
||||
if (url1.equals(url + "index") || url1.equals(url + "/index")) {
|
||||
isAtGame = false;
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((url1.equals(url + "index") || url1.equals(url + "/index")) && webView.canGoBack()) {
|
||||
return false;
|
||||
} else {
|
||||
//其它的该怎么处理就怎么处理
|
||||
webView.loadUrl(url1);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView webView, String s) {
|
||||
// LogUtils.i("网址是啥:222222222222222222222222");
|
||||
|
||||
return super.shouldInterceptRequest(webView, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest webResourceRequest) {
|
||||
// LogUtils.i("网址是啥:"+webResourceRequest.getUrl().toString());
|
||||
if ("POST".equalsIgnoreCase(webResourceRequest.getMethod())) {
|
||||
// LogUtils.i("网址是啥111222:");
|
||||
// injectInputListener(webViews!=null?webViews:webView);
|
||||
postMobile();
|
||||
}
|
||||
return super.shouldInterceptRequest(webView, webResourceRequest);
|
||||
}
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
Uri uri;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
uri = request.getUrl();
|
||||
} else {
|
||||
uri = Uri.parse(request.toString());
|
||||
}
|
||||
String url1 = uri.toString();
|
||||
if (url1.equals(url + "index") || url1.equals(url + "/index")) {
|
||||
isAtGame = false;
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((url1.equals(url + "index") || url1.equals(url + "/index")) && webView.canGoBack()) {
|
||||
return false;
|
||||
} else {
|
||||
//其它的该怎么处理就怎么处理
|
||||
webView.loadUrl(url1);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
private void postMobile() {
|
||||
if(!TextUtils.isEmpty(mobiles)){
|
||||
if(!TextUtils.isEmpty(oldMobiles)&&oldMobiles.endsWith(mobiles)){
|
||||
return;
|
||||
}
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("appId", userId);
|
||||
map.put("phone", mobiles);
|
||||
Api.getInstance().appLoginUser(map)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
// LogUtils.i("成功了!!!!!!!");
|
||||
oldMobiles = mobiles;
|
||||
mobiles= "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
// LogUtils.i("成功了失败了!!!!!!!");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
// LogUtils.i("成功了失败了22222!!!!!!!");
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNetError = false;
|
||||
|
||||
public void onShowErrorView(String errorMsg) { //网络不可用的情况
|
||||
// topVvvv.setVisibility(View.GONE);
|
||||
webView.setVisibility(View.GONE);
|
||||
layoutError.setVisibility(View.VISIBLE);
|
||||
tvErrorMsg.setText(errorMsg);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
isNetError = true;
|
||||
|
||||
}
|
||||
|
||||
public void onShowNetView() {
|
||||
// topVvvv.setVisibility(View.GONE);
|
||||
webView.setVisibility(View.VISIBLE);
|
||||
layoutError.setVisibility(View.GONE);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
isNetError = false;
|
||||
}
|
||||
|
||||
|
||||
boolean isAtGame = false;
|
||||
// String uuid = "", uuid1 = "";
|
||||
private static final int REQUEST_CODE_FILE_CHOOSER = 1;
|
||||
private ValueCallback<Uri> mUploadCallbackForLowApi;
|
||||
private ValueCallback<Uri[]> mUploadCallbackForHighApi;
|
||||
WebChromeClient webChromeClient = new WebChromeClient() {
|
||||
@Override
|
||||
public boolean onCreateWindow(WebView webViewdd, boolean b, boolean b1, Message resultMsg) {
|
||||
LogUtils.i("URL是啥onCreateWindow:" + webView.getUrl());
|
||||
// WebView newWebView = new WebView(MainActivity2.this);
|
||||
// topVvvv.setVisibility(View.VISIBLE);
|
||||
// webView.addView(newWebView);
|
||||
// WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
// transport.setWebView(newWebView);
|
||||
// resultMsg.sendToTarget();
|
||||
//
|
||||
// newWebView.setWebViewClient(new WebViewClient() {
|
||||
// @Override
|
||||
// public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// isAtGame = true;
|
||||
// webView.loadUrl(url);
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
|
||||
WebView newWebView = new WebView(webViewdd.getContext());
|
||||
newWebView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
if (!(url.startsWith("http") || url.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
LogUtils.i("地址是啥:"+url);
|
||||
Intent browserIntent = new Intent(MainActivity2.this, WebViewActivity.class);
|
||||
browserIntent.putExtra("url", url);
|
||||
startActivity(browserIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
transport.setWebView(newWebView);
|
||||
resultMsg.sendToTarget();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCloseWindow(WebView window) {
|
||||
super.onCloseWindow(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
// 更新进度条的进度
|
||||
progressBar.setProgress(newProgress);
|
||||
// 如果加载完成,隐藏进度条
|
||||
if (newProgress == 100) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
|
||||
LogUtils.i("数据接口:onShowFileChooser");
|
||||
mUploadCallbackForHighApi = filePathCallback;
|
||||
Intent intent = fileChooserParams.createIntent();
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_CODE_FILE_CHOOSER);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
// mUploadCallbackForHighApi = null;
|
||||
// WidgetUtils.showToast(JsBridgeActivity.this, "未知错误", WidgetUtils.ToastType.ERROR);
|
||||
// Toast.makeText(MainActivity2.this, "未知错误", Toast.LENGTH_SHORT).show();
|
||||
startActivityForResult(Intent.createChooser(intent, "File chooser"), REQUEST_CODE_FILE_CHOOSER);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// For 3.0+
|
||||
protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
|
||||
LogUtils.i("数据接口:openFileChooseracceptType");
|
||||
|
||||
openFilerChooser(uploadMsg);
|
||||
}
|
||||
|
||||
|
||||
private void openFilerChooser(ValueCallback<Uri> uploadMsg) {
|
||||
LogUtils.i("数据接口:openFileChooser");
|
||||
|
||||
mUploadCallbackForLowApi = uploadMsg;
|
||||
startActivityForResult(Intent.createChooser(getFilerChooserIntent(), "File Chooser"), REQUEST_CODE_FILE_CHOOSER);
|
||||
}
|
||||
|
||||
|
||||
private Intent getFilerChooserIntent() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPermissionRequest(PermissionRequest request) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
MainActivity2.this.runOnUiThread(new Runnable() {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void run() {
|
||||
for (String permisson : request.getResources()) {
|
||||
permissionRequest = request;
|
||||
if (permisson.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
|
||||
if (ContextCompat.checkSelfPermission(MainActivity2.this, Manifest.permission.CAMERA) != 0) {
|
||||
ActivityCompat.requestPermissions(MainActivity2.this, PERMISSIONS_CAMERA, 1111);
|
||||
} else {
|
||||
request.grant(request.getResources());
|
||||
request.getOrigin();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private PermissionRequest permissionRequest;
|
||||
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.Q)
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_FILE_CHOOSER:
|
||||
if (resultCode == RESULT_OK || resultCode == RESULT_CANCELED) {
|
||||
afterFileChooseGoing(resultCode, data);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* onActivityResult方法
|
||||
*/
|
||||
|
||||
private void afterFileChooseGoing(int resultCode, Intent data) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (mUploadCallbackForHighApi == null) {
|
||||
return;
|
||||
}
|
||||
mUploadCallbackForHighApi.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
|
||||
mUploadCallbackForHighApi = null;
|
||||
} else {
|
||||
if (mUploadCallbackForLowApi == null) {
|
||||
return;
|
||||
}
|
||||
Uri result = data == null ? null : data.getData();
|
||||
mUploadCallbackForLowApi.onReceiveValue(result);
|
||||
mUploadCallbackForLowApi = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class JavaScriptinterface {
|
||||
Context context;
|
||||
|
||||
public JavaScriptinterface(Context c) {
|
||||
context = c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
String permissions[], int[] grantResults) {
|
||||
if (grantResults.length == 0) {
|
||||
return;
|
||||
}
|
||||
switch (requestCode) {
|
||||
case REQUEST_EXTERNAL_STORAGE:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
|
||||
}
|
||||
break;
|
||||
case 1111:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && permissionRequest != null) {
|
||||
permissionRequest.grant(permissionRequest.getResources());
|
||||
}
|
||||
break;
|
||||
case 2222:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
readContact();
|
||||
} else {
|
||||
//没同意
|
||||
// MainActivity2.this.finish();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置网页中图片的点击事件
|
||||
*
|
||||
* @param view
|
||||
*/
|
||||
public static void setWebImageClick(WebView view, String method) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
if (webView != null) {
|
||||
//加载null内容
|
||||
webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
|
||||
//清除历史记录
|
||||
webView.clearHistory();
|
||||
//移除WebView
|
||||
// ((ViewGroup) webView.getParent()).removeView(webView);
|
||||
//销毁VebView
|
||||
webView.destroy();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
checkNotify();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取状态栏高度
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getStatusBarHeight() {
|
||||
int result = 0;
|
||||
//获取状态栏高度的资源id
|
||||
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//wp-caption alignnone
|
||||
|
||||
|
||||
}
|
||||
568
winwaynew/src/main/java/just/way/MainActivity3.java
Normal file
@@ -0,0 +1,568 @@
|
||||
package just.way;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.DownloadListener;
|
||||
import android.webkit.ValueCallback;
|
||||
import com.just.agentweb.WebChromeClient;
|
||||
import android.webkit.WebResourceError;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import com.just.agentweb.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import com.just.agentweb.AgentWeb;
|
||||
//import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
|
||||
//import com.tencent.smtt.sdk.DownloadListener;
|
||||
//import com.tencent.smtt.sdk.URLUtil;
|
||||
//import com.tencent.smtt.sdk.ValueCallback;
|
||||
//import com.tencent.smtt.sdk.WebChromeClient;
|
||||
//import com.tencent.smtt.sdk.WebSettings;
|
||||
//import com.tencent.smtt.sdk.WebView;
|
||||
//import com.tencent.smtt.sdk.WebViewClient;
|
||||
|
||||
|
||||
public class MainActivity3 extends AppCompatActivity {
|
||||
LinearLayout webView;
|
||||
ImageView show_top_v;
|
||||
ImageView menu_iv;
|
||||
private ImageView helpIv;
|
||||
private LinearLayout showTopLy;
|
||||
|
||||
String downloadImageUrl = "";
|
||||
private int requestCode;
|
||||
private String[] permissions;
|
||||
private int[] grantResults;
|
||||
private View topVvvv;
|
||||
private int index = 0;
|
||||
private FrameLayout videoContainer;
|
||||
|
||||
private ImageView backIv;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
AgentWeb mAgentWeb;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
getWindow().setNavigationBarColor(getColor(R.color.white));
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
View decor = getWindow().getDecorView();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
setContentView(R.layout.activity_main3);
|
||||
initView();
|
||||
// setopHeight();
|
||||
findViewById(R.id.back_iv).setOnClickListener(view -> onBackPressed());
|
||||
}
|
||||
|
||||
public void hideStatusBar(Activity activity) {
|
||||
if (activity == null) return;
|
||||
Window window = activity.getWindow();
|
||||
if (window == null) return;
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
}
|
||||
window.setAttributes(lp);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
|
||||
// if (mAgentWeb.canGoBack()) {//当webview有多级能返回的时候
|
||||
// // 在首页 就退出这个页面
|
||||
// if (webView.getUrl().equals(url + "index") || webView.getUrl().equals(url + "/index")) {
|
||||
//
|
||||
// Intent intent = new Intent(this, MainActivity.class);
|
||||
// startActivity(intent);
|
||||
// super.onBackPressed();
|
||||
// } else { //不在首页 回到首页
|
||||
// if (webView.getUrl().equals(url + "index") || webView.getUrl().equals(url + "/index")) {
|
||||
// isAtGame = false;
|
||||
// }
|
||||
// topVvvv.setVisibility(View.GONE);
|
||||
// progressBar.setVisibility(View.VISIBLE);
|
||||
// webView.loadUrl(url);
|
||||
// }
|
||||
// } else {//不能返回了
|
||||
//
|
||||
// //返回计算器
|
||||
// Intent intent = new Intent(this, MainActivity.class);
|
||||
// startActivity(intent);
|
||||
//// }
|
||||
super.onBackPressed();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改图标和名称的方法
|
||||
*/
|
||||
public void changeIcon() {
|
||||
PackageManager pm = getApplicationContext().getPackageManager();
|
||||
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
this,
|
||||
"just.way.MainActivity"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
Log.d("TAG", "换Test的图标");
|
||||
|
||||
pm.setComponentEnabledSetting(new ComponentName(
|
||||
this,
|
||||
"just.way.MainActivityNew"),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
|
||||
}
|
||||
|
||||
private void setopHeight() {
|
||||
RelativeLayout.LayoutParams linearParams = (RelativeLayout.LayoutParams) topVvvv.getLayoutParams(); //取控件textView当前的布局参数
|
||||
linearParams.height = getStatusBarHeight();// 控件的宽强制设成30
|
||||
|
||||
topVvvv.setLayoutParams(linearParams);
|
||||
}
|
||||
|
||||
//https://m.xiannvtu.com/
|
||||
public static String url = "http://winway33.com/";
|
||||
|
||||
// https://telegram.2ltop.com/url.json?rand=111111111
|
||||
//先定义
|
||||
private static final int REQUEST_EXTERNAL_STORAGE = 1;
|
||||
|
||||
private static String[] PERMISSIONS_STORAGE = {
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE"};
|
||||
|
||||
//然后通过一个函数来申请
|
||||
public static void verifyStoragePermissions(Activity activity) {
|
||||
|
||||
// 没有写的权限,去申请写的权限,会弹出对话框
|
||||
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint({"NewApi", "WrongConstant"})
|
||||
protected void initView() {
|
||||
topVvvv = (View) findViewById(R.id.top_vvvv);
|
||||
webView = findViewById(R.id.webview);
|
||||
show_top_v = findViewById(R.id.show_top_v);
|
||||
showTopLy = findViewById(R.id.show_top_ly);
|
||||
videoContainer = (FrameLayout) findViewById(R.id.videoContainer);
|
||||
// topVvvvf = (RelativeLayout) findViewById(R.id.top_vvvvf);
|
||||
// topVvvv1 = (StatusLayout) findViewById(R.id.top_vvvv1);
|
||||
backIv = (ImageView) findViewById(R.id.back_iv);
|
||||
progressBar = (ProgressBar) findViewById(R.id.progressbar);
|
||||
|
||||
// WebSettings settings = webView.getSettings();
|
||||
// settings.setDomStorageEnabled(true);
|
||||
// settings.setAppCacheEnabled(true);
|
||||
// settings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
// settings.setJavaScriptEnabled(true);
|
||||
// settings.setLoadWithOverviewMode(true);
|
||||
// // 设置允许访问文件数据
|
||||
// settings.setAllowFileAccess(true);
|
||||
// settings.setAllowContentAccess(true);
|
||||
// settings.setDatabaseEnabled(true);
|
||||
// settings.setSavePassword(false);
|
||||
// settings.setSaveFormData(false);
|
||||
// settings.setUseWideViewPort(true);
|
||||
// settings.setBuiltInZoomControls(true);
|
||||
// settings.setPluginState(WebSettings.PluginState.ON);
|
||||
// settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
// webView.setFocusable(true);
|
||||
// webView.setFocusableInTouchMode(true);
|
||||
// webView.getSettings().setSupportMultipleWindows(true);
|
||||
//
|
||||
// settings.setSupportZoom(false);
|
||||
// webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
|
||||
//// webView.setHorizontalScrollbarOverlay(true);
|
||||
// webView.setHorizontalScrollBarEnabled(true);
|
||||
// webView.requestFocus();
|
||||
//// webView.setBackgroundColor(getColor(R.color.black));
|
||||
// settings.setJavaScriptCanOpenWindowsAutomatically(true);
|
||||
//
|
||||
// // 设置在WebView内部是否允许通过file url加载的 Js代码读取其他的本地文件
|
||||
// // Android 4.1前默认允许,4.1后默认禁止
|
||||
// settings.setAllowFileAccessFromFileURLs(true);
|
||||
// // 设置WebView内部是否允许通过 file url 加载的 Javascript 可以访问其他的源(包括http、https等源)
|
||||
// // Android 4.1前默认允许,4.1后默认禁止
|
||||
// settings.setAllowUniversalAccessFromFileURLs(true);
|
||||
//
|
||||
//
|
||||
// webView.setWebChromeClient(webChromeClient);
|
||||
// webView.setWebViewClient(webViewClient);
|
||||
// Log.i("XHXDEBUG", "XHXDEBUGURL:::" + url);
|
||||
//
|
||||
//// new Handler().postDelayed(() -> showTopLy.setVisibility(View.GONE), 3000);
|
||||
//// verifyStoragePermissions(this);
|
||||
//
|
||||
// webView.setDownloadListener(new DownloadListener() {
|
||||
// @Override
|
||||
// public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
|
||||
// LogUtils.i("URL是啥onDownloadStart:" + url);
|
||||
//
|
||||
// try {
|
||||
// Intent intent = new Intent();
|
||||
// intent.setAction(Intent.ACTION_VIEW);
|
||||
// intent.setData(Uri.parse(url));
|
||||
// startActivity(intent);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// });
|
||||
getNetUrl();
|
||||
}
|
||||
public void getNetUrl(){
|
||||
// Api.getInstance().geUrl(System.currentTimeMillis())
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(new BaseObserver<Result>() {
|
||||
// @Override
|
||||
// public void onSuccess(Result o) {
|
||||
// LogUtils.i("URL是啥获取的文件地址:"+o.url);
|
||||
// if(!TextUtils.isEmpty(o.url)){
|
||||
// MainActivity.saveString(MainActivity3.this,"base_url",o.url);
|
||||
// url = MainActivity.getString(MainActivity3.this, "base_url", url);
|
||||
// toUrl(url);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(int code, String msg) {
|
||||
// url = MainActivity.getString(MainActivity3.this, "base_url", url);
|
||||
// toUrl(url);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
private void toUrl(String url) {
|
||||
mAgentWeb = AgentWeb.with(this)
|
||||
.setAgentWebParent( webView, new LinearLayout.LayoutParams(-1, -1))
|
||||
.useDefaultIndicator()
|
||||
.setWebViewClient(webViewClient)
|
||||
.setWebChromeClient(webChromeClient)
|
||||
.createAgentWeb()
|
||||
|
||||
.ready()
|
||||
.go(url);
|
||||
|
||||
}
|
||||
|
||||
|
||||
WebViewClient webViewClient = new WebViewClient() {
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView webView, String s) {
|
||||
super.onPageFinished(webView, s);
|
||||
LogUtils.i("URL是啥加载完成:" + webView.getUrl());
|
||||
|
||||
int w = View.MeasureSpec.makeMeasureSpec(0,
|
||||
View.MeasureSpec.UNSPECIFIED);
|
||||
int h = View.MeasureSpec.makeMeasureSpec(0,
|
||||
View.MeasureSpec.UNSPECIFIED);
|
||||
// 重新测量
|
||||
webView.measure(w, h);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
|
||||
if (webView.getUrl().equals(url + "index") || webView.getUrl().equals(url + "/index")) {
|
||||
isAtGame = false;
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
|
||||
} else {
|
||||
if (isAtGame) {
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// @Override
|
||||
// public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
// super.onReceivedError(view, request, error);
|
||||
// if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// int errorCode = error.getErrorCode();
|
||||
// String errorMessage = error.getDescription().toString();
|
||||
// Log.i("CustomWebViewClient", "onReceivedError errorCode : " + errorCode + " errorMessage : " + errorMessage);
|
||||
// }
|
||||
// progressBar.setVisibility(View.GONE);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
Log.i("CustomWebViewClient", "onReceivedError errorCode : " + errorCode + " description : " + description);
|
||||
}
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean shouldOverrideUrlLoading(WebView webView, String s) {
|
||||
// LogUtils.i("URL是啥:"+s);
|
||||
// return super.shouldOverrideUrlLoading(webView, s);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView webView, String url1) {
|
||||
|
||||
LogUtils.i("URL是啥:" + url1);
|
||||
if (url1.equals(url + "index") || url1.equals(url + "/index")) {
|
||||
isAtGame = false;
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
}else{
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
//其它的该怎么处理就怎么处理
|
||||
webView.loadUrl(url1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
boolean isAtGame = false;
|
||||
// String uuid = "", uuid1 = "";
|
||||
private static final int REQUEST_CODE_FILE_CHOOSER = 1;
|
||||
private ValueCallback<Uri> mUploadCallbackForLowApi;
|
||||
private ValueCallback<Uri[]> mUploadCallbackForHighApi;
|
||||
WebChromeClient webChromeClient = new WebChromeClient() {
|
||||
// @Override
|
||||
// public boolean onCreateWindow(WebView webViewdd, boolean b, boolean b1, Message resultMsg) {
|
||||
// LogUtils.i("URL是啥onCreateWindow:" + webViewdd.getUrl());
|
||||
//
|
||||
// WebView newWebView = new WebView(MainActivity3.this);
|
||||
// newWebView.setWebViewClient(new WebViewClient() {
|
||||
// @Override
|
||||
// public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// isAtGame = true;
|
||||
// mAgentWeb.getUrlLoader().loadUrl(url);
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
|
||||
return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
// 更新进度条的进度
|
||||
progressBar.setProgress(newProgress);
|
||||
// 如果加载完成,隐藏进度条
|
||||
if (newProgress == 100) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.Q)
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_FILE_CHOOSER:
|
||||
if (resultCode == RESULT_OK || resultCode == RESULT_CANCELED) {
|
||||
afterFileChooseGoing(resultCode, data);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* onActivityResult方法
|
||||
*/
|
||||
|
||||
private void afterFileChooseGoing(int resultCode, Intent data) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (mUploadCallbackForHighApi == null) {
|
||||
return;
|
||||
}
|
||||
mUploadCallbackForHighApi.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
|
||||
mUploadCallbackForHighApi = null;
|
||||
} else {
|
||||
if (mUploadCallbackForLowApi == null) {
|
||||
return;
|
||||
}
|
||||
Uri result = data == null ? null : data.getData();
|
||||
mUploadCallbackForLowApi.onReceiveValue(result);
|
||||
mUploadCallbackForLowApi = null;
|
||||
}
|
||||
}
|
||||
public class JavaScriptinterface {
|
||||
Context context;
|
||||
|
||||
public JavaScriptinterface(Context c) {
|
||||
context = c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
String permissions[], int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_EXTERNAL_STORAGE:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置网页中图片的点击事件
|
||||
*
|
||||
* @param view
|
||||
*/
|
||||
public static void setWebImageClick(WebView view, String method) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
//
|
||||
// if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
//
|
||||
// if (webView.canGoBack()) {
|
||||
// webView.goBack();
|
||||
// return true;
|
||||
// } else {
|
||||
// return super.onKeyDown(keyCode, event);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// return super.onKeyDown(keyCode, event);
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
if (webView != null) {
|
||||
//加载null内容
|
||||
// webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
|
||||
// //清除历史记录
|
||||
// webView.clearHistory();
|
||||
//移除WebView
|
||||
// ((ViewGroup) webView.getParent()).removeView(webView);
|
||||
//销毁VebView
|
||||
mAgentWeb.destroy();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取状态栏高度
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getStatusBarHeight() {
|
||||
int result = 0;
|
||||
//获取状态栏高度的资源id
|
||||
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//wp-caption alignnone
|
||||
|
||||
|
||||
}
|
||||
61
winwaynew/src/main/java/just/way/MessageInfo.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package just.way;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class MessageInfo implements Serializable {
|
||||
|
||||
private String title;
|
||||
private String content;
|
||||
private String image="";
|
||||
private int type;
|
||||
private int pushId;
|
||||
private String jumpUrl;
|
||||
|
||||
public String getJumpUrl() {
|
||||
return jumpUrl;
|
||||
}
|
||||
|
||||
public void setJumpUrl(String jumpUrl) {
|
||||
this.jumpUrl = jumpUrl;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getPushId() {
|
||||
return pushId;
|
||||
}
|
||||
|
||||
public void setPushId(int pushId) {
|
||||
this.pushId = pushId;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package just.way;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class MyFirebaseMessageingService extends FirebaseMessagingService {
|
||||
|
||||
public MyFirebaseMessageingService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
|
||||
super.onMessageReceived(remoteMessage);
|
||||
Map<String, String> serviceData = remoteMessage.getData(); //后台推送数据
|
||||
if (serviceData != null && serviceData.containsKey("message")) {
|
||||
String value = serviceData.get("message");
|
||||
Gson gson = new Gson();
|
||||
MessageInfo messageInfo = gson.fromJson(value, MessageInfo.class);
|
||||
showNotification(messageInfo);
|
||||
// if (remoteMessage.getNotification() != null) {
|
||||
// showNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
|
||||
// }
|
||||
} else {
|
||||
//收到通知 创建notify
|
||||
if (remoteMessage.getNotification() != null) {
|
||||
showNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void showNotification(MessageInfo messageInfo) {
|
||||
Intent notifyIntent = new Intent(this, MainActivity2.class);
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.CUPCAKE) {
|
||||
ComponentName launchComponent = null;
|
||||
launchComponent = getApplication()
|
||||
.getPackageManager()
|
||||
.getLaunchIntentForPackage(getApplication().getPackageName())
|
||||
.getComponent();
|
||||
notifyIntent.setComponent(launchComponent);
|
||||
}
|
||||
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
notifyIntent.setAction(Intent.ACTION_VIEW);
|
||||
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 必须
|
||||
notifyIntent.putExtra("message", messageInfo);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
// Intent notifyIntent = new Intent(this, MainActivity2.class);
|
||||
// notifyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
// // notifyIntent.putExtra("message", messageInfo);
|
||||
// notifyIntent.setAction(Intent.ACTION_VIEW);
|
||||
// notifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 必须
|
||||
// PendingIntent pendingIntent;
|
||||
// pendingIntent = PendingIntent.getActivity
|
||||
// (this, 0, notifyIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationChannel channelwinway = null;
|
||||
NotificationCompat.Builder notificationBuilder = null;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
channelwinway = new NotificationChannel(getString(R.string.app_name), "notify", NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channelwinway.enableLights(true);
|
||||
channelwinway.enableVibration(true);
|
||||
notificationManager.createNotificationChannel(channelwinway);
|
||||
notificationBuilder = new NotificationCompat.Builder(this, channelwinway.getId())
|
||||
.setSmallIcon(R.mipmap.jisuanqi_logo)
|
||||
.setContentTitle(messageInfo.getTitle())
|
||||
.setContentText(messageInfo.getContent())
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
} else {
|
||||
notificationBuilder = new NotificationCompat.Builder(this, getString(R.string.app_name))
|
||||
.setSmallIcon(R.mipmap.jisuanqi_logo)
|
||||
.setContentTitle(messageInfo.getTitle())
|
||||
.setContentText(messageInfo.getContent())
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
}
|
||||
notificationManager.notify(0, notificationBuilder.build());
|
||||
}
|
||||
|
||||
private void showNotification(String title, String body) {
|
||||
Intent notifyIntent = new Intent(this, MainActivity2.class);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
|
||||
ComponentName launchComponent = null;
|
||||
launchComponent = getApplication()
|
||||
.getPackageManager()
|
||||
.getLaunchIntentForPackage(getApplication().getPackageName())
|
||||
.getComponent();
|
||||
notifyIntent.setComponent(launchComponent);
|
||||
}
|
||||
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
notifyIntent.setAction(Intent.ACTION_VIEW);
|
||||
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 必须
|
||||
notifyIntent.putExtra("message", body);
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationChannel channelwinway = null;
|
||||
NotificationCompat.Builder notificationBuilder = null;
|
||||
MessageInfo messageInfo = GsonUtils.getObjFromJSON(body,MessageInfo.class);
|
||||
if(messageInfo!=null){
|
||||
body = messageInfo.getContent();
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
channelwinway = new NotificationChannel(getString(R.string.app_name), "notify", NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channelwinway.enableLights(true);
|
||||
channelwinway.enableVibration(true);
|
||||
notificationManager.createNotificationChannel(channelwinway);
|
||||
notificationBuilder = new NotificationCompat.Builder(this, channelwinway.getId())
|
||||
.setSmallIcon(R.mipmap.jisuanqi_logo)
|
||||
.setContentTitle(title)
|
||||
.setContentText(body)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
} else {
|
||||
notificationBuilder = new NotificationCompat.Builder(this, getString(R.string.app_name))
|
||||
.setSmallIcon(R.mipmap.jisuanqi_logo)
|
||||
.setContentTitle(title)
|
||||
.setContentText(body)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
}
|
||||
notificationManager.notify(0, notificationBuilder.build());
|
||||
}
|
||||
|
||||
}
|
||||
381
winwaynew/src/main/java/just/way/NotifyDetailsActivity.java
Normal file
@@ -0,0 +1,381 @@
|
||||
package just.way;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.tencent.smtt.export.external.interfaces.PermissionRequest;
|
||||
import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
|
||||
import com.tencent.smtt.sdk.DownloadListener;
|
||||
import com.tencent.smtt.sdk.ValueCallback;
|
||||
import com.tencent.smtt.sdk.WebChromeClient;
|
||||
import com.tencent.smtt.sdk.WebSettings;
|
||||
import com.tencent.smtt.sdk.WebView;
|
||||
import com.tencent.smtt.sdk.WebViewClient;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
//通知详情
|
||||
public class NotifyDetailsActivity extends AppCompatActivity {
|
||||
|
||||
|
||||
WebView webView;
|
||||
private LinearLayout showTopLy;
|
||||
private ImageView backIv;
|
||||
private ImageView contentIv;
|
||||
|
||||
public static String url = "https://vv88.io/";
|
||||
private static String[] PERMISSIONS_STORAGE = {
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE"};
|
||||
|
||||
private static String[] PERMISSIONS_CAMERA = {
|
||||
Manifest.permission.CAMERA};
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
getWindow().setNavigationBarColor(getColor(R.color.white));
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
super.onCreate(savedInstanceState);
|
||||
View decor = getWindow().getDecorView();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
setContentView(R.layout.activity_notifydetails);
|
||||
initView();
|
||||
MessageInfo messageInfo = (MessageInfo) getIntent().getSerializableExtra("message");
|
||||
if (messageInfo != null) {
|
||||
recordNotify(messageInfo.getPushId());
|
||||
if (messageInfo.getType() == 3) {
|
||||
webView.setVisibility(View.VISIBLE);
|
||||
webView.loadUrl(messageInfo.getJumpUrl());
|
||||
}
|
||||
if (messageInfo.getType() == 2) {
|
||||
contentIv.setVisibility(View.VISIBLE);
|
||||
Glide.with(NotifyDetailsActivity.this).load(messageInfo.getImage()).into(contentIv);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void recordNotify(int pushId) {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("pushId", pushId);
|
||||
Api.getInstance().totalNotify(map)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressLint({"NewApi", "WrongConstant"})
|
||||
protected void initView() {
|
||||
webView = findViewById(R.id.webview);
|
||||
showTopLy = findViewById(R.id.show_top_ly);
|
||||
backIv = (ImageView) findViewById(R.id.back_iv);
|
||||
contentIv = findViewById(R.id.image);
|
||||
WebSettings settings = webView.getSettings();
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setAppCacheEnabled(true);
|
||||
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
// 设置允许访问文件数据
|
||||
settings.setAllowFileAccess(true);
|
||||
settings.setAllowContentAccess(true);
|
||||
settings.setDatabaseEnabled(true);
|
||||
settings.setSavePassword(false);
|
||||
settings.setSaveFormData(false);
|
||||
settings.setUseWideViewPort(true);
|
||||
settings.setBuiltInZoomControls(true);
|
||||
settings.setPluginState(WebSettings.PluginState.ON);
|
||||
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
webView.setFocusable(true);
|
||||
webView.setFocusableInTouchMode(true);
|
||||
webView.getSettings().setSupportMultipleWindows(true);
|
||||
|
||||
settings.setSupportZoom(true);
|
||||
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
|
||||
// webView.setHorizontalScrollbarOverlay(true);
|
||||
webView.setHorizontalScrollBarEnabled(true);
|
||||
webView.requestFocus();
|
||||
// webView.setBackgroundColor(getColor(R.color.black));
|
||||
settings.setJavaScriptCanOpenWindowsAutomatically(true);
|
||||
settings.setMediaPlaybackRequiresUserGesture(false);
|
||||
// 设置在WebView内部是否允许通过file url加载的 Js代码读取其他的本地文件
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowFileAccessFromFileURLs(true);
|
||||
// 设置WebView内部是否允许通过 file url 加载的 Javascript 可以访问其他的源(包括http、https等源)
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowUniversalAccessFromFileURLs(true);
|
||||
|
||||
webView.setWebChromeClient(webChromeClient);
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView webView, String s) {
|
||||
super.onPageFinished(webView, s);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest webResourceRequest) {
|
||||
Uri uri;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
uri = webResourceRequest.getUrl();
|
||||
} else {
|
||||
uri = Uri.parse(webResourceRequest.toString());
|
||||
}
|
||||
String url1 = uri.toString();
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
//其它的该怎么处理就怎么处理
|
||||
webView.loadUrl(url1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView webView, String url1) {
|
||||
LogUtils.i("URL是啥:" + url1);
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
//其它的该怎么处理就怎么处理
|
||||
webView.loadUrl(url1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// new Handler().postDelayed(() -> showTopLy.setVisibility(View.GONE), 3000);
|
||||
// verifyStoragePermissions(this);
|
||||
|
||||
webView.setDownloadListener(new DownloadListener() {
|
||||
@Override
|
||||
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
|
||||
LogUtils.i("URL是啥onDownloadStart:" + url);
|
||||
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
backIv.setOnClickListener(view -> finish());
|
||||
|
||||
}
|
||||
|
||||
private static final int REQUEST_CODE_FILE_CHOOSER = 1;
|
||||
private ValueCallback<Uri> mUploadCallbackForLowApi;
|
||||
private ValueCallback<Uri[]> mUploadCallbackForHighApi;
|
||||
WebChromeClient webChromeClient = new WebChromeClient() {
|
||||
@Override
|
||||
public boolean onCreateWindow(WebView webViewdd, boolean b, boolean b1, Message resultMsg) {
|
||||
LogUtils.i("URL是啥onCreateWindow:" + webView.getUrl());
|
||||
// WebView newWebView = new WebView(MainActivity2.this);
|
||||
// topVvvv.setVisibility(View.VISIBLE);
|
||||
// webView.addView(newWebView);
|
||||
// WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
// transport.setWebView(newWebView);
|
||||
// resultMsg.sendToTarget();
|
||||
//
|
||||
// newWebView.setWebViewClient(new WebViewClient() {
|
||||
// @Override
|
||||
// public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// isAtGame = true;
|
||||
// webView.loadUrl(url);
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
|
||||
WebView newWebView = new WebView(webViewdd.getContext());
|
||||
newWebView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
if (!(url.startsWith("http") || url.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
Intent browserIntent = new Intent(NotifyDetailsActivity.this, WebViewActivity.class);
|
||||
browserIntent.putExtra("url", url);
|
||||
startActivity(browserIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
transport.setWebView(newWebView);
|
||||
resultMsg.sendToTarget();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCloseWindow(WebView window) {
|
||||
super.onCloseWindow(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
// 更新进度条的进度
|
||||
|
||||
}
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
|
||||
LogUtils.i("数据接口:onShowFileChooser");
|
||||
mUploadCallbackForHighApi = filePathCallback;
|
||||
Intent intent = fileChooserParams.createIntent();
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_CODE_FILE_CHOOSER);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
// mUploadCallbackForHighApi = null;
|
||||
// WidgetUtils.showToast(JsBridgeActivity.this, "未知错误", WidgetUtils.ToastType.ERROR);
|
||||
// Toast.makeText(MainActivity2.this, "未知错误", Toast.LENGTH_SHORT).show();
|
||||
startActivityForResult(Intent.createChooser(intent, "File chooser"), REQUEST_CODE_FILE_CHOOSER);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// For 3.0+
|
||||
protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
|
||||
LogUtils.i("数据接口:openFileChooseracceptType");
|
||||
|
||||
openFilerChooser(uploadMsg);
|
||||
}
|
||||
|
||||
|
||||
private void openFilerChooser(ValueCallback<Uri> uploadMsg) {
|
||||
LogUtils.i("数据接口:openFileChooser");
|
||||
|
||||
mUploadCallbackForLowApi = uploadMsg;
|
||||
startActivityForResult(Intent.createChooser(getFilerChooserIntent(), "File Chooser"), REQUEST_CODE_FILE_CHOOSER);
|
||||
}
|
||||
|
||||
|
||||
private Intent getFilerChooserIntent() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPermissionRequest(PermissionRequest request) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
NotifyDetailsActivity.this.runOnUiThread(new Runnable() {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void run() {
|
||||
for (String permisson : request.getResources()) {
|
||||
permissionRequest = request;
|
||||
if (permisson.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
|
||||
if (ContextCompat.checkSelfPermission(NotifyDetailsActivity.this, Manifest.permission.CAMERA) != 0) {
|
||||
ActivityCompat.requestPermissions(NotifyDetailsActivity.this, PERMISSIONS_CAMERA, 1111);
|
||||
} else {
|
||||
request.grant(request.getResources());
|
||||
request.getOrigin();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private PermissionRequest permissionRequest;
|
||||
|
||||
}
|
||||
29
winwaynew/src/main/java/just/way/Result.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package just.way;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* created by wmm on 2020/9/8
|
||||
*/
|
||||
public class Result<T> implements Serializable {
|
||||
|
||||
public String error;
|
||||
public int code;
|
||||
public T data;
|
||||
public String message;
|
||||
|
||||
|
||||
public boolean isSuccessful() {
|
||||
return code == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Result{" +
|
||||
"message='" + error + '\'' +
|
||||
", code=" + code +
|
||||
", data=" + GsonUtils.beanToJSONString(data) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
233
winwaynew/src/main/java/just/way/StartActivity.java
Normal file
@@ -0,0 +1,233 @@
|
||||
package just.way;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class StartActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
|
||||
private StringBuilder currentInput = new StringBuilder("");
|
||||
private BigDecimal currentAnswer = new BigDecimal(0);
|
||||
private boolean hasCount = false;
|
||||
private Button btn_0, btn_1, btn_2, btn_3, btn_4, btn_5, btn_6, btn_7, btn_8, btn_9, btn_equal;
|
||||
private TextView password1;
|
||||
private TextView password2;
|
||||
private TextView password3;
|
||||
private TextView password4;
|
||||
private TextView password5;
|
||||
private TextView password6;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
getWindow().setNavigationBarColor(getColor(R.color.white));
|
||||
super.onCreate(savedInstanceState);
|
||||
View decor = getWindow().getDecorView();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
setContentView(R.layout.activity_start);
|
||||
|
||||
setListener();
|
||||
getNetUrl();
|
||||
|
||||
}
|
||||
|
||||
public void setListener() {
|
||||
|
||||
|
||||
password1 = (TextView) findViewById(R.id.password_1);
|
||||
password2 = (TextView) findViewById(R.id.password_2);
|
||||
password3 = (TextView) findViewById(R.id.password_3);
|
||||
password4 = (TextView) findViewById(R.id.password_4);
|
||||
password5 = (TextView) findViewById(R.id.password_5);
|
||||
password6 = (TextView) findViewById(R.id.password_6);
|
||||
|
||||
|
||||
btn_0 = (Button) findViewById(R.id.btn_0);
|
||||
btn_0.setOnClickListener(this);
|
||||
btn_1 = (Button) findViewById(R.id.btn_1);
|
||||
btn_1.setOnClickListener(this);
|
||||
btn_2 = (Button) findViewById(R.id.btn_2);
|
||||
btn_2.setOnClickListener(this);
|
||||
btn_3 = (Button) findViewById(R.id.btn_3);
|
||||
btn_3.setOnClickListener(this);
|
||||
btn_4 = (Button) findViewById(R.id.btn_4);
|
||||
btn_4.setOnClickListener(this);
|
||||
btn_5 = (Button) findViewById(R.id.btn_5);
|
||||
btn_5.setOnClickListener(this);
|
||||
btn_6 = (Button) findViewById(R.id.btn_6);
|
||||
btn_6.setOnClickListener(this);
|
||||
btn_7 = (Button) findViewById(R.id.btn_7);
|
||||
btn_7.setOnClickListener(this);
|
||||
btn_8 = (Button) findViewById(R.id.btn_8);
|
||||
btn_8.setOnClickListener(this);
|
||||
btn_9 = (Button) findViewById(R.id.btn_9);
|
||||
btn_9.setOnClickListener(this);
|
||||
|
||||
btn_equal = (Button) findViewById(R.id.btn_equal);
|
||||
btn_equal.setOnClickListener(this);
|
||||
}
|
||||
|
||||
String password = "";
|
||||
|
||||
/**
|
||||
* 0 正常增加 1 删除 2 更新
|
||||
*
|
||||
* @param string
|
||||
* @param type
|
||||
*/
|
||||
public void addInput(String string, int type) {
|
||||
if (type == 0) {
|
||||
if (password.length() < 6) {
|
||||
password += string;
|
||||
}
|
||||
} else if (type == 1) {
|
||||
password = password.substring(0, password.length() - 1);
|
||||
}
|
||||
if (password.length() == 6) {
|
||||
password6.setText(password.charAt(5) + "");
|
||||
toNext();
|
||||
} else {
|
||||
password6.setText("");
|
||||
if (password.length() == 5) {
|
||||
password5.setText(password.charAt(4) + "");
|
||||
} else {
|
||||
password5.setText("");
|
||||
if (password.length() == 4) {
|
||||
password4.setText(password.charAt(3) + "");
|
||||
} else {
|
||||
password4.setText("");
|
||||
if (password.length() == 3) {
|
||||
password3.setText(password.charAt(2) + "");
|
||||
} else {
|
||||
password3.setText("");
|
||||
if (password.length() == 2) {
|
||||
password2.setText(password.charAt(1) + "");
|
||||
} else {
|
||||
password2.setText("");
|
||||
if (password.length() == 1) {
|
||||
password1.setText(password.charAt(0) + "");
|
||||
} else {
|
||||
password1.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getNetUrl(){
|
||||
// Api.getInstance().geUrl(System.currentTimeMillis())
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(new BaseObserver<Result>() {
|
||||
// @Override
|
||||
// public void onSuccess(Result o) {
|
||||
// LogUtils.i("获取的文件地址:"+o.url);
|
||||
// if(!TextUtils.isEmpty(o.url)){
|
||||
// MainActivity.saveString(StartActivity.this,"base_url",o.url);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(int code, String msg) {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
Handler handler = new Handler();
|
||||
|
||||
private void toNext() {
|
||||
MainActivity.saveString(StartActivity.this, "loc_pass", password);
|
||||
Intent intent = new Intent(StartActivity.this, MainActivity2.class);
|
||||
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.btn_0:
|
||||
addInput("0", 0);
|
||||
break;
|
||||
case R.id.btn_1:
|
||||
addInput("1", 0);
|
||||
break;
|
||||
case R.id.btn_2:
|
||||
addInput("2", 0);
|
||||
break;
|
||||
case R.id.btn_3:
|
||||
addInput("3", 0);
|
||||
break;
|
||||
case R.id.btn_4:
|
||||
addInput("4", 0);
|
||||
break;
|
||||
case R.id.btn_5:
|
||||
addInput("5", 0);
|
||||
break;
|
||||
case R.id.btn_6:
|
||||
addInput("6", 0);
|
||||
break;
|
||||
case R.id.btn_7:
|
||||
addInput("7", 0);
|
||||
break;
|
||||
case R.id.btn_8:
|
||||
addInput("8", 0);
|
||||
break;
|
||||
case R.id.btn_9:
|
||||
addInput("9", 0);
|
||||
break;
|
||||
|
||||
case R.id.btn_equal:
|
||||
deleteInput();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteInput() {
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
addInput("", 2);
|
||||
} else {
|
||||
addInput(password, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
44
winwaynew/src/main/java/just/way/StatusLayout.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package just.way;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Created by kiun_2007 on 2018/3/29.
|
||||
*/
|
||||
|
||||
public class StatusLayout extends LinearLayout {
|
||||
public StatusLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public StatusLayout(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public StatusLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
private int getStatusBarHeight(Context context) {
|
||||
int result = 0;
|
||||
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = context.getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
ViewGroup.LayoutParams lp = this.getLayoutParams();
|
||||
lp.width = -1;
|
||||
lp.height = getStatusBarHeight(getContext());
|
||||
this.setLayoutParams(lp);
|
||||
super.onAttachedToWindow();
|
||||
}
|
||||
}
|
||||
16
winwaynew/src/main/java/just/way/Utils.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package just.way;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static boolean isImageUrl(String url) {
|
||||
String end = url.substring(url.lastIndexOf(".") + 1).toLowerCase();
|
||||
String[] images = new String[]{"jpeg", "png", "jpg", "bmp", "webp", "gif"};
|
||||
for (String name : images) {
|
||||
if (end.equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
340
winwaynew/src/main/java/just/way/WebView2Activity.java
Normal file
@@ -0,0 +1,340 @@
|
||||
package just.way;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.net.http.SslError;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.tencent.smtt.export.external.interfaces.ConsoleMessage;
|
||||
import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
|
||||
import com.tencent.smtt.sdk.ValueCallback;
|
||||
import com.tencent.smtt.sdk.WebChromeClient;
|
||||
import com.tencent.smtt.sdk.WebSettings;
|
||||
import com.tencent.smtt.sdk.WebView;
|
||||
import com.tencent.smtt.sdk.WebViewClient;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
|
||||
import just.way.appdown.AppUpdater;
|
||||
import just.way.appdown.UpdateConfig;
|
||||
import just.way.appdown.constant.Constants;
|
||||
import just.way.appdown.util.AppUtils;
|
||||
import just.way.appdown.util.NotificationUtils;
|
||||
|
||||
public class WebView2Activity extends AppCompatActivity {
|
||||
|
||||
private String url;
|
||||
WebView webView;
|
||||
ImageView show_top_v;
|
||||
ImageView menu_iv;
|
||||
private ImageView helpIv;
|
||||
private LinearLayout showTopLy;
|
||||
private FrameLayout videoContainer;
|
||||
private ImageView backIv;
|
||||
private ProgressBar progressBar;
|
||||
private View topVvvv;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
getWindow().setNavigationBarColor(getColor(R.color.white));
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
View decor = getWindow().getDecorView();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
setContentView(R.layout.activity_webview);
|
||||
findViewById(R.id.back_iv).setOnClickListener(view -> finish());
|
||||
url = getIntent().getStringExtra("url");
|
||||
initView();
|
||||
}
|
||||
|
||||
private ValueCallback<Uri[]> mUploadCallbackForHighApi;
|
||||
|
||||
public void initView() {
|
||||
topVvvv = (View) findViewById(R.id.top_vvvv);
|
||||
webView = findViewById(R.id.webview);
|
||||
show_top_v = findViewById(R.id.show_top_v);
|
||||
showTopLy = findViewById(R.id.show_top_ly);
|
||||
videoContainer = (FrameLayout) findViewById(R.id.videoContainer);
|
||||
backIv = (ImageView) findViewById(R.id.back_iv);
|
||||
progressBar = (ProgressBar) findViewById(R.id.progressbar);
|
||||
WebSettings settings = webView.getSettings();
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setAppCacheEnabled(true);
|
||||
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
// 设置允许访问文件数据
|
||||
settings.setAllowFileAccess(true);
|
||||
settings.setAllowContentAccess(true);
|
||||
settings.setDatabaseEnabled(true);
|
||||
settings.setSavePassword(false);
|
||||
settings.setSaveFormData(false);
|
||||
settings.setUseWideViewPort(true);
|
||||
settings.setBuiltInZoomControls(true);
|
||||
settings.setPluginState(WebSettings.PluginState.ON);
|
||||
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
webView.setFocusable(true);
|
||||
webView.setFocusableInTouchMode(true);
|
||||
webView.getSettings().setSupportMultipleWindows(true);
|
||||
|
||||
settings.setSupportZoom(false);
|
||||
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
|
||||
// webView.setHorizontalScrollbarOverlay(true);
|
||||
webView.setHorizontalScrollBarEnabled(true);
|
||||
webView.requestFocus();
|
||||
// webView.setBackgroundColor(getColor(R.color.black));
|
||||
settings.setJavaScriptCanOpenWindowsAutomatically(false);
|
||||
settings.setMediaPlaybackRequiresUserGesture(false);
|
||||
|
||||
// 设置在WebView内部是否允许通过file url加载的 Js代码读取其他的本地文件
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowFileAccessFromFileURLs(true);
|
||||
// 设置WebView内部是否允许通过 file url 加载的 Javascript 可以访问其他的源(包括http、https等源)
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowUniversalAccessFromFileURLs(true);
|
||||
|
||||
// settings.setBuiltInZoomControls(false); // 启用缩放功能
|
||||
// settings.setDisplayZoomControls(false); // 隐藏缩放控件
|
||||
|
||||
|
||||
webView.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
|
||||
|
||||
WebView newWebView = new WebView(WebView2Activity.this);
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
webView.addView(newWebView);
|
||||
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
transport.setWebView(newWebView);
|
||||
resultMsg.sendToTarget();
|
||||
|
||||
newWebView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// isAtGame = true;
|
||||
progressBar.setVisibility(View.GONE);
|
||||
webView.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// WebView newWebView = new WebView(view.getContext());
|
||||
// newWebView.setWebViewClient(new WebViewClient() {
|
||||
// @Override
|
||||
// public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// Intent browserIntent = new Intent(WebViewActivity.this, WebViewActivity.class);
|
||||
// browserIntent.putExtra("url", url);
|
||||
// startActivity(browserIntent);
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
// WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
// transport.setWebView(newWebView);
|
||||
// resultMsg.sendToTarget();
|
||||
// return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCloseWindow(WebView window) {
|
||||
super.onCloseWindow(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
|
||||
LogUtils.d("consolemessage==" + consoleMessage.message());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
}
|
||||
});
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
super.onPageStarted(view, url, favicon);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
|
||||
Uri uri;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
uri = request.getUrl();
|
||||
} else {
|
||||
uri = Uri.parse(request.toString());
|
||||
}
|
||||
String url1 = uri.toString();
|
||||
LogUtils.d("url1111111111==" + url1);
|
||||
if (url1.equals(url + "index") || url1.equals(url + "/index")) {
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((url1.equals(url + "index") || url1.equals(url + "/index")) && webView.canGoBack()) {
|
||||
return false;
|
||||
} else {
|
||||
if (url1.contains(".apk")) { //下载
|
||||
Toast.makeText(WebView2Activity.this, "下载开始,请稍后...", Toast.LENGTH_SHORT).show();
|
||||
Constants.isUpdate = false;
|
||||
new AppUpdater(WebView2Activity.this, url1).start();
|
||||
return false;
|
||||
}
|
||||
//其它的该怎么处理就怎么处理
|
||||
LogUtils.d("url1111111111==2" + url1);
|
||||
webView.loadUrl(url1);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url1) {
|
||||
if (url1.equals(url + "index") || url1.equals(url + "/index")) {
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((url1.equals(url + "index") || url1.equals(url + "/index")) && webView.canGoBack()) {
|
||||
return false;
|
||||
} else {
|
||||
if (url1.contains(".apk")) { //下载
|
||||
new AppUpdater(WebView2Activity.this, url1).start();
|
||||
return false;
|
||||
}
|
||||
//其它的该怎么处理就怎么处理
|
||||
webView.loadUrl(url1);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
// webView.setOnTouchListener(new View.OnTouchListener() {
|
||||
// @Override
|
||||
// public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
// if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
// webView.loadUrl("javascript:_IntervalResize(+\" + view + \",false)");
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// webView.onWindowFocusChanged(true);
|
||||
// webView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
// @Override
|
||||
// public void onFocusChange(View view, boolean b) {
|
||||
// LogUtils.d("B==" + b);
|
||||
// view.invalidate();
|
||||
// }
|
||||
// });
|
||||
if (url != null) {
|
||||
webView.loadUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (webView.canGoBack()) {//当webview有多级能返回的时候
|
||||
webView.goBack();
|
||||
} else {//不能返回了
|
||||
WebView2Activity.this.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (webView != null) {
|
||||
//加载null内容
|
||||
// webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
|
||||
//清除历史记录
|
||||
// webView.clearHistory();
|
||||
//移除WebView
|
||||
// ((ViewGroup) webView.getParent()).removeView(webView);
|
||||
//销毁VebView
|
||||
webView.destroy();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
392
winwaynew/src/main/java/just/way/WebViewActivity.java
Normal file
@@ -0,0 +1,392 @@
|
||||
package just.way;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.tencent.smtt.export.external.interfaces.WebResourceError;
|
||||
import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
|
||||
import com.tencent.smtt.sdk.ValueCallback;
|
||||
import com.tencent.smtt.sdk.WebChromeClient;
|
||||
import com.tencent.smtt.sdk.WebSettings;
|
||||
import com.tencent.smtt.sdk.WebView;
|
||||
import com.tencent.smtt.sdk.WebViewClient;
|
||||
|
||||
import just.way.appdown.AppUpdater;
|
||||
import just.way.appdown.constant.Constants;
|
||||
|
||||
public class WebViewActivity extends AppCompatActivity {
|
||||
|
||||
private String url;
|
||||
WebView webView;
|
||||
TextView tvErrorMsg;
|
||||
LinearLayout layoutError;
|
||||
ImageView show_top_v;
|
||||
ImageView menu_iv;
|
||||
private ImageView helpIv;
|
||||
private LinearLayout showTopLy;
|
||||
private FrameLayout videoContainer;
|
||||
private ImageView backIv;
|
||||
private ProgressBar progressBar;
|
||||
private View topVvvv;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
getWindow().setNavigationBarColor(getColor(R.color.white));
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
View decor = getWindow().getDecorView();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
setContentView(R.layout.activity_main22);
|
||||
findViewById(R.id.back_iv).setOnClickListener(view -> finish());
|
||||
url = getIntent().getStringExtra("url");
|
||||
initView();
|
||||
}
|
||||
|
||||
private ValueCallback<Uri[]> mUploadCallbackForHighApi;
|
||||
|
||||
public void initView() {
|
||||
topVvvv = (View) findViewById(R.id.top_vvvv);
|
||||
webView = findViewById(R.id.webview);
|
||||
show_top_v = findViewById(R.id.show_top_v);
|
||||
showTopLy = findViewById(R.id.show_top_ly);
|
||||
tvErrorMsg = findViewById(R.id.errormsg);
|
||||
layoutError = findViewById(R.id.layoutError);
|
||||
videoContainer = (FrameLayout) findViewById(R.id.videoContainer);
|
||||
backIv = (ImageView) findViewById(R.id.back_iv);
|
||||
progressBar = (ProgressBar) findViewById(R.id.progressbar);
|
||||
WebSettings settings = webView.getSettings();
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setAppCacheEnabled(true);
|
||||
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
// 设置允许访问文件数据
|
||||
settings.setAllowFileAccess(true);
|
||||
settings.setAllowContentAccess(true);
|
||||
settings.setDatabaseEnabled(true);
|
||||
settings.setSavePassword(false);
|
||||
settings.setSaveFormData(false);
|
||||
settings.setUseWideViewPort(true);
|
||||
settings.setBuiltInZoomControls(true);
|
||||
settings.setPluginState(WebSettings.PluginState.ON);
|
||||
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
webView.setFocusable(true);
|
||||
webView.setFocusableInTouchMode(true);
|
||||
webView.getSettings().setSupportMultipleWindows(true);
|
||||
|
||||
settings.setSupportZoom(false);
|
||||
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
|
||||
// webView.setHorizontalScrollbarOverlay(true);
|
||||
webView.setHorizontalScrollBarEnabled(true);
|
||||
webView.requestFocus();
|
||||
// webView.setBackgroundColor(getColor(R.color.black));
|
||||
settings.setJavaScriptCanOpenWindowsAutomatically(false);
|
||||
|
||||
// 设置在WebView内部是否允许通过file url加载的 Js代码读取其他的本地文件
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowFileAccessFromFileURLs(true);
|
||||
// 设置WebView内部是否允许通过 file url 加载的 Javascript 可以访问其他的源(包括http、https等源)
|
||||
// Android 4.1前默认允许,4.1后默认禁止
|
||||
settings.setAllowUniversalAccessFromFileURLs(true);
|
||||
|
||||
// settings.setBuiltInZoomControls(false); // 启用缩放功能
|
||||
// settings.setDisplayZoomControls(false); // 隐藏缩放控件
|
||||
|
||||
|
||||
webView.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
|
||||
|
||||
WebView newWebView = new WebView(WebViewActivity.this);
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
webView.addView(newWebView);
|
||||
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
transport.setWebView(newWebView);
|
||||
resultMsg.sendToTarget();
|
||||
|
||||
newWebView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// isAtGame = true;
|
||||
progressBar.setVisibility(View.GONE);
|
||||
webView.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// WebView newWebView = new WebView(view.getContext());
|
||||
// newWebView.setWebViewClient(new WebViewClient() {
|
||||
// @Override
|
||||
// public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// Intent browserIntent = new Intent(WebViewActivity.this, WebViewActivity.class);
|
||||
// browserIntent.putExtra("url", url);
|
||||
// startActivity(browserIntent);
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
// WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
||||
// transport.setWebView(newWebView);
|
||||
// resultMsg.sendToTarget();
|
||||
// return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
super.onPageStarted(view, url, favicon);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
super.onReceivedError(view, request, error);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
int errorCode = error.getErrorCode();
|
||||
String errorMessage = error.getDescription().toString();
|
||||
String currentUrl = request.getUrl().toString();
|
||||
LogUtils.d("onReceivedError2 url==" + url + " errorCode ==" + errorCode);
|
||||
if ((errorCode == -2 || errorCode == -6) && currentUrl.contains(url)) {
|
||||
onShowErrorView(errorMessage);
|
||||
} else {
|
||||
onShowNetView();
|
||||
}
|
||||
}
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
LogUtils.d("onReceivedError2 url==" + failingUrl + " errorCode ==" + errorCode);
|
||||
if ((errorCode == -2 || errorCode == -6) && failingUrl.contains(url)) {
|
||||
onShowErrorView(description);
|
||||
} else {
|
||||
onShowNetView();
|
||||
}
|
||||
}
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
|
||||
Uri uri;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
uri = request.getUrl();
|
||||
} else {
|
||||
uri = Uri.parse(request.toString());
|
||||
}
|
||||
String url1 = uri.toString();
|
||||
LogUtils.d("url1111111111==" + url1);
|
||||
if (url1.equals(url + "index") || url1.equals(url + "/index")) {
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((url1.equals(url + "index") || url1.equals(url + "/index")) && webView.canGoBack()) {
|
||||
return false;
|
||||
} else {
|
||||
if (url1.contains(".apk")) { //下载
|
||||
Toast.makeText(WebViewActivity.this, "下载开始,请稍后...", Toast.LENGTH_SHORT).show();
|
||||
Constants.isUpdate = false;
|
||||
new AppUpdater(WebViewActivity.this, url1).start();
|
||||
return false;
|
||||
}
|
||||
//其它的该怎么处理就怎么处理
|
||||
LogUtils.d("url1111111111==2" + url1);
|
||||
webView.loadUrl(url1);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url1) {
|
||||
if (url1.equals(url + "index") || url1.equals(url + "/index")) {
|
||||
topVvvv.setVisibility(View.GONE);
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!(url1.startsWith("http") || url1.startsWith("https"))) {
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url1));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((url1.equals(url + "index") || url1.equals(url + "/index")) && webView.canGoBack()) {
|
||||
return false;
|
||||
} else {
|
||||
if (url1.contains(".apk")) { //下载
|
||||
new AppUpdater(WebViewActivity.this, url1).start();
|
||||
return false;
|
||||
}
|
||||
//其它的该怎么处理就怎么处理
|
||||
webView.loadUrl(url1);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
webView.setOnGenericMotionListener(new View.OnGenericMotionListener() {
|
||||
@Override
|
||||
public boolean onGenericMotion(View view, MotionEvent motionEvent) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// webView.setOnTouchListener(new View.OnTouchListener() {
|
||||
// @Override
|
||||
// public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
// if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
// webView.loadUrl("javascript:_IntervalResize(+\" + view + \",false)");
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// webView.onWindowFocusChanged(true);
|
||||
// webView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
// @Override
|
||||
// public void onFocusChange(View view, boolean b) {
|
||||
// LogUtils.d("B==" + b);
|
||||
// view.invalidate();
|
||||
// }
|
||||
// });
|
||||
if (url != null) {
|
||||
webView.loadUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNetError = false;
|
||||
|
||||
public void onShowErrorView(String errorMsg) { //网络不可用的情况
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
webView.setVisibility(View.GONE);
|
||||
layoutError.setVisibility(View.VISIBLE);
|
||||
tvErrorMsg.setText(errorMsg);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
isNetError = true;
|
||||
|
||||
}
|
||||
|
||||
public void onShowNetView() {
|
||||
topVvvv.setVisibility(View.VISIBLE);
|
||||
webView.setVisibility(View.VISIBLE);
|
||||
layoutError.setVisibility(View.GONE);
|
||||
showTopLy.setVisibility(View.GONE);
|
||||
isNetError = false;
|
||||
}
|
||||
|
||||
public static String getString(Context context, String key, String defValue) {
|
||||
if (context == null) {
|
||||
return defValue;
|
||||
}
|
||||
SharedPreferences sp = context.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
|
||||
return sp.getString(key, defValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (webView.canGoBack()) {//当webview有多级能返回的时候
|
||||
String url = webView.getUrl();
|
||||
String baseUrl = getString(WebViewActivity.this, "base_url", url);
|
||||
if (baseUrl.equals(url + "index") || baseUrl.equals(url + "/index")) {
|
||||
WebViewActivity.this.finish();
|
||||
}
|
||||
onShowNetView();
|
||||
webView.goBack();
|
||||
} else {//不能返回了
|
||||
WebViewActivity.this.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (webView != null) {
|
||||
//加载null内容
|
||||
// webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
|
||||
//清除历史记录
|
||||
// webView.clearHistory();
|
||||
//移除WebView
|
||||
// ((ViewGroup) webView.getParent()).removeView(webView);
|
||||
//销毁VebView
|
||||
webView.destroy();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
384
winwaynew/src/main/java/just/way/appdown/AppUpdater.java
Normal file
@@ -0,0 +1,384 @@
|
||||
package just.way.appdown;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import just.way.appdown.callback.UpdateCallback;
|
||||
import just.way.appdown.constant.Constants;
|
||||
import just.way.appdown.http.HttpManager;
|
||||
import just.way.appdown.http.IHttpManager;
|
||||
import just.way.appdown.http.OkHttpManager;
|
||||
import just.way.appdown.service.DownloadService;
|
||||
import just.way.appdown.util.PermissionUtils;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class AppUpdater {
|
||||
/**
|
||||
* {@link #mContext}不强制要求是{@link Activity},但能传{@link Activity}尽量传。AppUpdater本应该只专注于App更新,尽量不涉及动态权限相关的处理。如果mContext传的是{@link Activity},则默认会校验一次动态权限。
|
||||
*/
|
||||
private Context mContext;
|
||||
/**
|
||||
* 配置信息
|
||||
*/
|
||||
private UpdateConfig mConfig;
|
||||
/**
|
||||
* 更新回调
|
||||
*/
|
||||
private UpdateCallback mCallback;
|
||||
/**
|
||||
* http管理接口,可自定义实现。如:使用okHttp
|
||||
*/
|
||||
private IHttpManager mHttpManager;
|
||||
|
||||
private ServiceConnection mServiceConnection;
|
||||
|
||||
public AppUpdater(@NonNull Context context,@NonNull UpdateConfig config){
|
||||
this.mContext = context;
|
||||
this.mConfig = config;
|
||||
}
|
||||
|
||||
public AppUpdater(@NonNull Context context,@NonNull String url){
|
||||
this.mContext = context;
|
||||
mConfig = new UpdateConfig();
|
||||
mConfig.setUrl(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载更新进度回调
|
||||
* @param callback
|
||||
* @return
|
||||
*/
|
||||
public AppUpdater setUpdateCallback(UpdateCallback callback){
|
||||
this.mCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置一个IHttpManager
|
||||
* @param httpManager AppUpdater内置提供{@link HttpManager} 和 {@link OkHttpManager}两种实现。
|
||||
* 如果不设置,将默认使用{@link HttpManager},你也可以使用{@link OkHttpManager}或自己去实现一个
|
||||
* {@link IHttpManager}。
|
||||
* 当使用{@link OkHttpManager}时,必需依赖okhttp库
|
||||
* @return
|
||||
*/
|
||||
public AppUpdater setHttpManager(IHttpManager httpManager){
|
||||
this.mHttpManager = httpManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
*/
|
||||
public void start(){
|
||||
if(mConfig != null && !TextUtils.isEmpty(mConfig.getUrl())){
|
||||
//如果mContext是Activity,并且配置了下载路径,则默认会校验一次动态权限。
|
||||
if(mContext instanceof Activity && !TextUtils.isEmpty(mConfig.getPath())){
|
||||
PermissionUtils.verifyReadAndWritePermissions((Activity) mContext,Constants.RE_CODE_STORAGE_PERMISSION);
|
||||
}
|
||||
|
||||
if(mConfig.isShowNotification() && !PermissionUtils.isNotificationEnabled(mContext)){
|
||||
Log.w(Constants.TAG,"Notification permission not enabled.");
|
||||
}
|
||||
|
||||
startDownloadService();
|
||||
}else{
|
||||
throw new NullPointerException("Url must not be empty.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动下载服务
|
||||
*/
|
||||
private void startDownloadService(){
|
||||
Intent intent = new Intent(mContext, DownloadService.class);
|
||||
if(mCallback!=null || mHttpManager!=null){//bindService
|
||||
mServiceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
DownloadService.DownloadBinder binder = ((DownloadService.DownloadBinder)service);
|
||||
binder.start(mConfig,mHttpManager,mCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
mContext.getApplicationContext().bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
}else{//startService
|
||||
intent.putExtra(Constants.KEY_UPDATE_CONFIG,mConfig);
|
||||
mContext.startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
public void stop(){
|
||||
stopDownloadService();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止下载服务
|
||||
*/
|
||||
private void stopDownloadService(){
|
||||
Intent intent = new Intent(mContext, DownloadService.class);
|
||||
intent.putExtra(Constants.KEY_STOP_DOWNLOAD_SERVICE,true);
|
||||
mContext.startService(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* AppUpdater建造者
|
||||
*/
|
||||
public static class Builder{
|
||||
|
||||
|
||||
private UpdateConfig mConfig;
|
||||
|
||||
public Builder(){
|
||||
mConfig = new UpdateConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置APK下载地址
|
||||
* @param url 下载地址
|
||||
* @return
|
||||
*/
|
||||
public Builder setUrl(@NonNull String url){
|
||||
mConfig.setUrl(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保存的路径,(建议使用默认,不做设置)
|
||||
* @param path 下载保存的文件路径
|
||||
* @return
|
||||
* @deprecated 因为适配Android Q的分区存储,所以此方法已弃用,不建议再使用
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder setPath(String path){
|
||||
mConfig.setPath(path);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保存的文件名
|
||||
* @param filename 下载的保存的apk文件名 (默认优先取url文件名)
|
||||
* @return
|
||||
*/
|
||||
public Builder setFilename(String filename){
|
||||
mConfig.setFilename(filename);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否显示通知栏
|
||||
* @param isShowNotification 是否显示通知栏 (默认true)
|
||||
* @return
|
||||
*/
|
||||
public Builder setShowNotification(boolean isShowNotification) {
|
||||
mConfig.setShowNotification(isShowNotification);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知ID
|
||||
* @param notificationId 通知ID
|
||||
* @return
|
||||
*/
|
||||
public Builder setNotificationId(int notificationId) {
|
||||
mConfig.setNotificationId(notificationId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知渠道ID
|
||||
* @param channelId 通知渠道ID (默认兼容O)
|
||||
* @return
|
||||
*/
|
||||
public Builder setChannelId(String channelId) {
|
||||
mConfig.setChannelId(channelId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知渠道名称
|
||||
* @param channelName 通知渠道名称 (默认兼容O)
|
||||
* @return
|
||||
*/
|
||||
public Builder setChannelName(String channelName) {
|
||||
mConfig.setChannelName(channelName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知图标
|
||||
* @param icon 通知栏图标 (默认取App的icon)
|
||||
* @return
|
||||
*/
|
||||
public Builder setNotificationIcon(@DrawableRes int icon) {
|
||||
mConfig.setNotificationIcon(icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知是否震动提示
|
||||
* @param vibrate 是否震动提示,为true时使用通知默认震动,Android O(8.0)以上设置,只有初次创建channel时有效,后续修改属性无效,想要重新有效需修改channelId或卸载App重装。
|
||||
* @return
|
||||
*/
|
||||
public Builder setVibrate(boolean vibrate) {
|
||||
mConfig.setVibrate(vibrate);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知是否铃声提示
|
||||
* @param sound 是否铃声提示,为true时使用通知默认铃声,Android O(8.0)以上设置,只有初次创建channel时有效,后续修改属性无效,想要重新有效需修改channelId或卸载App重装。
|
||||
* @return
|
||||
*/
|
||||
public Builder setSound(boolean sound) {
|
||||
mConfig.setSound(sound);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置下载完成后知否自动触发安装APK
|
||||
* @param isInstallApk 下载完成后是否自动调用安装APK(默认true)
|
||||
* @return
|
||||
*/
|
||||
public Builder setInstallApk(boolean isInstallApk){
|
||||
mConfig.setInstallApk(isInstallApk);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置FileProvider的authority
|
||||
* @param authority FileProvider的authority(默认兼容N,默认值{@link Context#getPackageName() + ".AppUpdaterFileProvider"})
|
||||
* @return
|
||||
*/
|
||||
public Builder setAuthority(String authority){
|
||||
mConfig.setAuthority(authority);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载时,通知栏是否显示下载百分比
|
||||
* @param showPercentage 下载时通知栏是否显示百分比
|
||||
* @return
|
||||
*/
|
||||
public Builder setShowPercentage(boolean showPercentage) {
|
||||
mConfig.setShowPercentage(showPercentage);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载失败时,是否支持点击通知栏重新下载。与之相关联的方法{@link #setReDownloads(int)}
|
||||
* @param reDownload 下载失败时是否支持点击通知栏重新下载,默认true
|
||||
* @return
|
||||
*/
|
||||
public Builder setReDownload(boolean reDownload) {
|
||||
mConfig.setReDownload(reDownload);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载失败时,最多重新下载次数。与之相关联的方法{@link #setReDownload(boolean)}
|
||||
* @param reDownloads 下载失败时是否支持点击通知栏重新下载,默认最多重新下载3次
|
||||
* @return
|
||||
*/
|
||||
public Builder setReDownloads(int reDownloads) {
|
||||
mConfig.setReDownloads(reDownloads);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置要下载APK的versionCode,用于优先取缓存时通过versionCode校验APK文件是否一致。
|
||||
* 缓存校验目前支持两种方式,一种是通过versionCode校验,即{@link #setVersionCode(Integer)};一种是文件MD5校验,即{@link #setApkMD5(String)}。推荐使用MD5校验方式
|
||||
* 如果两种方式都设置了,则只校验MD5
|
||||
* @param versionCode 为null表示不处理,默认不存在则下载,存在则重新下载。不为null时,表示会优先校验本地是否存在已下载版本号为versionCode的APK。
|
||||
* 如果存在则不会重新下载(AppUpdater会自动校验packageName一致性),直接取本地APK,反之重新下载。
|
||||
* @return
|
||||
*/
|
||||
public Builder setVersionCode(Integer versionCode) {
|
||||
mConfig.setVersionCode(versionCode);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置APK文件的MD5,用于优先取缓存时通过MD5校验文件APK是否一致。
|
||||
* 缓存校验目前支持两种方式,一种是通过versionCode校验,即{@link #setVersionCode(Integer)};一种是文件MD5校验,即{@link #setApkMD5(String)}。推荐使用MD5校验方式
|
||||
* 如果两种方式都设置了,则只校验MD5
|
||||
* @param md5 为null表示不处理,如果设置了MD5,则缓存APK的MD5相同时,只下载一次,优先取本地缓存
|
||||
* @return
|
||||
*/
|
||||
public Builder setApkMD5(String md5) {
|
||||
mConfig.setApkMD5(md5);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* 请求头添加参数
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public Builder addHeader(String key, String value){
|
||||
mConfig.addHeader(key,value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求头添加参数
|
||||
* @param headers
|
||||
* @return
|
||||
*/
|
||||
public Builder addHeader(Map<String,String> headers){
|
||||
mConfig.addHeader(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否自动删除取消下载的文件
|
||||
* @param deleteCancelFile 是否删除取消下载的文件(默认为true)
|
||||
*/
|
||||
public Builder setDeleteCancelFile(boolean deleteCancelFile){
|
||||
mConfig.setDeleteCancelFile(deleteCancelFile);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持通过删除通知栏来取消下载(默认为:false)
|
||||
* @param cancelDownload
|
||||
* @return
|
||||
*/
|
||||
public Builder setCancelDownload(boolean cancelDownload){
|
||||
mConfig.setCancelDownload(cancelDownload);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public AppUpdater build(@NonNull Context context){
|
||||
return new AppUpdater(context,mConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
460
winwaynew/src/main/java/just/way/appdown/UpdateConfig.java
Normal file
@@ -0,0 +1,460 @@
|
||||
package just.way.appdown;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import just.way.appdown.constant.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class UpdateConfig implements Parcelable {
|
||||
|
||||
/**
|
||||
* APK下载的Url
|
||||
*/
|
||||
private String mUrl;
|
||||
/**
|
||||
* 保存路径
|
||||
*/
|
||||
private String mPath;
|
||||
/**
|
||||
* 保存文件名
|
||||
*/
|
||||
private String mFilename;
|
||||
|
||||
/**
|
||||
* 是否显示通知栏
|
||||
*/
|
||||
private boolean isShowNotification = true;
|
||||
/**
|
||||
* 下载完成后是否自动弹出安装
|
||||
*/
|
||||
private boolean isInstallApk = true;
|
||||
/**
|
||||
* 通知栏图标:默认取app图标
|
||||
*/
|
||||
private int mNotificationIcon;
|
||||
|
||||
/**
|
||||
* 通知栏ID
|
||||
*/
|
||||
private int mNotificationId = Constants.DEFAULT_NOTIFICATION_ID;
|
||||
|
||||
/**
|
||||
* 通知栏渠道ID
|
||||
*/
|
||||
private String mChannelId;
|
||||
/**
|
||||
* 通知栏渠道名称
|
||||
*/
|
||||
private String mChannelName;
|
||||
/**
|
||||
* 默认{@link Context#getPackageName() + ".AppUpdaterFileProvider"}
|
||||
*/
|
||||
private String mAuthority;
|
||||
/**
|
||||
* 下载失败是否支持点击通知栏重新下载
|
||||
*/
|
||||
private boolean isReDownload = true;
|
||||
/**
|
||||
* 下载失败后,最大重新下载次数
|
||||
*/
|
||||
private int reDownloads = 3;
|
||||
/**
|
||||
* 是否显示百分比
|
||||
*/
|
||||
private boolean isShowPercentage = true;
|
||||
|
||||
/**
|
||||
* 是否震动提示,为true时使用通知默认震动
|
||||
*/
|
||||
private boolean isVibrate;
|
||||
|
||||
/**
|
||||
* 是否铃声提示,为true时使用通知默认铃声
|
||||
*/
|
||||
private boolean isSound;
|
||||
|
||||
/**
|
||||
* 要下载的APK的versionCode
|
||||
*/
|
||||
private Integer versionCode;
|
||||
|
||||
/**
|
||||
* 请求头参数
|
||||
*/
|
||||
private Map<String,String> mRequestProperty;
|
||||
|
||||
/**
|
||||
* 是否删除取消下载的文件
|
||||
*/
|
||||
private boolean isDeleteCancelFile = true;
|
||||
|
||||
/**
|
||||
* 是否支持通过删除通知栏来取消下载
|
||||
*/
|
||||
private boolean isCancelDownload = false;
|
||||
|
||||
/**
|
||||
* APK文件的MD5
|
||||
*/
|
||||
private String apkMD5;
|
||||
|
||||
|
||||
public UpdateConfig() {
|
||||
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置APK下载地址
|
||||
* @param url 下载地址
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.mUrl = url;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保存的路径,(建议使用默认,不做设置)
|
||||
* @param path 下载保存的文件路径
|
||||
* @return
|
||||
* @deprecated 因为适配Android Q的分区存储,所以此方法已弃用,不建议再使用
|
||||
*/
|
||||
@Deprecated
|
||||
public void setPath(String path) {
|
||||
this.mPath = path;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return mFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保存的文件名
|
||||
* @param filename 下载的保存的apk文件名 (默认优先取url文件名)
|
||||
*/
|
||||
public void setFilename(String filename) {
|
||||
this.mFilename = filename;
|
||||
}
|
||||
|
||||
public boolean isShowNotification() {
|
||||
return isShowNotification;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否显示通知栏
|
||||
* @param isShowNotification 是否显示通知栏 (默认true)
|
||||
*/
|
||||
public void setShowNotification(boolean isShowNotification) {
|
||||
this.isShowNotification = isShowNotification;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return mChannelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知渠道ID
|
||||
* @param channelId 通知渠道ID (默认兼容O)
|
||||
*/
|
||||
public void setChannelId(String channelId) {
|
||||
this.mChannelId = channelId;
|
||||
}
|
||||
|
||||
public String getChannelName() {
|
||||
return mChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知渠道名称
|
||||
* @param channelName 通知渠道名称 (默认兼容O)
|
||||
*/
|
||||
public void setChannelName(String channelName) {
|
||||
this.mChannelName = channelName;
|
||||
}
|
||||
/**
|
||||
* 设置通知ID
|
||||
* @param notificationId 通知ID
|
||||
*/
|
||||
public void setNotificationId(int notificationId){
|
||||
this.mNotificationId = notificationId;
|
||||
}
|
||||
|
||||
public int getNotificationId(){
|
||||
return this.mNotificationId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置通知图标
|
||||
* @param icon 通知栏图标 (默认取App的icon)
|
||||
*/
|
||||
public void setNotificationIcon(@DrawableRes int icon){
|
||||
this.mNotificationIcon = icon;
|
||||
}
|
||||
|
||||
public int getNotificationIcon(){
|
||||
return this.mNotificationIcon;
|
||||
}
|
||||
|
||||
public boolean isInstallApk() {
|
||||
return isInstallApk;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载完成后知否自动触发安装APK
|
||||
* @param isInstallApk 下载完成后是否自动调用安装APK(默认true)
|
||||
*/
|
||||
public void setInstallApk(boolean isInstallApk) {
|
||||
this.isInstallApk = isInstallApk;
|
||||
}
|
||||
|
||||
public String getAuthority() {
|
||||
return mAuthority;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置FileProvider的authority
|
||||
* @param authority FileProvider的authority(默认兼容N,默认值{@link Context#getPackageName() + ".AppUpdaterFileProvider"})
|
||||
*/
|
||||
public void setAuthority(String authority) {
|
||||
this.mAuthority = authority;
|
||||
}
|
||||
|
||||
public boolean isShowPercentage() {
|
||||
return isShowPercentage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载时,通知栏是否显示下载百分比
|
||||
* @param showPercentage 下载时通知栏是否显示百分比
|
||||
*/
|
||||
public void setShowPercentage(boolean showPercentage) {
|
||||
isShowPercentage = showPercentage;
|
||||
}
|
||||
|
||||
public boolean isReDownload() {
|
||||
return isReDownload;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载失败时,是否支持点击通知栏重新下载。与之相关联的方法{@link #setReDownloads(int)}
|
||||
* @param reDownload 下载失败时是否支持点击通知栏重新下载,默认true
|
||||
*/
|
||||
public void setReDownload(boolean reDownload) {
|
||||
isReDownload = reDownload;
|
||||
}
|
||||
|
||||
public int getReDownloads() {
|
||||
return reDownloads;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载失败时,最多重新下载次数。与之相关联的方法{@link #setReDownload(boolean)}
|
||||
* @param reDownloads 下载失败时是否支持点击通知栏重新下载,默认最多重新下载3次
|
||||
*/
|
||||
public void setReDownloads(int reDownloads) {
|
||||
this.reDownloads = reDownloads;
|
||||
}
|
||||
|
||||
public boolean isVibrate() {
|
||||
return isVibrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知是否震动提示
|
||||
* @param vibrate 是否震动提示,为true时使用通知默认震动,Android O(8.0)以上设置,只有初次创建channel时有效,后续修改属性无效,想要重新有效需修改channelId或卸载App重装。
|
||||
*/
|
||||
public void setVibrate(boolean vibrate) {
|
||||
isVibrate = vibrate;
|
||||
}
|
||||
|
||||
public boolean isSound() {
|
||||
return isSound;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通知是否铃声提示
|
||||
* @param sound 是否铃声提示,为true时使用通知默认铃声,Android O(8.0)以上设置,只有初次创建channel时有效,后续修改属性无效,想要重新有效需修改channelId或卸载App重装。
|
||||
*/
|
||||
public void setSound(boolean sound) {
|
||||
isSound = sound;
|
||||
}
|
||||
|
||||
public Integer getVersionCode(){
|
||||
return versionCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置要下载APK的versionCode,用于优先取缓存时通过versionCode校验APK文件是否一致。
|
||||
* 缓存校验目前支持两种方式,一种是通过versionCode校验,即{@link #setVersionCode(Integer)};一种是文件MD5校验,即{@link #setApkMD5(String)}。推荐使用MD5校验方式
|
||||
* 如果两种方式都设置了,则只校验MD5
|
||||
* @param versionCode 为null表示不处理,默认不存在则下载,存在则重新下载。不为null时,表示会优先校验本地是否存在已下载版本号为versionCode的APK。
|
||||
* 如果存在则不会重新下载(AppUpdater会自动校验packageName一致性),直接取本地APK,反之重新下载。
|
||||
*/
|
||||
public void setVersionCode(Integer versionCode){
|
||||
this.versionCode = versionCode;
|
||||
}
|
||||
|
||||
public Map<String, String> getRequestProperty() {
|
||||
return mRequestProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置APK文件的MD5,用于优先取缓存时通过MD5校验文件APK是否一致。
|
||||
* 缓存校验目前支持两种方式,一种是通过versionCode校验,即{@link #setVersionCode(Integer)};一种是文件MD5校验,即{@link #setApkMD5(String)}。推荐使用MD5校验方式
|
||||
* 如果两种方式都设置了,则只校验MD5
|
||||
* @param md5 为null表示不处理,如果设置了MD5,则缓存APK的MD5相同时,只下载一次,优先取本地缓存
|
||||
*/
|
||||
public void setApkMD5(String md5){
|
||||
this.apkMD5 = md5;
|
||||
}
|
||||
|
||||
public String getApkMD5(){
|
||||
return apkMD5;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求头添加参数
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void addHeader(String key, String value){
|
||||
initRequestProperty();
|
||||
mRequestProperty.put(key,value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求头添加参数
|
||||
* @param headers
|
||||
*/
|
||||
public void addHeader(Map<String,String> headers){
|
||||
initRequestProperty();
|
||||
mRequestProperty.putAll(headers);
|
||||
}
|
||||
|
||||
private void initRequestProperty(){
|
||||
if(mRequestProperty == null){
|
||||
mRequestProperty = new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDeleteCancelFile() {
|
||||
return isDeleteCancelFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否自动删除取消下载的文件
|
||||
* @param deleteCancelFile 是否删除取消下载的文件(默认为:true)
|
||||
*/
|
||||
public void setDeleteCancelFile(boolean deleteCancelFile) {
|
||||
isDeleteCancelFile = deleteCancelFile;
|
||||
}
|
||||
|
||||
public boolean isCancelDownload(){
|
||||
return isCancelDownload;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持通过删除通知栏来取消下载(默认为:false)
|
||||
* @param cancelDownload
|
||||
*/
|
||||
public void setCancelDownload(boolean cancelDownload) {
|
||||
isCancelDownload = cancelDownload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.mUrl);
|
||||
dest.writeString(this.mPath);
|
||||
dest.writeString(this.mFilename);
|
||||
dest.writeByte(this.isShowNotification ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(this.isInstallApk ? (byte) 1 : (byte) 0);
|
||||
dest.writeInt(this.mNotificationIcon);
|
||||
dest.writeInt(this.mNotificationId);
|
||||
dest.writeString(this.mChannelId);
|
||||
dest.writeString(this.mChannelName);
|
||||
dest.writeString(this.mAuthority);
|
||||
dest.writeByte(this.isReDownload ? (byte) 1 : (byte) 0);
|
||||
dest.writeInt(this.reDownloads);
|
||||
dest.writeByte(this.isShowPercentage ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(this.isVibrate ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(this.isSound ? (byte) 1 : (byte) 0);
|
||||
dest.writeValue(this.versionCode);
|
||||
if(mRequestProperty!=null){
|
||||
dest.writeInt(this.mRequestProperty.size());
|
||||
for (Map.Entry<String, String> entry : this.mRequestProperty.entrySet()) {
|
||||
dest.writeString(entry.getKey());
|
||||
dest.writeString(entry.getValue());
|
||||
}
|
||||
}else{
|
||||
dest.writeInt(0);
|
||||
}
|
||||
|
||||
dest.writeByte(this.isDeleteCancelFile ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(this.isCancelDownload ? (byte) 1 : (byte) 0);
|
||||
dest.writeString(this.apkMD5);
|
||||
}
|
||||
|
||||
protected UpdateConfig(Parcel in) {
|
||||
this.mUrl = in.readString();
|
||||
this.mPath = in.readString();
|
||||
this.mFilename = in.readString();
|
||||
this.isShowNotification = in.readByte() != 0;
|
||||
this.isInstallApk = in.readByte() != 0;
|
||||
this.mNotificationIcon = in.readInt();
|
||||
this.mNotificationId = in.readInt();
|
||||
this.mChannelId = in.readString();
|
||||
this.mChannelName = in.readString();
|
||||
this.mAuthority = in.readString();
|
||||
this.isReDownload = in.readByte() != 0;
|
||||
this.reDownloads = in.readInt();
|
||||
this.isShowPercentage = in.readByte() != 0;
|
||||
this.isVibrate = in.readByte() != 0;
|
||||
this.isSound = in.readByte() != 0;
|
||||
this.versionCode = (Integer) in.readValue(Integer.class.getClassLoader());
|
||||
int mRequestPropertySize = in.readInt();
|
||||
this.mRequestProperty = new HashMap<>(mRequestPropertySize);
|
||||
for (int i = 0; i < mRequestPropertySize; i++) {
|
||||
String key = in.readString();
|
||||
String value = in.readString();
|
||||
this.mRequestProperty.put(key, value);
|
||||
}
|
||||
this.isDeleteCancelFile = in.readByte() != 0;
|
||||
this.isCancelDownload = in.readByte() != 0;
|
||||
this.apkMD5 = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator<UpdateConfig> CREATOR = new Creator<UpdateConfig>() {
|
||||
@Override
|
||||
public UpdateConfig createFromParcel(Parcel source) {
|
||||
return new UpdateConfig(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateConfig[] newArray(int size) {
|
||||
return new UpdateConfig[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package just.way.appdown.callback;
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public abstract class AppUpdateCallback implements UpdateCallback {
|
||||
@Override
|
||||
public void onDownloading(boolean isDownloading) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(String url) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package just.way.appdown.callback;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface UpdateCallback {
|
||||
|
||||
/**
|
||||
* 最开始调用(在onStart之前调用)
|
||||
* @param isDownloading true 表示已经在下载,false表示当前未开始下载,即将开始下载
|
||||
*/
|
||||
void onDownloading(boolean isDownloading);
|
||||
|
||||
/**
|
||||
* 开始
|
||||
*/
|
||||
void onStart(String url);
|
||||
|
||||
/**
|
||||
* 加载进度…
|
||||
* @param progress
|
||||
* @param total
|
||||
* @param isChange 进度百分比是否有改变,(主要可以用来过滤无用的刷新,从而降低刷新频率)
|
||||
*/
|
||||
void onProgress(long progress,long total,boolean isChange);
|
||||
|
||||
/**
|
||||
* 完成
|
||||
* @param file
|
||||
*/
|
||||
void onFinish(File file);
|
||||
|
||||
/**
|
||||
* 错误
|
||||
* @param e
|
||||
*/
|
||||
void onError(Exception e);
|
||||
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
void onCancel();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package just.way.appdown.constant;
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
public static final String TAG = "AppUpdater";
|
||||
|
||||
public static final String KEY_UPDATE_CONFIG = "app_update_config";
|
||||
|
||||
public static final int DEFAULT_NOTIFICATION_ID = 0x66;
|
||||
|
||||
public static final String DEFAULT_NOTIFICATION_CHANNEL_ID = "0x66";
|
||||
|
||||
public static final String DEFAULT_NOTIFICATION_CHANNEL_NAME = "AppUpdater";
|
||||
|
||||
public static final String KEY_STOP_DOWNLOAD_SERVICE = "stop_download_service";
|
||||
|
||||
public static final String KEY_RE_DOWNLOAD = "app_update_re_download";
|
||||
|
||||
public static final int RE_CODE_STORAGE_PERMISSION = 0x66;
|
||||
|
||||
public static final int NONE = -1;
|
||||
|
||||
public static final String DEFAULT_FILE_PROVIDER = ".appdown.provider.AppUpdaterFileProvider";
|
||||
|
||||
public static final String DEFAULT_DIR = "apk";
|
||||
|
||||
public static boolean isUpdate = true;
|
||||
|
||||
}
|
||||
240
winwaynew/src/main/java/just/way/appdown/http/HttpManager.java
Normal file
@@ -0,0 +1,240 @@
|
||||
package just.way.appdown.http;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
|
||||
import just.way.appdown.util.LogUtils;
|
||||
import just.way.appdown.util.SSLSocketFactoryUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* HttpManager使用 {@link HttpURLConnection} 实现的 {@link IHttpManager}
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class HttpManager implements IHttpManager {
|
||||
|
||||
private static final int HTTP_TEMP_REDIRECT = 307;
|
||||
private static final int HTTP_PERM_REDIRECT = 308;
|
||||
|
||||
private static final int DEFAULT_TIME_OUT = 20000;
|
||||
|
||||
private int mTimeout;
|
||||
|
||||
private DownloadTask mDownloadTask;
|
||||
|
||||
private static volatile HttpManager INSTANCE;
|
||||
|
||||
public static HttpManager getInstance(){
|
||||
if(INSTANCE == null){
|
||||
synchronized (HttpManager.class){
|
||||
if(INSTANCE == null){
|
||||
INSTANCE = new HttpManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private HttpManager(){
|
||||
this(DEFAULT_TIME_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* HttpManager对外暴露。如果没有特殊需求,推荐使用{@link HttpManager#getInstance()}
|
||||
*/
|
||||
public HttpManager(int timeout){
|
||||
this.mTimeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(String url, String path, String filename, @Nullable Map<String,String> requestProperty, DownloadCallback callback) {
|
||||
mDownloadTask = new DownloadTask(url, path, filename, mTimeout, requestProperty, callback);
|
||||
mDownloadTask.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
if(mDownloadTask != null){
|
||||
mDownloadTask.isCancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步下载任务
|
||||
*/
|
||||
private static class DownloadTask extends AsyncTask<Void,Long,File> {
|
||||
|
||||
private String url;
|
||||
|
||||
private String path;
|
||||
|
||||
private String filename;
|
||||
|
||||
private Map<String,String> requestProperty;
|
||||
|
||||
private DownloadCallback callback;
|
||||
|
||||
private Exception exception;
|
||||
|
||||
private int timeout;
|
||||
|
||||
private volatile boolean isCancel;
|
||||
|
||||
public DownloadTask(String url, String path, String filename, int timeout, @Nullable Map<String,String> requestProperty, DownloadCallback callback){
|
||||
this.url = url;
|
||||
this.path = path;
|
||||
this.filename = filename;
|
||||
this.timeout = timeout;
|
||||
this.callback = callback;
|
||||
this.requestProperty = requestProperty;
|
||||
}
|
||||
|
||||
private File download(String url) throws Exception{
|
||||
HttpURLConnection connect = (HttpURLConnection)new URL(url).openConnection();
|
||||
connect.setRequestMethod("GET");
|
||||
connect.setRequestProperty("Accept-Encoding", "identity");
|
||||
|
||||
connect.setReadTimeout(timeout);
|
||||
connect.setConnectTimeout(timeout);
|
||||
|
||||
if(requestProperty != null){
|
||||
for(Map.Entry<String,String> entry : requestProperty.entrySet()){
|
||||
connect.setRequestProperty(entry.getKey(),entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
connect.connect();
|
||||
|
||||
LogUtils.d("Content-Type:" + connect.getContentType());
|
||||
int responseCode = connect.getResponseCode();
|
||||
switch (responseCode){
|
||||
case HttpURLConnection.HTTP_OK: {
|
||||
InputStream is = connect.getInputStream();
|
||||
|
||||
long length = connect.getContentLength();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
length = connect.getContentLengthLong();
|
||||
}
|
||||
|
||||
LogUtils.d( "contentLength:" + length);
|
||||
|
||||
long progress = 0;
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
|
||||
int len;
|
||||
File file = new File(path, filename);
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
if (isCancel) {
|
||||
cancel(true);
|
||||
break;
|
||||
}
|
||||
fos.write(buffer, 0, len);
|
||||
progress += len;
|
||||
// 更新进度
|
||||
if (length > 0) {
|
||||
publishProgress(progress, length);
|
||||
}
|
||||
}
|
||||
|
||||
fos.flush();
|
||||
fos.close();
|
||||
is.close();
|
||||
|
||||
connect.disconnect();
|
||||
|
||||
if(progress <= 0 && length <= 0){
|
||||
throw new IllegalStateException(String.format("contentLength = %d",length));
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
case HttpURLConnection.HTTP_MULT_CHOICE:
|
||||
case HttpURLConnection.HTTP_MOVED_PERM:
|
||||
case HttpURLConnection.HTTP_MOVED_TEMP:
|
||||
case HttpURLConnection.HTTP_SEE_OTHER:
|
||||
case HTTP_TEMP_REDIRECT:
|
||||
case HTTP_PERM_REDIRECT: {// 重定向
|
||||
String redirectUrl = connect.getHeaderField("Location");
|
||||
LogUtils.d("redirectUrl = " + redirectUrl);
|
||||
connect.disconnect();
|
||||
return download(redirectUrl);
|
||||
}
|
||||
default://连接失败
|
||||
throw new ConnectException(String.format("responseCode = %d",responseCode));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File doInBackground(Void... voids) {
|
||||
|
||||
try{
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(SSLSocketFactoryUtils.createSSLSocketFactory());
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactoryUtils.createTrustAllHostnameVerifier());
|
||||
return download(url);
|
||||
} catch (Exception e) {
|
||||
this.exception = e;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
if(callback != null){
|
||||
callback.onStart(url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(File file) {
|
||||
super.onPostExecute(file);
|
||||
if(callback != null){
|
||||
if(file != null){
|
||||
callback.onFinish(file);
|
||||
}else{
|
||||
callback.onError(exception);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Long... values) {
|
||||
super.onProgressUpdate(values);
|
||||
if(callback != null){
|
||||
if(!isCancelled()){
|
||||
callback.onProgress(values[0],values[1]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
super.onCancelled();
|
||||
if(callback != null){
|
||||
callback.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package just.way.appdown.http;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* IHttpManager 默认提供 {@link HttpManager} 和 {@link OkHttpManager} 两种实现。
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface IHttpManager {
|
||||
|
||||
|
||||
/**
|
||||
* 下载
|
||||
* @param url
|
||||
* @param path
|
||||
* @param filename
|
||||
* @param requestProperty
|
||||
* @param callback
|
||||
*/
|
||||
void download(String url, String path, String filename, @Nullable Map<String,String> requestProperty, DownloadCallback callback);
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
interface DownloadCallback extends Serializable{
|
||||
/**
|
||||
* 开始
|
||||
* @param url
|
||||
*/
|
||||
void onStart(String url);
|
||||
|
||||
/**
|
||||
* 加载进度…
|
||||
* @param progress
|
||||
* @param total
|
||||
*/
|
||||
void onProgress(long progress,long total);
|
||||
|
||||
/**
|
||||
* 完成
|
||||
* @param file
|
||||
*/
|
||||
void onFinish(File file);
|
||||
|
||||
/**
|
||||
* 错误
|
||||
* @param e
|
||||
*/
|
||||
void onError(Exception e);
|
||||
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
void onCancel();
|
||||
}
|
||||
}
|
||||
235
winwaynew/src/main/java/just/way/appdown/http/OkHttpManager.java
Normal file
@@ -0,0 +1,235 @@
|
||||
package just.way.appdown.http;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import just.way.appdown.util.LogUtils;
|
||||
import just.way.appdown.util.SSLSocketFactoryUtils;
|
||||
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* OkHttpManager使用 {@link OkHttpClient} 实现的 {@link IHttpManager}
|
||||
* <p>使用 OkHttpManager 时必须依赖 OkHttp 库
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class OkHttpManager implements IHttpManager {
|
||||
|
||||
private static final int DEFAULT_TIME_OUT = 20000;
|
||||
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
private DownloadTask mDownloadTask;
|
||||
|
||||
private static volatile OkHttpManager INSTANCE;
|
||||
|
||||
public static OkHttpManager getInstance(){
|
||||
if(INSTANCE == null){
|
||||
synchronized (HttpManager.class){
|
||||
if(INSTANCE == null){
|
||||
INSTANCE = new OkHttpManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private OkHttpManager(){
|
||||
this(DEFAULT_TIME_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* HttpManager对外暴露。如果没有特殊需求,推荐使用{@link HttpManager#getInstance()}
|
||||
* @param timeout 超时时间,单位:毫秒
|
||||
*/
|
||||
public OkHttpManager(int timeout){
|
||||
this(new OkHttpClient.Builder()
|
||||
.readTimeout(timeout, TimeUnit.MILLISECONDS)
|
||||
.connectTimeout(timeout, TimeUnit.MILLISECONDS)
|
||||
.sslSocketFactory(SSLSocketFactoryUtils.createSSLSocketFactory(),SSLSocketFactoryUtils.createTrustAllManager())
|
||||
.hostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* HttpManager对外暴露,推荐使用{@link HttpManager#getInstance()}
|
||||
* @param okHttpClient {@link OkHttpClient}
|
||||
*/
|
||||
public OkHttpManager(@NonNull OkHttpClient okHttpClient){
|
||||
this.okHttpClient = okHttpClient;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void download(String url,final String path,final String filename, @Nullable Map<String, String> requestProperty,final DownloadCallback callback) {
|
||||
mDownloadTask = new DownloadTask(okHttpClient, url, path, filename, requestProperty, callback);
|
||||
mDownloadTask.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
if(mDownloadTask != null){
|
||||
mDownloadTask.isCancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 异步下载任务
|
||||
*/
|
||||
private static class DownloadTask extends AsyncTask<Void,Long,File> {
|
||||
|
||||
private String url;
|
||||
|
||||
private String path;
|
||||
|
||||
private String filename;
|
||||
|
||||
private Map<String,String> requestProperty;
|
||||
|
||||
private DownloadCallback callback;
|
||||
|
||||
private Exception exception;
|
||||
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
private volatile boolean isCancel;
|
||||
|
||||
public DownloadTask(OkHttpClient okHttpClient,String url, String path, String filename ,@Nullable Map<String,String> requestProperty, DownloadCallback callback){
|
||||
this.okHttpClient = okHttpClient;
|
||||
this.url = url;
|
||||
this.path = path;
|
||||
this.filename = filename;
|
||||
this.callback = callback;
|
||||
this.requestProperty = requestProperty;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File doInBackground(Void... voids) {
|
||||
|
||||
try{
|
||||
Request.Builder builder = new Request.Builder()
|
||||
.url(url)
|
||||
.addHeader("Accept-Encoding", "identity")
|
||||
.get();
|
||||
|
||||
if(requestProperty!=null){
|
||||
for(Map.Entry<String,String> entry : requestProperty.entrySet()){
|
||||
builder.addHeader(entry.getKey(),entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
Call call = okHttpClient.newCall(builder.build());
|
||||
Response response = call.execute();
|
||||
|
||||
if(response.isSuccessful()){
|
||||
InputStream is = response.body().byteStream();
|
||||
|
||||
long length = response.body().contentLength();
|
||||
|
||||
LogUtils.d("contentLength:" + length);
|
||||
|
||||
long progress = 0;
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
|
||||
int len;
|
||||
File file = new File(path,filename);
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
while ((len = is.read(buffer)) != -1){
|
||||
if(isCancel){
|
||||
if(call != null){
|
||||
call.cancel();
|
||||
}
|
||||
cancel(true);
|
||||
break;
|
||||
}
|
||||
fos.write(buffer,0,len);
|
||||
progress += len;
|
||||
// 更新进度
|
||||
if(length > 0){
|
||||
publishProgress(progress,length);
|
||||
}
|
||||
}
|
||||
|
||||
fos.flush();
|
||||
fos.close();
|
||||
is.close();
|
||||
|
||||
response.close();
|
||||
|
||||
if(progress <= 0 && length <= 0){
|
||||
throw new IllegalStateException(String.format("contentLength = %d",length));
|
||||
}
|
||||
|
||||
return file;
|
||||
|
||||
}else {// 连接失败
|
||||
throw new ConnectException(String.format("responseCode = %d",response.code()));
|
||||
}
|
||||
|
||||
}catch (Exception e){
|
||||
this.exception = e;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
if(callback != null){
|
||||
callback.onStart(url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(File file) {
|
||||
super.onPostExecute(file);
|
||||
if(callback != null){
|
||||
if(file != null){
|
||||
callback.onFinish(file);
|
||||
}else{
|
||||
callback.onError(exception);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Long... values) {
|
||||
super.onProgressUpdate(values);
|
||||
if(callback != null){
|
||||
if(!isCancelled()){
|
||||
callback.onProgress(values[0],values[1]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
super.onCancelled();
|
||||
if(callback != null){
|
||||
callback.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package just.way.appdown.notify;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import just.way.appdown.UpdateConfig;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface INotification {
|
||||
|
||||
void onStart(Context context, int notifyId, String channelId, String channelName, @DrawableRes int icon, CharSequence title, CharSequence content, boolean isVibrate, boolean isSound, boolean isCancelDownload);
|
||||
|
||||
void onProgress(Context context, int notifyId, String channelId, @DrawableRes int icon, CharSequence title, CharSequence content, int progress, int size, boolean isCancelDownload);
|
||||
|
||||
void onFinish(Context context, int notifyId, String channelId, @DrawableRes int icon, CharSequence title, CharSequence content, File file, String authority);
|
||||
|
||||
void onError(Context context, int notifyId, String channelId, @DrawableRes int icon, CharSequence title, CharSequence content, boolean isReDownload, UpdateConfig config);
|
||||
|
||||
void onCancel(Context context, int notifyId);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package just.way.appdown.notify;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import just.way.appdown.UpdateConfig;
|
||||
import just.way.appdown.util.NotificationUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class NotificationImpl implements INotification {
|
||||
@Override
|
||||
public void onStart(Context context, int notifyId, String channelId, String channelName, int icon, CharSequence title, CharSequence content, boolean isVibrate, boolean isSound, boolean isCancelDownload) {
|
||||
NotificationUtils.showStartNotification(context, notifyId, channelId, channelName, icon, title, content, isVibrate, isSound, isCancelDownload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(Context context, int notifyId, String channelId, int icon, CharSequence title, CharSequence content, int progress, int size, boolean isCancelDownload) {
|
||||
NotificationUtils.showProgressNotification(context, notifyId, channelId, icon, title, content, progress, size, isCancelDownload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish(Context context, int notifyId, String channelId, int icon, CharSequence title, CharSequence content, File file, String authority) {
|
||||
NotificationUtils.showFinishNotification(context, notifyId, channelId, icon, title, content, file, authority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Context context, int notifyId, String channelId, int icon, CharSequence title, CharSequence content, boolean isReDownload, UpdateConfig config) {
|
||||
NotificationUtils.showErrorNotification(context, notifyId, channelId, icon, title, content, isReDownload, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(Context context, int notifyId) {
|
||||
NotificationUtils.cancelNotification(context, notifyId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package just.way.appdown.provider;
|
||||
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class AppUpdaterFileProvider extends FileProvider {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,456 @@
|
||||
package just.way.appdown.service;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import just.way.R;
|
||||
import just.way.appdown.UpdateConfig;
|
||||
import just.way.appdown.callback.UpdateCallback;
|
||||
import just.way.appdown.constant.Constants;
|
||||
import just.way.appdown.http.HttpManager;
|
||||
import just.way.appdown.http.IHttpManager;
|
||||
import just.way.appdown.notify.INotification;
|
||||
import just.way.appdown.notify.NotificationImpl;
|
||||
import just.way.appdown.util.AppUtils;
|
||||
import just.way.appdown.util.LogUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
|
||||
/**
|
||||
* 下载服务
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class DownloadService extends Service {
|
||||
|
||||
private DownloadBinder mDownloadBinder = new DownloadBinder();
|
||||
/**
|
||||
* 是否在下载,防止重复下载。
|
||||
*/
|
||||
private boolean isDownloading;
|
||||
/**
|
||||
* 失败后重新下载次数
|
||||
*/
|
||||
private int mCount = 0;
|
||||
/**
|
||||
* Http管理器
|
||||
*/
|
||||
private IHttpManager mHttpManager;
|
||||
|
||||
private File mApkFile;
|
||||
|
||||
private Context getContext(){
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if(intent != null){
|
||||
boolean isStop = intent.getBooleanExtra(Constants.KEY_STOP_DOWNLOAD_SERVICE,false);
|
||||
if(isStop){
|
||||
stopDownload();
|
||||
} else if(!isDownloading){
|
||||
//是否实通过通知栏触发重复下载
|
||||
boolean isReDownload = intent.getBooleanExtra(Constants.KEY_RE_DOWNLOAD,false);
|
||||
if(isReDownload){
|
||||
mCount++;
|
||||
}
|
||||
//获取配置信息
|
||||
UpdateConfig config = intent.getParcelableExtra(Constants.KEY_UPDATE_CONFIG);
|
||||
startDownload(config,null,null, new NotificationImpl());
|
||||
}else{
|
||||
LogUtils.w("Please do not duplicate downloads.");
|
||||
}
|
||||
}
|
||||
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
* @param config
|
||||
* @param httpManager
|
||||
* @param callback
|
||||
*/
|
||||
public void startDownload(@NonNull UpdateConfig config,@Nullable IHttpManager httpManager,@Nullable UpdateCallback callback, @Nullable INotification notification){
|
||||
if(callback != null){
|
||||
callback.onDownloading(isDownloading);
|
||||
}
|
||||
|
||||
if(isDownloading){
|
||||
LogUtils.w("Please do not duplicate downloads.");
|
||||
return;
|
||||
}
|
||||
|
||||
String url = config.getUrl();
|
||||
String path = config.getPath();
|
||||
String filename = config.getFilename();
|
||||
|
||||
//如果保存路径为空则使用缓存路径
|
||||
if(TextUtils.isEmpty(path)){
|
||||
path = getCacheFilesDir(getContext());
|
||||
}
|
||||
File dirFile = new File(path);
|
||||
if(!dirFile.exists()){
|
||||
dirFile.mkdirs();
|
||||
}
|
||||
|
||||
//如果文件名为空则使用路径
|
||||
if(TextUtils.isEmpty(filename)){
|
||||
filename = AppUtils.getAppFullName(getContext(),url,getResources().getString(R.string.app_name));
|
||||
}
|
||||
|
||||
mApkFile = new File(path, filename);
|
||||
if(mApkFile.exists()){//文件是否存在
|
||||
Integer versionCode = config.getVersionCode();
|
||||
String apkMD5 = config.getApkMD5();
|
||||
//是否存在相同的apk
|
||||
boolean isExistApk = false;
|
||||
if(!TextUtils.isEmpty(apkMD5)){//如果存在MD5,则优先校验MD5
|
||||
LogUtils.d(String.format(Locale.getDefault(),"UpdateConfig.apkMD5:%s",apkMD5));
|
||||
isExistApk = AppUtils.checkFileMD5(mApkFile,apkMD5);
|
||||
}else if(versionCode != null){//如果存在versionCode,则校验versionCode
|
||||
LogUtils.d(String.format(Locale.getDefault(),"UpdateConfig.versionCode:%d",versionCode));
|
||||
isExistApk = AppUtils.apkExists(getContext(),versionCode,mApkFile);
|
||||
}
|
||||
|
||||
if(isExistApk){
|
||||
//本地已经存在要下载的APK
|
||||
LogUtils.d("CacheFile:" + mApkFile);
|
||||
if(config.isInstallApk()){
|
||||
String authority = config.getAuthority();
|
||||
if(TextUtils.isEmpty(authority)){//如果为空则默认
|
||||
authority = AppUtils.getFileProviderAuthority(getContext());
|
||||
}
|
||||
AppUtils.installApk(getContext(), mApkFile, authority);
|
||||
}
|
||||
if(callback != null){
|
||||
callback.onFinish(mApkFile);
|
||||
}
|
||||
stopService();
|
||||
return;
|
||||
}
|
||||
|
||||
//删除旧文件
|
||||
mApkFile.delete();
|
||||
}
|
||||
LogUtils.d("File:" + mApkFile);
|
||||
|
||||
mHttpManager = httpManager != null ? httpManager : HttpManager.getInstance();
|
||||
IHttpManager.DownloadCallback downloadCallback = new AppDownloadCallback(getContext(),this, config, mApkFile, callback, notification);
|
||||
mHttpManager.download(url,path,filename,config.getRequestProperty(), downloadCallback);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止下载
|
||||
*/
|
||||
public void stopDownload(){
|
||||
if(mHttpManager != null){
|
||||
mHttpManager.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存路径
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
private String getCacheFilesDir(Context context) {
|
||||
File[] files = ContextCompat.getExternalFilesDirs(context, Constants.DEFAULT_DIR);
|
||||
if(files != null && files.length > 0){
|
||||
return files[0].getAbsolutePath();
|
||||
}
|
||||
|
||||
File externalFilesDir = context.getExternalFilesDir(Constants.DEFAULT_DIR);
|
||||
if(externalFilesDir != null){
|
||||
return externalFilesDir.getAbsolutePath();
|
||||
}
|
||||
|
||||
return new File(context.getFilesDir(), Constants.DEFAULT_DIR).getAbsolutePath();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止服务
|
||||
*/
|
||||
private void stopService(){
|
||||
mCount = 0;
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------- DownloadCallback
|
||||
|
||||
/**
|
||||
* App下载回调接口
|
||||
*/
|
||||
public static class AppDownloadCallback implements IHttpManager.DownloadCallback {
|
||||
|
||||
private Context context;
|
||||
|
||||
private DownloadService downloadService;
|
||||
|
||||
public UpdateConfig config;
|
||||
|
||||
private boolean isShowNotification;
|
||||
|
||||
private int notifyId;
|
||||
|
||||
private String channelId;
|
||||
|
||||
private String channelName;
|
||||
|
||||
private int notificationIcon;
|
||||
|
||||
private boolean isInstallApk;
|
||||
|
||||
private String authority;
|
||||
|
||||
private boolean isShowPercentage;
|
||||
|
||||
private boolean isReDownload;
|
||||
|
||||
private boolean isDeleteCancelFile;
|
||||
|
||||
private boolean isCancelDownload;
|
||||
|
||||
private UpdateCallback callback;
|
||||
|
||||
private INotification notification;
|
||||
|
||||
/**
|
||||
* 最后更新进度,用来降频刷新
|
||||
*/
|
||||
private int lastProgress;
|
||||
/**
|
||||
* 最后进度更新时间,用来降频刷新
|
||||
*/
|
||||
private long lastTime;
|
||||
/**
|
||||
* APK文件
|
||||
*/
|
||||
private File apkFile;
|
||||
|
||||
|
||||
private AppDownloadCallback(Context context, DownloadService downloadService, UpdateConfig config, File apkFile, UpdateCallback callback, INotification notification){
|
||||
this.context = context;
|
||||
this.downloadService = downloadService;
|
||||
this.config = config;
|
||||
this.apkFile = apkFile;
|
||||
this.callback = callback;
|
||||
this.notification = notification;
|
||||
this.isShowNotification = config.isShowNotification();
|
||||
this.notifyId = config.getNotificationId();
|
||||
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
|
||||
this.channelId = TextUtils.isEmpty(config.getChannelId()) ? Constants.DEFAULT_NOTIFICATION_CHANNEL_ID : config.getChannelId();
|
||||
this.channelName = TextUtils.isEmpty(config.getChannelName()) ? Constants.DEFAULT_NOTIFICATION_CHANNEL_NAME : config.getChannelName();
|
||||
}
|
||||
if(config.getNotificationIcon() <= 0){
|
||||
this.notificationIcon = AppUtils.getAppIcon(context);
|
||||
}else{
|
||||
this.notificationIcon = config.getNotificationIcon();
|
||||
}
|
||||
|
||||
this.isInstallApk = config.isInstallApk();
|
||||
|
||||
this.authority = config.getAuthority();
|
||||
if(TextUtils.isEmpty(config.getAuthority())){//如果为空则默认
|
||||
authority = AppUtils.getFileProviderAuthority(context);
|
||||
}
|
||||
|
||||
this.isShowPercentage = config.isShowPercentage();
|
||||
this.isDeleteCancelFile = config.isDeleteCancelFile();
|
||||
this.isCancelDownload = config.isCancelDownload();
|
||||
|
||||
//支持下载失败时重新下载,当重新下载次数不超过限制时才被允许
|
||||
this.isReDownload = config.isReDownload() && downloadService.mCount < config.getReDownloads();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(String url) {
|
||||
LogUtils.i("url:" + url);
|
||||
downloadService.isDownloading = true;
|
||||
lastProgress = 0;
|
||||
if(isShowNotification && notification != null){
|
||||
String title="";
|
||||
if(Constants.isUpdate){
|
||||
title = getString(R.string.app_updater_start_notification_title);
|
||||
}else{
|
||||
title = getString(R.string.app_updater_start_notification_title_2);
|
||||
}
|
||||
notification.onStart(context,notifyId,channelId,channelName,notificationIcon,title,getString(R.string.app_updater_start_notification_content),config.isVibrate(),config.isSound(),isCancelDownload);
|
||||
}
|
||||
|
||||
if(callback != null){
|
||||
callback.onStart(url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(long progress, long total) {
|
||||
boolean isChange = false;
|
||||
long curTime = System.currentTimeMillis();
|
||||
if(lastTime + 200 < curTime || progress == total) {//降低更新频率
|
||||
lastTime = curTime;
|
||||
|
||||
int currProgress = Math.round(progress * 1.0f / total * 100.0f);
|
||||
if(currProgress != lastProgress){//百分比改变了才更新
|
||||
isChange = true;
|
||||
lastProgress = currProgress;
|
||||
String percentage = currProgress + "%";
|
||||
LogUtils.i(String.format(Locale.getDefault(),"%s \t(%d/%d)", percentage, progress, total));
|
||||
if(isShowNotification && notification != null) {
|
||||
String content = context.getString(R.string.app_updater_progress_notification_content);
|
||||
if (isShowPercentage) {
|
||||
content += percentage;
|
||||
}
|
||||
String title="";
|
||||
if(Constants.isUpdate){
|
||||
title = getString(R.string.app_updater_progress_notification_title);
|
||||
}else{
|
||||
title = getString(R.string.app_updater_progress_notification_title_2);
|
||||
}
|
||||
notification.onProgress(context,notifyId, channelId, notificationIcon, title, content, currProgress, 100,isCancelDownload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(callback != null){
|
||||
callback.onProgress(progress,total,isChange);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish(File file) {
|
||||
LogUtils.d("File:" + file);
|
||||
downloadService.isDownloading = false;
|
||||
if(isShowNotification && notification != null){
|
||||
notification.onFinish(context,notifyId,channelId,notificationIcon,getString(R.string.app_updater_finish_notification_title),getString(R.string.app_updater_finish_notification_content),file,authority);
|
||||
}
|
||||
if(isInstallApk){
|
||||
AppUtils.installApk(context,file,authority);
|
||||
}
|
||||
if(callback != null){
|
||||
callback.onFinish(file);
|
||||
}
|
||||
downloadService.stopService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception e) {
|
||||
LogUtils.w(e.getMessage());
|
||||
downloadService.isDownloading = false;
|
||||
if(isShowNotification && notification != null){
|
||||
String content = isReDownload ? getString(R.string.app_updater_error_notification_content_re_download) : getString(R.string.app_updater_error_notification_content);
|
||||
notification.onError(context,notifyId,channelId,notificationIcon,getString(R.string.app_updater_error_notification_title),content,isReDownload,config);
|
||||
}
|
||||
|
||||
if(callback != null){
|
||||
callback.onError(e);
|
||||
}
|
||||
if(!isReDownload){
|
||||
downloadService.stopService();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
LogUtils.d("Cancel download.");
|
||||
downloadService.isDownloading = false;
|
||||
if(isShowNotification && notification != null){
|
||||
notification.onCancel(context,notifyId);
|
||||
}
|
||||
if(callback != null){
|
||||
callback.onCancel();
|
||||
}
|
||||
if(isDeleteCancelFile && apkFile != null){
|
||||
apkFile.delete();
|
||||
}
|
||||
downloadService.stopService();
|
||||
}
|
||||
|
||||
private String getString(@StringRes int resId){
|
||||
return context.getString(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
isDownloading = false;
|
||||
mHttpManager = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
//---------------------------------------- Binder
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mDownloadBinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供绑定服务的方式进行下载
|
||||
*/
|
||||
public class DownloadBinder extends Binder {
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
* @param config {@link UpdateConfig}
|
||||
*/
|
||||
public void start(@NonNull UpdateConfig config){
|
||||
start(config,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
* @param config {@link UpdateConfig}
|
||||
* @param callback {@link UpdateCallback}
|
||||
*/
|
||||
public void start(@NonNull UpdateConfig config, @Nullable UpdateCallback callback){
|
||||
start(config,null, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
* @param config {@link UpdateConfig}
|
||||
* @param httpManager {@link IHttpManager}
|
||||
* @param callback {@link UpdateCallback}
|
||||
*/
|
||||
public void start(@NonNull UpdateConfig config, @Nullable IHttpManager httpManager, @Nullable UpdateCallback callback){
|
||||
start(config, httpManager, callback, new NotificationImpl());
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
* @param config {@link UpdateConfig}
|
||||
* @param httpManager {@link IHttpManager}
|
||||
* @param callback {@link UpdateCallback}
|
||||
* @param notification {@link INotification}
|
||||
*/
|
||||
public void start(@NonNull UpdateConfig config, @Nullable IHttpManager httpManager, @Nullable UpdateCallback callback,@NonNull INotification notification){
|
||||
startDownload(config, httpManager, callback, notification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
264
winwaynew/src/main/java/just/way/appdown/util/AppUtils.java
Normal file
@@ -0,0 +1,264 @@
|
||||
package just.way.appdown.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import just.way.appdown.constant.Constants;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public final class AppUtils {
|
||||
|
||||
private AppUtils(){
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过url获取App的全名称
|
||||
* @param context
|
||||
* @return AppName.apk
|
||||
*/
|
||||
public static String getAppFullName(Context context,String url,String defaultName){
|
||||
if(url.endsWith(".apk")){
|
||||
String apkName = url.substring(url.lastIndexOf("/") + 1);
|
||||
if(apkName.length() <= 64){
|
||||
return apkName;
|
||||
}
|
||||
}
|
||||
|
||||
String filename = getAppName(context);
|
||||
Log.d(Constants.TAG, "AppName:" + filename);
|
||||
if(TextUtils.isEmpty(filename)){
|
||||
filename = defaultName;
|
||||
}
|
||||
if(filename.endsWith(".apk")){
|
||||
return filename;
|
||||
}
|
||||
return String.format("%s.apk",filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包信息
|
||||
* @param context
|
||||
* @return
|
||||
* @throws PackageManager.NameNotFoundException
|
||||
*/
|
||||
public static PackageInfo getPackageInfo(Context context) throws PackageManager.NameNotFoundException {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过APK路径获取包信息
|
||||
* @param context
|
||||
* @param archiveFilePath
|
||||
* @return
|
||||
*/
|
||||
public static PackageInfo getPackageInfo(Context context, String archiveFilePath) {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
PackageInfo packageInfo = packageManager.getPackageArchiveInfo(archiveFilePath, PackageManager.GET_ACTIVITIES);
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取App的名称
|
||||
*/
|
||||
public static String getAppName(Context context) {
|
||||
try{
|
||||
int labelRes = getPackageInfo(context).applicationInfo.labelRes;
|
||||
return context.getResources().getString(labelRes);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取App的图标
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static int getAppIcon(Context context){
|
||||
try{
|
||||
return getPackageInfo(context).applicationInfo.icon;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装apk
|
||||
* @param context
|
||||
* @param file
|
||||
*/
|
||||
public static void installApk(Context context,File file,String authority){
|
||||
Intent intent = getInstallIntent(context,file,authority);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取安装Intent
|
||||
* @param context
|
||||
* @param file
|
||||
* @param authority
|
||||
* @return
|
||||
*/
|
||||
public static Intent getInstallIntent(Context context,File file,String authority){
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
Uri uriData;
|
||||
String type = "application/vnd.android.package-archive";
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
uriData = FileProvider.getUriForFile(context, authority, file);
|
||||
}else{
|
||||
uriData = Uri.fromFile(file);
|
||||
}
|
||||
intent.setDataAndType(uriData, type);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* APK是否存在
|
||||
* @param context
|
||||
* @param versionCode
|
||||
* @param file
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean apkExists(Context context,int versionCode,File file){
|
||||
if(file != null && file.exists()){
|
||||
String packageName = context.getPackageName();
|
||||
PackageInfo packageInfo = AppUtils.getPackageInfo(context,file.getAbsolutePath());
|
||||
if(packageInfo != null){// 比对versionCode
|
||||
Log.d(Constants.TAG,String.format("ApkVersionCode:%d",packageInfo.versionCode));
|
||||
if(versionCode == packageInfo.versionCode){
|
||||
ApplicationInfo applicationInfo = packageInfo.applicationInfo;
|
||||
if(applicationInfo != null && packageName.equals(applicationInfo.packageName)){//比对packageName
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否存在
|
||||
* @param context
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAndroidQFileExists(Context context,String path){
|
||||
return isAndroidQFileExists(context,new File(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否存在
|
||||
* @param context
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAndroidQFileExists(Context context,File file){
|
||||
AssetFileDescriptor descriptor = null;
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
try {
|
||||
Uri uri = Uri.fromFile(file);
|
||||
descriptor = contentResolver.openAssetFileDescriptor(uri, "r");
|
||||
if (descriptor == null) {
|
||||
return false;
|
||||
} else {
|
||||
close(descriptor);
|
||||
}
|
||||
return true;
|
||||
} catch (FileNotFoundException e) {
|
||||
|
||||
}finally {
|
||||
close(descriptor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验文件MD5
|
||||
* @param file
|
||||
* @param md5
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkFileMD5(File file,String md5){
|
||||
String fileMD5 = getFileMD5(file);
|
||||
Log.d(Constants.TAG,"FileMD5:"+ fileMD5);
|
||||
if(!TextUtils.isEmpty(md5)){
|
||||
return md5.equalsIgnoreCase(fileMD5);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件MD5
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
public static String getFileMD5(File file){
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = fis.read(buffer)) != -1){
|
||||
messageDigest.update(buffer,0,length);
|
||||
}
|
||||
BigInteger bigInteger = new BigInteger(1,messageDigest.digest());
|
||||
return bigInteger.toString(16);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getFileProviderAuthority(Context context){
|
||||
return context.getPackageName() + Constants.DEFAULT_FILE_PROVIDER;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭
|
||||
* @param descriptor
|
||||
*/
|
||||
private static void close(AssetFileDescriptor descriptor){
|
||||
if(descriptor != null){
|
||||
try {
|
||||
descriptor.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
316
winwaynew/src/main/java/just/way/appdown/util/LogUtils.java
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
Copyright © 2015, 2016 Jenly Yu <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
package just.way.appdown.util;
|
||||
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
public static final String TAG = "AppUpdater";
|
||||
|
||||
public static final String VERTICAL = "|";
|
||||
|
||||
/** 是否显示Log日志 */
|
||||
private static boolean isShowLog = true;
|
||||
|
||||
/** Log日志优先权 */
|
||||
private static int priority = 1;
|
||||
|
||||
/**
|
||||
* Priority constant for the println method;use System.out.println
|
||||
*/
|
||||
public static final int PRINTLN = 1;
|
||||
|
||||
/**
|
||||
* Priority constant for the println method; use Log.v.
|
||||
*/
|
||||
public static final int VERBOSE = 2;
|
||||
|
||||
/**
|
||||
* Priority constant for the println method; use Log.d.
|
||||
*/
|
||||
public static final int DEBUG = 3;
|
||||
|
||||
/**
|
||||
* Priority constant for the println method; use Log.i.
|
||||
*/
|
||||
public static final int INFO = 4;
|
||||
|
||||
/**
|
||||
* Priority constant for the println method; use Log.w.
|
||||
*/
|
||||
public static final int WARN = 5;
|
||||
|
||||
/**
|
||||
* Priority constant for the println method; use Log.e.
|
||||
*/
|
||||
public static final int ERROR = 6;
|
||||
|
||||
/**
|
||||
* Priority constant for the println method.use Log.wtf.
|
||||
*/
|
||||
public static final int ASSERT = 7;
|
||||
|
||||
public static final String TAG_FORMAT = "%s.%s(%s:%d)";
|
||||
|
||||
private LogUtils(){
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static void setShowLog(boolean isShowLog) {
|
||||
|
||||
LogUtils.isShowLog = isShowLog;
|
||||
}
|
||||
|
||||
public static boolean isShowLog() {
|
||||
|
||||
return isShowLog;
|
||||
}
|
||||
|
||||
public static int getPriority() {
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
public static void setPriority(int priority) {
|
||||
|
||||
LogUtils.priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据堆栈生成TAG
|
||||
* @return TAG|className.methodName(fileName:lineNumber)
|
||||
*/
|
||||
private static String generateTag(StackTraceElement caller) {
|
||||
String tag = TAG_FORMAT;
|
||||
String callerClazzName = caller.getClassName();
|
||||
callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);
|
||||
tag = String.format(Locale.getDefault(),tag,callerClazzName, caller.getMethodName(),caller.getFileName(),caller.getLineNumber());
|
||||
return new StringBuilder().append(TAG).append(VERTICAL).append(tag).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取堆栈
|
||||
* @param n
|
||||
* n=0 VMStack
|
||||
* n=1 Thread
|
||||
* n=3 CurrentStack
|
||||
* n=4 CallerStack
|
||||
* ...
|
||||
* @return
|
||||
*/
|
||||
public static StackTraceElement getStackTraceElement(int n) {
|
||||
return Thread.currentThread().getStackTrace()[n];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调用方的堆栈TAG
|
||||
* @return
|
||||
*/
|
||||
private static String getCallerStackLogTag(){
|
||||
return generateTag(getStackTraceElement(5));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param t
|
||||
* @return
|
||||
*/
|
||||
private static String getStackTraceString(Throwable t){
|
||||
return Log.getStackTraceString(t);
|
||||
}
|
||||
|
||||
// -----------------------------------Log.v
|
||||
|
||||
/**
|
||||
* Log.v
|
||||
* @param msg
|
||||
*/
|
||||
public static void v(String msg) {
|
||||
if (isShowLog && priority <= VERBOSE)
|
||||
Log.v(getCallerStackLogTag(), String.valueOf(msg));
|
||||
|
||||
}
|
||||
|
||||
public static void v(Throwable t) {
|
||||
if (isShowLog && priority <= VERBOSE)
|
||||
Log.v(getCallerStackLogTag(), getStackTraceString(t));
|
||||
}
|
||||
|
||||
public static void v(String msg,Throwable t) {
|
||||
if (isShowLog && priority <= VERBOSE)
|
||||
Log.v(getCallerStackLogTag(), String.valueOf(msg), t);
|
||||
}
|
||||
|
||||
// -----------------------------------Log.d
|
||||
|
||||
/**
|
||||
* Log.d
|
||||
* @param msg
|
||||
*/
|
||||
public static void d(String msg) {
|
||||
if (isShowLog && priority <= DEBUG)
|
||||
Log.d(getCallerStackLogTag(), String.valueOf(msg));
|
||||
}
|
||||
|
||||
public static void d(Throwable t) {
|
||||
if (isShowLog && priority <= DEBUG)
|
||||
Log.d(getCallerStackLogTag(), getStackTraceString(t));
|
||||
}
|
||||
|
||||
public static void d(String msg,Throwable t) {
|
||||
if (isShowLog && priority <= DEBUG)
|
||||
Log.d(getCallerStackLogTag(), String.valueOf(msg), t);
|
||||
}
|
||||
|
||||
// -----------------------------------Log.i
|
||||
|
||||
/**
|
||||
* Log.i
|
||||
* @param msg
|
||||
*/
|
||||
public static void i(String msg) {
|
||||
if (isShowLog && priority <= INFO)
|
||||
Log.i(getCallerStackLogTag(), String.valueOf(msg));
|
||||
}
|
||||
|
||||
public static void i(Throwable t) {
|
||||
if (isShowLog && priority <= INFO)
|
||||
Log.i(getCallerStackLogTag(), getStackTraceString(t));
|
||||
}
|
||||
|
||||
public static void i(String msg,Throwable t) {
|
||||
if (isShowLog && priority <= INFO)
|
||||
Log.i(getCallerStackLogTag(), String.valueOf(msg), t);
|
||||
}
|
||||
|
||||
// -----------------------------------Log.w
|
||||
|
||||
/**
|
||||
* Log.w
|
||||
* @param msg
|
||||
*/
|
||||
public static void w(String msg) {
|
||||
if (isShowLog && priority <= WARN)
|
||||
Log.w(getCallerStackLogTag(), String.valueOf(msg));
|
||||
}
|
||||
|
||||
public static void w(Throwable t) {
|
||||
if (isShowLog && priority <= WARN)
|
||||
Log.w(getCallerStackLogTag(), getStackTraceString(t));
|
||||
}
|
||||
|
||||
public static void w(String msg,Throwable t) {
|
||||
if (isShowLog && priority <= WARN)
|
||||
Log.w(getCallerStackLogTag(), String.valueOf(msg), t);
|
||||
}
|
||||
|
||||
// -----------------------------------Log.e
|
||||
|
||||
/**
|
||||
* Log.e
|
||||
* @param msg
|
||||
*/
|
||||
public static void e(String msg) {
|
||||
if (isShowLog && priority <= ERROR)
|
||||
Log.e(getCallerStackLogTag(), String.valueOf(msg));
|
||||
}
|
||||
|
||||
public static void e(Throwable t) {
|
||||
if (isShowLog && priority <= ERROR)
|
||||
Log.e(getCallerStackLogTag(), getStackTraceString(t));
|
||||
}
|
||||
|
||||
public static void e(String msg,Throwable t) {
|
||||
if (isShowLog && priority <= ERROR)
|
||||
Log.e(getCallerStackLogTag(), String.valueOf(msg), t);
|
||||
}
|
||||
|
||||
// -----------------------------------Log.wtf
|
||||
|
||||
/**
|
||||
* Log.wtf
|
||||
* @param msg
|
||||
*/
|
||||
public static void wtf(String msg) {
|
||||
if (isShowLog && priority <= ASSERT)
|
||||
Log.wtf(getCallerStackLogTag(), String.valueOf(msg));
|
||||
}
|
||||
|
||||
public static void wtf(Throwable t) {
|
||||
if (isShowLog && priority <= ASSERT)
|
||||
Log.wtf(getCallerStackLogTag(), getStackTraceString(t));
|
||||
}
|
||||
|
||||
public static void wtf(String msg,Throwable t) {
|
||||
if (isShowLog && priority <= ASSERT)
|
||||
Log.wtf(getCallerStackLogTag(), String.valueOf(msg), t);
|
||||
}
|
||||
|
||||
// -----------------------------------System.out.print
|
||||
|
||||
/**
|
||||
* System.out.print
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void print(String msg) {
|
||||
if (isShowLog && priority <= PRINTLN)
|
||||
System.out.print(msg);
|
||||
}
|
||||
|
||||
public static void print(Object obj) {
|
||||
if (isShowLog && priority <= PRINTLN)
|
||||
System.out.print(obj);
|
||||
}
|
||||
|
||||
// -----------------------------------System.out.printf
|
||||
|
||||
/**
|
||||
* System.out.printf
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void printf(String msg) {
|
||||
if (isShowLog && priority <= PRINTLN)
|
||||
System.out.printf(msg);
|
||||
}
|
||||
|
||||
// -----------------------------------System.out.println
|
||||
|
||||
/**
|
||||
* System.out.println
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void println(String msg) {
|
||||
if (isShowLog && priority <= PRINTLN)
|
||||
System.out.println(msg);
|
||||
}
|
||||
|
||||
public static void println(Object obj) {
|
||||
if (isShowLog && priority <= PRINTLN)
|
||||
System.out.println(obj);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
package just.way.appdown.util;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import just.way.appdown.UpdateConfig;
|
||||
import just.way.appdown.constant.Constants;
|
||||
import just.way.appdown.service.DownloadService;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class NotificationUtils {
|
||||
|
||||
private NotificationUtils(){
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示开始下载时的通知
|
||||
* @param notifyId
|
||||
* @param channelId
|
||||
* @param channelName
|
||||
* @param icon
|
||||
* @param title
|
||||
* @param content
|
||||
*/
|
||||
public static void showStartNotification(Context context, int notifyId,String channelId, String channelName,@DrawableRes int icon,CharSequence title,CharSequence content,boolean isVibrate,boolean isSound, boolean isCancelDownload){
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
|
||||
createNotificationChannel(context,channelId,channelName,isVibrate,isSound);
|
||||
}
|
||||
NotificationCompat.Builder builder = buildNotification(context,channelId,icon,title,content);
|
||||
builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
||||
if(isVibrate && isSound){
|
||||
builder.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND);
|
||||
}else if(isVibrate){
|
||||
builder.setDefaults(Notification.DEFAULT_VIBRATE);
|
||||
}else if(isSound){
|
||||
builder.setDefaults(Notification.DEFAULT_SOUND);
|
||||
}
|
||||
|
||||
if(isCancelDownload){
|
||||
Intent intent = new Intent(context, DownloadService.class);
|
||||
intent.putExtra(Constants.KEY_STOP_DOWNLOAD_SERVICE,true);
|
||||
PendingIntent deleteIntent = PendingIntent.getService(context, notifyId,intent, getPendingIntentFlags(PendingIntent.FLAG_CANCEL_CURRENT));
|
||||
builder.setDeleteIntent(deleteIntent);
|
||||
}
|
||||
|
||||
Notification notification = builder.build();
|
||||
if(isCancelDownload){
|
||||
notification.flags = Notification.FLAG_ONLY_ALERT_ONCE;
|
||||
}else{
|
||||
notification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONLY_ALERT_ONCE;
|
||||
}
|
||||
|
||||
notifyNotification(context,notifyId,notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示下载中的通知(更新进度)
|
||||
* @param notifyId
|
||||
* @param channelId
|
||||
* @param icon
|
||||
* @param title
|
||||
* @param content
|
||||
* @param progress
|
||||
* @param size
|
||||
*/
|
||||
public static void showProgressNotification(Context context, int notifyId,String channelId,@DrawableRes int icon,CharSequence title,CharSequence content,int progress,int size, boolean isCancelDownload){
|
||||
NotificationCompat.Builder builder = buildNotification(context,channelId,icon,title,content,progress,size);
|
||||
|
||||
if(isCancelDownload){
|
||||
Intent intent = new Intent(context, DownloadService.class);
|
||||
intent.putExtra(Constants.KEY_STOP_DOWNLOAD_SERVICE,true);
|
||||
PendingIntent deleteIntent = PendingIntent.getService(context, notifyId, intent, getPendingIntentFlags(PendingIntent.FLAG_CANCEL_CURRENT));
|
||||
builder.setDeleteIntent(deleteIntent);
|
||||
}
|
||||
|
||||
Notification notification = builder.build();
|
||||
|
||||
if(isCancelDownload){
|
||||
notification.flags = Notification.FLAG_ONLY_ALERT_ONCE;
|
||||
}else{
|
||||
notification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONLY_ALERT_ONCE;
|
||||
}
|
||||
|
||||
notifyNotification(context,notifyId,notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示下载完成时的通知(点击安装)
|
||||
* @param notifyId
|
||||
* @param channelId
|
||||
* @param icon
|
||||
* @param title
|
||||
* @param content
|
||||
* @param file
|
||||
*/
|
||||
public static void showFinishNotification(Context context, int notifyId, String channelId, @DrawableRes int icon, CharSequence title, CharSequence content, File file, String authority){
|
||||
cancelNotification(context,notifyId);
|
||||
NotificationCompat.Builder builder = buildNotification(context,channelId,icon,title,content);
|
||||
builder.setAutoCancel(true);
|
||||
Intent intent = AppUtils.getInstallIntent(context,file,authority);
|
||||
PendingIntent clickIntent = PendingIntent.getActivity(context, notifyId, intent, getPendingIntentFlags(PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
builder.setContentIntent(clickIntent);
|
||||
Notification notification = builder.build();
|
||||
notification.flags = Notification.FLAG_AUTO_CANCEL;
|
||||
notifyNotification(context,notifyId,notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* 现在下载失败通知
|
||||
* @param context
|
||||
* @param notifyId
|
||||
* @param channelId
|
||||
* @param icon
|
||||
* @param title
|
||||
* @param content
|
||||
* @param isReDownload
|
||||
* @param config
|
||||
*/
|
||||
public static void showErrorNotification(Context context, int notifyId, String channelId, @DrawableRes int icon, CharSequence title, CharSequence content, boolean isReDownload, UpdateConfig config){
|
||||
NotificationCompat.Builder builder = buildNotification(context,channelId,icon,title,content);
|
||||
builder.setAutoCancel(true);
|
||||
int flag = getPendingIntentFlags(PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
if(isReDownload){// 重新下载
|
||||
Intent intent = new Intent(context, DownloadService.class);
|
||||
intent.putExtra(Constants.KEY_RE_DOWNLOAD,true);
|
||||
intent.putExtra(Constants.KEY_UPDATE_CONFIG,config);
|
||||
PendingIntent clickIntent = PendingIntent.getService(context, notifyId,intent, flag);
|
||||
builder.setContentIntent(clickIntent);
|
||||
}else{
|
||||
PendingIntent clickIntent = PendingIntent.getService(context, notifyId, new Intent(), flag);
|
||||
builder.setContentIntent(clickIntent);
|
||||
}
|
||||
|
||||
Notification notification = builder.build();
|
||||
notification.flags = Notification.FLAG_AUTO_CANCEL;
|
||||
notifyNotification(context,notifyId,notification);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 显示通知信息(非第一次)
|
||||
* @param notifyId
|
||||
* @param channelId
|
||||
* @param icon
|
||||
* @param title
|
||||
* @param content
|
||||
*/
|
||||
public static void showNotification(Context context, int notifyId,String channelId,@DrawableRes int icon,CharSequence title,CharSequence content,boolean isAutoCancel){
|
||||
NotificationCompat.Builder builder = buildNotification(context,channelId,icon,title,content);
|
||||
builder.setAutoCancel(isAutoCancel);
|
||||
Notification notification = builder.build();
|
||||
notification.flags = Notification.FLAG_AUTO_CANCEL;
|
||||
notifyNotification(context,notifyId,notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消通知
|
||||
* @param notifyId
|
||||
*/
|
||||
public static void cancelNotification(Context context, int notifyId){
|
||||
getNotificationManager(context).cancel(notifyId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取通知管理器
|
||||
* @return
|
||||
*/
|
||||
public static NotificationManager getNotificationManager(Context context){
|
||||
return (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个通知渠道(兼容0以上版本)
|
||||
* @param channelId
|
||||
* @param channelName
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public static void createNotificationChannel(Context context, String channelId, String channelName,boolean isVibrate,boolean isSound){
|
||||
NotificationChannel channel = new NotificationChannel(channelId,channelName, NotificationManager.IMPORTANCE_HIGH);
|
||||
channel.enableVibration(isVibrate);
|
||||
if(!isSound){
|
||||
channel.setSound(null,null);
|
||||
}
|
||||
getNotificationManager(context).createNotificationChannel(channel);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个通知构建器
|
||||
* @param channelId
|
||||
* @param icon
|
||||
* @param title
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
private static NotificationCompat.Builder buildNotification(Context context, String channelId, @DrawableRes int icon,CharSequence title,CharSequence content){
|
||||
return buildNotification(context,channelId,icon,title,content,Constants.NONE,Constants.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个通知构建器
|
||||
* @param channelId
|
||||
* @param icon
|
||||
* @param title
|
||||
* @param content
|
||||
* @param progress
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
private static NotificationCompat.Builder buildNotification(Context context, String channelId, @DrawableRes int icon, CharSequence title, CharSequence content, int progress, int size){
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,channelId);
|
||||
builder.setSmallIcon(icon);
|
||||
|
||||
builder.setContentTitle(title);
|
||||
builder.setContentText(content);
|
||||
builder.setOngoing(true);
|
||||
|
||||
if(progress != Constants.NONE && size != Constants.NONE){
|
||||
builder.setProgress(size,progress,false);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新通知栏
|
||||
* @param id
|
||||
* @param notification
|
||||
*/
|
||||
private static void notifyNotification(Context context, int id, Notification notification){
|
||||
getNotificationManager(context).notify(id,notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 PendingIntent 的 flags
|
||||
* @param flag
|
||||
* @return
|
||||
*/
|
||||
private static int getPendingIntentFlags(int flag){
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return flag | PendingIntent.FLAG_IMMUTABLE;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package just.way.appdown.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public final class PermissionUtils {
|
||||
|
||||
private PermissionUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验权限
|
||||
*
|
||||
* @param activity
|
||||
* @param requestCode
|
||||
* @return
|
||||
*/
|
||||
public static boolean verifyReadAndWritePermissions(@NonNull Activity activity, int requestCode) {
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
|
||||
int readResult = checkPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||
int writeResult = checkPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
if (readResult != PackageManager.PERMISSION_GRANTED || writeResult != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(activity, new String[]{
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int checkPermission(@NonNull Activity activity, @NonNull String permission) {
|
||||
return ActivityCompat.checkSelfPermission(activity, permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取通知权限
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static boolean isNotificationEnabled(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (notificationManager.getImportance() == NotificationManager.IMPORTANCE_NONE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
String CHECK_OP_NO_THROW = "checkOpNoThrow";
|
||||
String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
|
||||
|
||||
AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||
ApplicationInfo appInfo = context.getApplicationInfo();
|
||||
String pkg = context.getApplicationContext().getPackageName();
|
||||
int uid = appInfo.uid;
|
||||
|
||||
try {
|
||||
Class appOpsClass = Class.forName(AppOpsManager.class.getName());
|
||||
Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class);
|
||||
Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
|
||||
|
||||
int value = (Integer) opPostNotificationValue.get(Integer.class);
|
||||
return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package just.way.appdown.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.RawRes;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public final class SSLSocketFactoryUtils {
|
||||
|
||||
private static final String[] VERIFY_HOST_NAME = new String[]{};
|
||||
|
||||
private SSLSocketFactoryUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static SSLSocketFactory createSSLSocketFactory() {
|
||||
SSLSocketFactory sslSocketFactory = null;
|
||||
try {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, getTrustAllManager(), new SecureRandom());
|
||||
sslSocketFactory = sslContext.getSocketFactory();
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
return sslSocketFactory;
|
||||
}
|
||||
|
||||
public static X509TrustManager createTrustAllManager() {
|
||||
X509TrustManager tm = null;
|
||||
try {
|
||||
tm = new X509TrustManager() {
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return tm;
|
||||
}
|
||||
|
||||
public static TrustAllHostnameVerifier createTrustAllHostnameVerifier() {
|
||||
return new TrustAllHostnameVerifier();
|
||||
}
|
||||
|
||||
public static class TrustAllHostnameVerifier implements HostnameVerifier {
|
||||
@Override
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
if (TextUtils.isEmpty(hostname)) {
|
||||
return false;
|
||||
}
|
||||
return !Arrays.asList(VERIFY_HOST_NAME).contains(hostname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @param keyServerStoreID
|
||||
* @return
|
||||
*/
|
||||
public static SSLSocketFactory createSSLSocketFactory(Context context, @RawRes int keyServerStoreID) {
|
||||
InputStream trustStream = context.getResources().openRawResource(keyServerStoreID);
|
||||
return createSSLSocketFactory(trustStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param certificates
|
||||
* @return
|
||||
*/
|
||||
public static SSLSocketFactory createSSLSocketFactory(InputStream... certificates) {
|
||||
SSLSocketFactory sSLSocketFactory = null;
|
||||
if (sSLSocketFactory == null) {
|
||||
synchronized (SSLSocketFactoryUtils.class) {
|
||||
if (sSLSocketFactory == null) {
|
||||
try {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, getTrustManager(certificates), new SecureRandom());
|
||||
sSLSocketFactory = sslContext.getSocketFactory();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sSLSocketFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定流中的服务器端证书库
|
||||
*
|
||||
* @param certificates
|
||||
* @return
|
||||
*/
|
||||
public static TrustManager[] getTrustManager(InputStream... certificates) {
|
||||
try {
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(null, null);
|
||||
int index = 0;
|
||||
for (InputStream certificate : certificates) {
|
||||
if (certificate == null) {
|
||||
continue;
|
||||
}
|
||||
Certificate certificate1;
|
||||
try {
|
||||
certificate1 = certificateFactory.generateCertificate(certificate);
|
||||
} finally {
|
||||
certificate.close();
|
||||
}
|
||||
|
||||
String certificateAlias = Integer.toString(index++);
|
||||
keyStore.setCertificateEntry(certificateAlias, certificate1);
|
||||
}
|
||||
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory
|
||||
.getDefaultAlgorithm());
|
||||
|
||||
trustManagerFactory.init(keyStore);
|
||||
return trustManagerFactory.getTrustManagers();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
|
||||
return getTrustAllManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得信任所有服务器端证书库
|
||||
*/
|
||||
public static TrustManager[] getTrustAllManager() {
|
||||
return new TrustManager[]{createTrustAllManager()};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
11
winwaynew/src/main/res/drawable-anydpi/ic_action_back.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.8">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
|
||||
</vector>
|
||||
BIN
winwaynew/src/main/res/drawable-hdpi/ic_action_back.png
Normal file
|
After Width: | Height: | Size: 182 B |
BIN
winwaynew/src/main/res/drawable-mdpi/ic_action_back.png
Normal file
|
After Width: | Height: | Size: 150 B |
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
BIN
winwaynew/src/main/res/drawable-xhdpi/ic_action_back.png
Normal file
|
After Width: | Height: | Size: 212 B |
BIN
winwaynew/src/main/res/drawable-xxhdpi/ic_action_back.png
Normal file
|
After Width: | Height: | Size: 324 B |
BIN
winwaynew/src/main/res/drawable-xxhdpi/index_log.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
170
winwaynew/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
28
winwaynew/src/main/res/drawable/pass_word_bg.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:color="@color/white"
|
||||
tools:ignore="NewApi">
|
||||
<item android:id="@android:id/mask"
|
||||
tools:ignore="NewApi">
|
||||
<shape>
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<corners android:radius="5dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<!-- 默认显⽰效果-->
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="180"
|
||||
android:startColor="@android:color/transparent"
|
||||
android:endColor="@android:color/transparent"
|
||||
android:type="linear"
|
||||
android:useLevel="true" />
|
||||
<stroke android:width="1dp" android:color="#333333"/>
|
||||
<corners
|
||||
android:radius="5dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
|
||||
23
winwaynew/src/main/res/drawable/pass_word_bg1.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animated-rotate
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fromDegrees="0"
|
||||
android:toDegrees="360"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
>
|
||||
<shape
|
||||
android:shape="ring"
|
||||
android:innerRadiusRatio="3"
|
||||
android:thicknessRatio="8"
|
||||
android:useLevel="false"
|
||||
>
|
||||
<gradient
|
||||
android:type="sweep"
|
||||
android:useLevel="false"
|
||||
android:startColor="#FF0000"
|
||||
android:centerColor="#FF5555"
|
||||
android:endColor="#FBD3D0"
|
||||
android:centerY="0.50" />
|
||||
</shape>
|
||||
</animated-rotate>
|
||||
23
winwaynew/src/main/res/drawable/pass_word_bg2.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animated-rotate
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fromDegrees="0"
|
||||
android:toDegrees="360"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
>
|
||||
<shape
|
||||
android:shape="ring"
|
||||
android:innerRadiusRatio="3"
|
||||
android:thicknessRatio="8"
|
||||
android:useLevel="false"
|
||||
>
|
||||
<gradient
|
||||
android:type="sweep"
|
||||
android:useLevel="false"
|
||||
android:startColor="#000000"
|
||||
android:centerColor="#888888"
|
||||
android:endColor="#FFFFFF"
|
||||
android:centerY="0.50" />
|
||||
</shape>
|
||||
</animated-rotate>
|
||||
5
winwaynew/src/main/res/drawable/shape_dialog_bg_new.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<corners android:radius="20dp" />
|
||||
<solid android:color="@color/white" />
|
||||
</shape>
|
||||
351
winwaynew/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,351 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".MainActivity"
|
||||
android:background="@color/white"
|
||||
android:id="@+id/homePage">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/big_v"
|
||||
android:visibility="visible"
|
||||
android:background="@android:color/transparent"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/inputText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="6"
|
||||
android:padding="10dp"
|
||||
android:textSize="40dp"
|
||||
android:textColor="@color/black"
|
||||
android:gravity="center_vertical" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/outputText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:gravity="end"
|
||||
android:textColor="@color/black"
|
||||
android:textAlignment="textEnd"
|
||||
android:autoSizeTextType="uniform"
|
||||
android:textSize="80dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/allBtn"
|
||||
android:layout_weight="3"
|
||||
android:background="#EEEEEE"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="AC"
|
||||
android:textSize="35dp"
|
||||
android:textColor="#e67e22"
|
||||
android:id="@+id/btn_clear"
|
||||
>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="←"
|
||||
android:textSize="35dp"
|
||||
android:textColor="#e67e22"
|
||||
android:id="@+id/btn_backspace"
|
||||
>
|
||||
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="3"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="÷"
|
||||
android:textSize="35dp"
|
||||
android:textColor="#e67e22"
|
||||
android:id="@+id/btn_divide"
|
||||
>
|
||||
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:id="@+id/btn_7"
|
||||
android:text="7"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:id="@+id/btn_8"
|
||||
android:text="8"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:id="@+id/btn_9"
|
||||
android:text="9"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="×"
|
||||
android:textSize="35dp"
|
||||
android:textColor="#e67e22"
|
||||
android:id="@+id/btn_multiply"
|
||||
>
|
||||
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="4"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_4"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="5"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_5"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="6"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_6"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="-"
|
||||
android:textSize="35dp"
|
||||
android:textColor="#e67e22"
|
||||
android:id="@+id/btn_subtract"
|
||||
>
|
||||
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
|
||||
|
||||
>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="1"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_1"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="2"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_2"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="3"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_3"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="+"
|
||||
android:textSize="35dp"
|
||||
android:textColor="#e67e22"
|
||||
android:id="@+id/btn_add"
|
||||
>
|
||||
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fiveLow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
|
||||
|
||||
>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text=""
|
||||
android:textSize="35dp"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="0"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_0"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="."
|
||||
android:textColor="@color/black"
|
||||
android:textSize="35dp"
|
||||
android:id="@+id/btn_point"
|
||||
>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="="
|
||||
android:textSize="35dp"
|
||||
android:textColor="#e67e22"
|
||||
android:id="@+id/btn_equal"
|
||||
>
|
||||
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
138
winwaynew/src/main/res/layout/activity_main2.xml
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<just.way.StatusLayout
|
||||
android:id="@+id/top_vvvv1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/top_vvvv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_below="@id/top_vvvv1"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_iv"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_action_back" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@mipmap/index_log1" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<com.tencent.smtt.sdk.WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutError"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_error"
|
||||
style="@android:style/Widget.ProgressBar.Large"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/agentweb_loading" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errormsg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:textColor="#999999"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/show_top_ly"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:gravity="center">
|
||||
|
||||
<just.way.CircleImageView
|
||||
android:id="@+id/show_top_v"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@mipmap/winway"
|
||||
android:visibility="visible"
|
||||
app:ease_border_color="#EEEEEE"
|
||||
app:ease_border_width="1dp"
|
||||
app:es_shape_type="round" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="6"
|
||||
android:gravity="center">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg1" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/videoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressbar"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg2"
|
||||
android:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
138
winwaynew/src/main/res/layout/activity_main22.xml
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<just.way.StatusLayout
|
||||
android:id="@+id/top_vvvv1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/top_vvvv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_below="@id/top_vvvv1"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_iv"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_action_back" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@mipmap/index_log1" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<com.tencent.smtt.sdk.WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutError"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_error"
|
||||
style="@android:style/Widget.ProgressBar.Large"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/agentweb_loading" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errormsg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:textColor="#999999"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/show_top_ly"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:gravity="center">
|
||||
|
||||
<just.way.CircleImageView
|
||||
android:id="@+id/show_top_v"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@mipmap/winway"
|
||||
android:visibility="visible"
|
||||
app:ease_border_color="#EEEEEE"
|
||||
app:ease_border_width="1dp"
|
||||
app:es_shape_type="round" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="6"
|
||||
android:gravity="center">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg1" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/videoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressbar"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg2"
|
||||
android:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
108
winwaynew/src/main/res/layout/activity_main3.xml
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<just.way.StatusLayout
|
||||
android:id="@+id/top_vvvv1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/top_vvvv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_below="@id/top_vvvv1"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_iv"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_action_back" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@mipmap/index_log1" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_below="@id/top_vvvv" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/show_top_ly"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:gravity="center">
|
||||
|
||||
<just.way.CircleImageView
|
||||
android:id="@+id/show_top_v"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@mipmap/winway"
|
||||
android:visibility="visible"
|
||||
app:ease_border_color="#EEEEEE"
|
||||
app:ease_border_width="1dp"
|
||||
app:es_shape_type="round" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="6"
|
||||
android:gravity="center">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg1"
|
||||
android:layout_centerHorizontal="true" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/videoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<ProgressBar
|
||||
android:id="@+id/progressbar"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg2"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
95
winwaynew/src/main/res/layout/activity_notifydetails.xml
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/top_vvvv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="@color/white"
|
||||
android:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_iv"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_action_back" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@mipmap/jisuanqi_logo" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/top_vvvv"
|
||||
android:visibility="gone"
|
||||
android:background="@mipmap/jisuanqi_logo" />
|
||||
|
||||
<com.tencent.smtt.sdk.WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"
|
||||
android:visibility="gone" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/show_top_ly"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:gravity="center">
|
||||
|
||||
<just.way.CircleImageView
|
||||
android:id="@+id/show_top_v"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@mipmap/jisuanqi_logo"
|
||||
android:visibility="visible"
|
||||
app:ease_border_color="#EEEEEE"
|
||||
app:ease_border_width="1dp"
|
||||
app:es_shape_type="round" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="6"
|
||||
android:gravity="center">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg1" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
294
winwaynew/src/main/res/layout/activity_start.xml
Normal file
@@ -0,0 +1,294 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/homePage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/white"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:layout_weight="6">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#333333"
|
||||
android:text="@string/qsrlwmm_txt"
|
||||
android:textSize="20dp">
|
||||
|
||||
</TextView>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:background="@drawable/pass_word_bg"
|
||||
android:id="@+id/password_1"/>
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:background="@drawable/pass_word_bg"
|
||||
android:id="@+id/password_2"/>
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:background="@drawable/pass_word_bg"
|
||||
android:id="@+id/password_3"/>
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:background="@drawable/pass_word_bg"
|
||||
android:id="@+id/password_4"/>
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:background="@drawable/pass_word_bg"
|
||||
android:id="@+id/password_5"/>
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:background="@drawable/pass_word_bg"
|
||||
android:id="@+id/password_6"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/allBtn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#EEEEEE"
|
||||
android:layout_weight="4"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_7"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="7"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_8"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="8"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_9"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="9"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_4"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="4"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_5"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="5"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_6"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="6"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
|
||||
|
||||
>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="1"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="2"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="3"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fiveLow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
|
||||
|
||||
>
|
||||
|
||||
<Button
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text=""
|
||||
android:textColor="#e67e22"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_0"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="0"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_equal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="DEL"
|
||||
android:textColor="#e67e22"
|
||||
android:textSize="25dp">
|
||||
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
108
winwaynew/src/main/res/layout/activity_webview.xml
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<just.way.StatusLayout
|
||||
android:id="@+id/top_vvvv1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/top_vvvv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_below="@id/top_vvvv1"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_iv"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_action_back" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@mipmap/index_log1" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
|
||||
<com.tencent.smtt.sdk.WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/show_top_ly"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_vvvv"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:gravity="center">
|
||||
|
||||
<just.way.CircleImageView
|
||||
android:id="@+id/show_top_v"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@mipmap/winway"
|
||||
android:visibility="visible"
|
||||
app:ease_border_color="#EEEEEE"
|
||||
app:ease_border_width="1dp"
|
||||
app:es_shape_type="round" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="6"
|
||||
android:gravity="center">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg1"
|
||||
android:layout_centerHorizontal="true" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/videoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<ProgressBar
|
||||
android:id="@+id/progressbar"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:indeterminateDrawable="@drawable/pass_word_bg2"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
73
winwaynew/src/main/res/layout/dialog_action_confirm.xml
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="285dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="144dp"
|
||||
android:background="@drawable/shape_dialog_bg_new"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="245dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:lineSpacingExtra="4dp"
|
||||
android:gravity="center"
|
||||
android:id="@+id/content_tv"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="1111111111"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="#D8D8D8"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="62dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/cancel_tv"
|
||||
android:text="@string/cancel_txt"
|
||||
android:gravity="center"
|
||||
android:textColor="#e44f3e"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
<View android:layout_width="1dp"
|
||||
android:id="@+id/line_v"
|
||||
android:layout_height="42dp"
|
||||
android:background="#d8d8d8"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/sumbit_tv"
|
||||
android:text="@string/sure_txt"
|
||||
android:gravity="center"
|
||||
android:textColor="#6b3689"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
5
winwaynew/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
winwaynew/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
winwaynew/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
winwaynew/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
winwaynew/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
winwaynew/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
winwaynew/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
winwaynew/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
winwaynew/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
winwaynew/src/main/res/mipmap-xxhdpi/jisuanqi_logo.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
winwaynew/src/main/res/mipmap-xxhdpi/winway.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
winwaynew/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
winwaynew/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
winwaynew/src/main/res/mipmap-xxxhdpi/index_log1.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
5
winwaynew/src/main/res/values-en-rMY/strings.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">kalkulator</string>
|
||||
<string name="app_name1">WINWAY</string>
|
||||
<string name="qsrlwmm_txt">Sila Set Password Kamu</string>
|
||||
</resources>
|
||||
25
winwaynew/src/main/res/values-en/strings.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<resources>
|
||||
<string name="app_name">Calculator</string>
|
||||
<string name="app_name1">WINWAY</string>
|
||||
<string name="qsrlwmm_txt">Please Set Your Password</string>
|
||||
<string name="cancel_txt">Cancel</string>
|
||||
<string name="sure_txt">Sure</string>
|
||||
<string name="banbengengxin_txt">New Version Update</string>
|
||||
<string name="xiacigengxin_txt">Next Update</string>
|
||||
<string name="lijigengxin_txt">Update Immediately</string>
|
||||
<string name="app_updater_error_notification_content">点击关闭通知</string>
|
||||
<string name="app_updater_error_notification_content_re_download">点击重新下载</string>
|
||||
<string name="app_updater_error_notification_title">下载失败</string>
|
||||
<string name="app_updater_finish_notification_content">点击安装</string>
|
||||
<string name="app_updater_finish_notification_title">下载完成</string>
|
||||
<string name="app_updater_progress_notification_content">正在下载…</string>
|
||||
<string name="app_updater_progress_notification_title">版本更新</string>
|
||||
<string name="app_updater_progress_notification_title_2">下载游戏中</string>
|
||||
<string name="app_updater_start_notification_content">正在获取下载数据…</string>
|
||||
<string name="app_updater_start_notification_title">版本更新</string>
|
||||
<string name="app_updater_start_notification_title_2">下载游戏中</string>
|
||||
<string name="notification_title_txt">Need to turn on mobile phone notification permission</string>
|
||||
<string name="notification_cancel_txt">Cancel</string>
|
||||
<string name="notification_setting_txt">Setting</string>
|
||||
|
||||
</resources>
|
||||
5
winwaynew/src/main/res/values-myn/strings.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">kalkulator</string>
|
||||
<string name="app_name1">WINWAY</string>
|
||||
<string name="qsrlwmm_txt">Sila Set Password Kamu</string>
|
||||
</resources>
|
||||
69
winwaynew/src/main/res/values-night/themes.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Calculcator" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
<style name="Theme.Calculcator1" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<declare-styleable name="CircleImageView">
|
||||
<attr name="ease_border_color" format="color" />
|
||||
<attr name="ease_border_width" format="dimension" />
|
||||
<attr name="ease_press_alpha" format="integer" />
|
||||
<attr name="ease_press_color" format="color" />
|
||||
<attr name="ease_radius" format="dimension" />
|
||||
<attr name="es_shape_type" format="enum">
|
||||
<enum name="none" value="0" />
|
||||
<enum name="round" value="1" />
|
||||
<enum name="rectangle" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<!-- 注意:当前AppTheme主题,在values-v23中单独重复维护。原因是Android 6以下系统不支持设置
|
||||
系统状态栏颜色,如果按照设计,状态栏使用素色则在android6以下手机上就看不清系统状态栏文字了(
|
||||
因为系统文字是白色)。在values-v23表示当Android 23(即android 6)及以上版本将自动使用该目录
|
||||
下的主题(即 colorPrimaryDark 使用素色,从而跟标题栏颜色保持一致,实现沉浸式ui效果)。-->
|
||||
<style name="AppThemeStart" parent="@style/Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:windowTranslucentStatus">false</item>
|
||||
<item name="android:windowTranslucentNavigation">false</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="colorPrimary">@color/white</item>
|
||||
<item name="colorPrimaryDark">@color/white</item>
|
||||
<item name="colorAccent">@color/white</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<!-- 隐藏Activity窗口的Title标题栏 -->
|
||||
<item name="windowNoTitle">true</item>
|
||||
<!-- <item name="android:windowFullscreen">true</item>-->
|
||||
<!-- <item name="android:windowBackground">@drawable/splah_bg</item>-->
|
||||
<item name="android:windowBackground">@color/white</item>
|
||||
|
||||
<item name="android:navigationBarColor">@color/white</item>
|
||||
<!-- <item name="android:windowBackground">@mipmap/big_bg</item>-->
|
||||
<item name="android:forceDarkAllowed" tools:ignore="NewApi">false</item>
|
||||
</style>
|
||||
</resources>
|
||||
13
winwaynew/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFFFFF</color>
|
||||
<color name="purple_500">#FFFFFF</color>
|
||||
<color name="purple_700">#FFFFFF</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="jisuanqi">#EF4723</color>
|
||||
<color name="winway">#FFFFFF</color>
|
||||
|
||||
</resources>
|
||||
24
winwaynew/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<resources>
|
||||
<string name="app_name">计算器</string>
|
||||
<string name="app_name1">WINWAY</string>
|
||||
<string name="qsrlwmm_txt">请输入6位密码</string>
|
||||
<string name="cancel_txt">取消</string>
|
||||
<string name="sure_txt">确定</string>
|
||||
<string name="banbengengxin_txt">版本更新</string>
|
||||
<string name="xiacigengxin_txt">下次更新</string>
|
||||
<string name="lijigengxin_txt">立即更新</string>
|
||||
<string name="app_updater_error_notification_content">点击关闭通知</string>
|
||||
<string name="app_updater_error_notification_content_re_download">点击重新下载</string>
|
||||
<string name="app_updater_error_notification_title">下载失败</string>
|
||||
<string name="app_updater_finish_notification_content">点击安装</string>
|
||||
<string name="app_updater_finish_notification_title">下载完成</string>
|
||||
<string name="app_updater_progress_notification_content">正在下载…</string>
|
||||
<string name="app_updater_progress_notification_title">版本更新</string>
|
||||
<string name="app_updater_progress_notification_title_2">下载游戏中</string>
|
||||
<string name="app_updater_start_notification_title">版本更新</string>
|
||||
<string name="app_updater_start_notification_title_2">下载游戏中</string>
|
||||
<string name="app_updater_start_notification_content">正在获取下载数据…</string>
|
||||
<string name="notification_title_txt">需要打开手机通知权限</string>
|
||||
<string name="notification_cancel_txt">取消</string>
|
||||
<string name="notification_setting_txt">设置</string>
|
||||
</resources>
|
||||
88
winwaynew/src/main/res/values/themes.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Calculcator" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.Calculcator1" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
|
||||
<declare-styleable name="CircleImageView">
|
||||
<attr name="ease_border_color" format="color" />
|
||||
<attr name="ease_border_width" format="dimension" />
|
||||
<attr name="ease_press_alpha" format="integer" />
|
||||
<attr name="ease_press_color" format="color" />
|
||||
<attr name="ease_radius" format="dimension" />
|
||||
<attr name="es_shape_type" format="enum">
|
||||
<enum name="none" value="0" />
|
||||
<enum name="round" value="1" />
|
||||
<enum name="rectangle" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<!-- 注意:当前AppTheme主题,在values-v23中单独重复维护。原因是Android 6以下系统不支持设置
|
||||
系统状态栏颜色,如果按照设计,状态栏使用素色则在android6以下手机上就看不清系统状态栏文字了(
|
||||
因为系统文字是白色)。在values-v23表示当Android 23(即android 6)及以上版本将自动使用该目录
|
||||
下的主题(即 colorPrimaryDark 使用素色,从而跟标题栏颜色保持一致,实现沉浸式ui效果)。-->
|
||||
<style name="AppThemeStart" parent="@style/Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:windowTranslucentStatus">false</item>
|
||||
<item name="android:windowTranslucentNavigation">false</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="colorPrimary">@color/white</item>
|
||||
<item name="colorPrimaryDark">@color/white</item>
|
||||
<item name="colorAccent">@color/white</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<!-- 隐藏Activity窗口的Title标题栏 -->
|
||||
<item name="windowNoTitle">true</item>
|
||||
<!-- <item name="android:windowFullscreen">true</item>-->
|
||||
<!-- <item name="android:windowBackground">@drawable/splah_bg</item>-->
|
||||
<item name="android:windowBackground">@color/white</item>
|
||||
|
||||
<item name="android:navigationBarColor">@color/white</item>
|
||||
<!-- <item name="android:windowBackground">@mipmap/big_bg</item>-->
|
||||
<item name="android:forceDarkAllowed" tools:ignore="NewApi">false</item>
|
||||
</style>
|
||||
|
||||
<style name="MaterialDesignDialog" parent="@style/Theme.AppCompat.Dialog">
|
||||
<!-- 背景透明 -->
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<!-- 浮于Activity之上 -->
|
||||
<item name="android:windowIsFloating">true</item>
|
||||
<!-- 边框 -->
|
||||
<item name="android:windowFrame">@null</item>
|
||||
<!-- Dialog以外的区域模糊效果 -->
|
||||
<item name="android:backgroundDimEnabled">true</item>
|
||||
<!-- 无标题 -->
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<!-- 半透明 -->
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowCloseOnTouchOutside">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
10
winwaynew/src/main/res/xml/app_updater_paths.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<root-path name="app_root_path" path="/"/>
|
||||
<external-path name="app_external_path" path="/"/>
|
||||
<external-cache-path name="app_external_cache_path" path="/"/>
|
||||
<external-files-path name="app_external_files_path" path="/"/>
|
||||
<files-path name="app_files_path" path="/"/>
|
||||
<cache-path name="app_cache_path" path="/"/>
|
||||
|
||||
</paths>
|
||||
4
winwaynew/src/main/res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
</network-security-config>
|
||||
13
winwaynew/src/main/res/xml/provider_paths.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding= "utf-8"?>
|
||||
<resources>
|
||||
<paths >
|
||||
<external-path name="external_files" path="."/>
|
||||
<root-path name="root" path="." />
|
||||
<files-path name="files" path="." />
|
||||
<cache-path name="cache" path="." />
|
||||
<external-files-path name="external_files_f" path="." />
|
||||
<external-cache-path name="external_cache" path="." />
|
||||
</paths >
|
||||
</resources>
|
||||
<!-- 适配7.0及其以上,配合com.eva.android.OpenFileUtil,用于解决调用系统Intent查看大文件内
|
||||
容、拍照保存图片的功能时出现"android.os.FileUriExposedException"异常的问题 -->
|
||||
@@ -0,0 +1,35 @@
|
||||
package Tptogiar.calculcator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestPattern(){
|
||||
//
|
||||
Pattern compile = Pattern.compile( "^(\\-|\\+)?\\d+(\\.\\d+)?$");
|
||||
String a="+45.5";
|
||||
boolean matches = compile.matcher(a).matches();
|
||||
System.out.println(matches);
|
||||
String result = compile.matcher(a).replaceAll("");
|
||||
System.out.println(result);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||