Commit 068dc478 authored by sheteng's avatar sheteng

加入模块app

parent 8538bd00
/build
\ No newline at end of file
plugins {
id("com.android.application")
id("kotlin-android")
id("kotlin-kapt")
id("kotlin-parcelize")
}
android {
signingConfigs {
register("config") {
keyAlias = "ccim"
keyPassword = "123456"
storeFile = file("ccim_game_accelerator.jks")
storePassword = "123456"
}
}
// compileSdk 30
// defaultConfig {
// applicationId = "com.ccwangluo.accelerator"
// minSdk 21
// targetSdk 30
// versionCode = 1
// versionName = "1.0"
// testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// javaCompileOptions {
// annotationProcessor(Options {)
// arguments = listOf( moduleName : project.getName() )
// }
// }
// manifestPlaceholders = listOf(qqappid = "你的qq appid")
// }
// buildTypes {
// named("release"){
// signingConfig = signingConfigs.getByName("config")
// isMinifyEnabled = false
// setProguardFiles(listOf(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"))
// buildConfigField "String", "BASE_URL", "\"http://10.16.1.98:9002/api(\"")
// }
// named("debug"){
// signingConfig = signingConfigs.getByName("config")
// isMinifyEnabled = false
// buildConfigField "String", "BASE_URL", "\"http://10.16.1.98:9002/api(\"")
// }
// }
// compileOptions {
// sourceCompatibility = JavaVersion.VERSION_1_8
// targetCompatibility = JavaVersion.VERSION_1_8
// }
// kotlinOptions {
// jvmTarget = "1.8"
// }
}
setupApp()
android.defaultConfig.applicationId = "com.ccwangluo.accelerator"
android.buildFeatures.viewBinding = true
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
implementation("androidx.appcompat:appcompat:1.3.1")
implementation("com.google.android.material:material:1.4.0")
implementation("androidx.annotation:annotation:1.2.0")
implementation("androidx.vectordrawable:vectordrawable:1.1.0")
implementation("androidx.legacy:legacy-support-v4:1.0.0")
implementation("androidx.recyclerview:recyclerview:1.2.0")
implementation("androidx.navigation:navigation-fragment-ktx:2.3.0")
implementation("androidx.navigation:navigation-ui-ktx:2.3.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.3")
val multidex_version = "2.0.1"
implementation("androidx.multidex:multidex:$multidex_version")
val lifecycle_version = "2.3.1"
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0")
implementation("androidx.recyclerview:recyclerview:1.2.1")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
implementation("com.github.bumptech.glide:glide:4.12.0")
implementation("com.squareup.okhttp3:okhttp:4.9.0")
implementation("com.google.code.gson:gson:2.8.7")
implementation("com.github.xuexiangjys:XUI:1.1.8")
implementation("com.karumi:dexter:6.2.3")
//工具类
implementation("com.github.xuexiangjys.XUtil:xutil-core:2.0.0")
implementation("com.github.xuexiangjys.XUtil:xutil-sub:2.0.0")
implementation("com.tencent:mmkv:1.2.10")
//XPage
implementation("com.github.xuexiangjys.XPage:xpage-lib:3.3.0")
kapt("com.github.xuexiangjys.XPage:xpage-compiler:3.3.0")
implementation("com.github.getActivity:ToastUtils:10.3")
implementation("com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.0")
implementation("com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.0")
implementation("com.github.xuexiangjys.AgentWeb:agentweb-filechooser:1.0.0")
// 友盟基础组件库(所有友盟业务SDK都依赖基础组件库)
implementation("com.umeng.umsdk:common:9.4.7")// (必选))
implementation("com.umeng.umsdk:asms:1.5.0")// 必选)
implementation("com.umeng.umsdk:share-core:7.1.7")//分享核心库,必选)
implementation("com.umeng.umsdk:share-board:7.1.7")//分享面板功能,可选)
//在线依赖目前支持QQ、微信、新浪微博、支付宝、钉钉;若需支持其他平台,请选择手动下载SDK
implementation("com.umeng.umsdk:share-wx:7.1.7") //微信完整版)
implementation("com.tencent.mm.opensdk:wechat-sdk-android-without-mta:6.7.9")
//
// implementation("com.umeng.umsdk:share-qq:7.1.7")//QQ完整版)
// implementation("com.squareup.okhttp3:okhttp:3.14.9")//QQ官方sdk 3.53及之后版本需要集成okhttp3.x,必选)
}
\ No newline at end of file
# 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 com.cmic.sso.sdk.**
-dontwarn com.unikuwei.mianmi.account.shield.**
-dontwarn com.sdk.**
-keep class com.cmic.sso.sdk.**{*;}
-keep class com.sdk.** { *;}
-keep class com.unikuwei.mianmi.account.shield.** {*;}
-keep class cn.com.chinatelecom.account.api.**{*;}
-keep class com.xuexiang.xui.widget.edittext.materialedittext.** { *; }
# gson
-keepattributes Signature
-keepattributes *Annotation*
-dontwarn sun.misc.**
-keep class com.google.gson.examples.android.model.** { <fields>; }
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
# xpage
-keep class com.xuexiang.xpage.annotation.** { *; }
-keep class com.xuexiang.xpage.config.** { *; }
-keep class com.just.agentweb.** {
*;
}
-dontwarn com.just.agentweb.**
-dontshrink
-dontoptimize
-dontwarn com.google.android.maps.**
-dontwarn com.squareup.okhttp.**
-dontwarn android.webkit.WebView
-dontwarn com.umeng.**
-dontwarn com.tencent.weibo.sdk.**
-dontwarn com.facebook.**
-keep public class javax.**
-keep public class android.webkit.**
-dontwarn android.support.v4.**
-keep enum com.facebook.**
-keepattributes Exceptions,InnerClasses,Signature
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keepattributes EnclosingMethod
-keep public interface com.facebook.**
-keep public interface com.tencent.**
-keep public interface com.umeng.socialize.**
-keep public interface com.umeng.socialize.sensor.**
-keep public interface com.umeng.scrshot.**
-keep public class com.umeng.socialize.* {*;}
-keep class com.umeng.commonsdk.statistics.common.MLog {*;}
-keep class com.umeng.commonsdk.UMConfigure {*;}
-keep class com.umeng.** {*;}
-keep class com.umeng.**
-keep class com.facebook.**
-keep class com.facebook.** { *; }
-keep class com.umeng.scrshot.**
-keep public class com.tencent.** {*;}
-keep class com.umeng.socialize.sensor.**
-keep class com.umeng.socialize.handler.**
-keep class com.umeng.socialize.handler.*
-keep class com.umeng.weixin.handler.**
-keep class com.umeng.weixin.handler.*
-keep class com.umeng.qq.handler.**
-keep class com.umeng.qq.handler.*
-keep class UMMoreHandler{*;}
-keep class com.tencent.mm.sdk.modelmsg.WXMediaMessage {*;}
-keep class com.tencent.mm.sdk.modelmsg.** implements com.tencent.mm.sdk.modelmsg.WXMediaMessage$IMediaObject {*;}
-keep class im.yixin.sdk.api.YXMessage {*;}
-keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YXMessageData{*;}
-keep class com.tencent.mm.sdk.** {
*;
}
-keep class com.tencent.mm.opensdk.** {
*;
}
-keep class com.tencent.wxop.** {
*;
}
-keep class com.tencent.mm.sdk.** {
*;
}
-dontwarn twitter4j.**
-keep class twitter4j.** { *; }
-keep class com.tencent.** {*;}
-dontwarn com.tencent.**
-keep class com.kakao.** {*;}
-dontwarn com.kakao.**
-keep public class com.umeng.com.umeng.soexample.R$*{
public static final int *;
}
-keep public class com.linkedin.android.mobilesdk.R$*{
public static final int *;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class com.tencent.open.TDialog$*
-keep class com.tencent.open.TDialog$* {*;}
-keep class com.tencent.open.PKDialog
-keep class com.tencent.open.PKDialog {*;}
-keep class com.tencent.open.PKDialog$*
-keep class com.tencent.open.PKDialog$* {*;}
-keep class com.umeng.socialize.impl.ImageImpl {*;}
-keep class com.sina.** {*;}
-dontwarn com.sina.**
-keep class com.alipay.share.sdk.** {
*;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
-keep class com.linkedin.** { *; }
-keep class com.android.dingtalk.share.ddsharemodule.** { *; }
-keepattributes Signature
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ccwangluo.accelerator">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<queries>
<package android:name="com.tencent.mm" />
<package android:name="com.tencent.mobileqq" />
</queries>
<application
android:name=".App"
android:allowBackup="true"
android:usesCleartextTraffic="true"
android:icon="@mipmap/tt_logo"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ui.MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".wxapi.WXEntryActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
<!-- <provider-->
<!-- android:name="android.support.v4.content.FileProvider"-->
<!-- android:authorities="com.ccwangluo.accelerator.fileprovider"-->
<!-- android:exported="false"-->
<!-- android:grantUriPermissions="true">-->
<!-- <meta-data-->
<!-- android:name="android.support.FILE_PROVIDER_PATHS"-->
<!-- android:resource="@xml/filepaths"/>-->
<!-- </provider>-->
<activity
android:name="com.tencent.tauth.AuthActivity"
android:noHistory="true"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="1212121" />
</intent-filter>
</activity>
<activity
android:name="com.tencent.connect.common.AssistActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="behind"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<!-- <provider-->
<!-- android:authorities="${applicationId}.fileprovider"-->
<!-- android:name="android.support.v4.content.FileProvider"-->
<!-- android:exported="false"-->
<!-- android:grantUriPermissions="true"-->
<!-- >-->
<!-- <meta-data-->
<!-- android:name="android.support.FILE_PROVIDER_PATHS"-->
<!-- android:resource="@xml/filepaths"/>-->
<!-- </provider>-->
<activity
android:name="com.chuanglan.shanyan_sdk.view.CmccLoginActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:screenOrientation="behind"
/>
<activity-alias
android:name="com.cmic.sso.sdk.view.LoginAuthActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:screenOrientation="behind"
android:targetActivity="com.chuanglan.shanyan_sdk.view.CmccLoginActivity"
/>
<activity
android:name="com.chuanglan.shanyan_sdk.view.ShanYanOneKeyActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:screenOrientation="behind"
/>
<activity
android:name="com.chuanglan.shanyan_sdk.view.CTCCPrivacyProtocolActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:screenOrientation="behind"
/>
</application>
</manifest>
\ No newline at end of file
package com.ccwangluo.accelerator
import android.app.Application
import android.content.Context
import android.content.res.Configuration
import androidx.multidex.MultiDex
import com.ccwangluo.accelerator.ui.MainActivity
import com.ccwangluo.accelerator.utils.PhoneUtils
import com.github.shadowsocks.Core
import com.hjq.toast.ToastUtils
import com.xuexiang.xpage.PageConfig
import com.xuexiang.xpage.base.XPageActivity
class App : Application(), androidx.work.Configuration.Provider by Core {
override fun onCreate() {
super.onCreate()
PageConfig.getInstance() // //页面注册,默认不设置的话使用的就是自动注册
// .setPageConfiguration(new AutoPageConfiguration())
.debug("PageLog") //开启调试
.setContainActivityClazz(XPageActivity::class.java) //设置默认的容器Activity
.init(this)
PhoneUtils.initSdk(this)
// 初始化 Toast 框架
ToastUtils.init(this)
// UMConfigure.preInit()
MultiDex.install(this)
Core.init(this, MainActivity::class)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
Core.updateNotificationChannels()
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
/**
* actor 晴天 create 2019/5/17
* 封装一个kotlin下的通用adapter
*/
class KotlinDataAdapter<T> private constructor() : RecyclerView.Adapter<KotlinDataAdapter<T>.MyViewHolder>() {
//数据
private var mDatalist: ArrayList<T>? = null
//布局id
private var mLayoutId: Int? = null
//绑定事件的lambda放发
private var addBindView: ((itemView: View, itemData: T) -> Unit)? = null
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): MyViewHolder {
val view = LayoutInflater.from(p0.context).inflate(mLayoutId!!, p0, false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return mDatalist?.size ?: -1 //左侧为null时返回-1
}
override fun onBindViewHolder(p0: MyViewHolder, p1: Int) {
addBindView?.invoke(p0.itemView, mDatalist?.get(p1)!!)
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
/**
* 建造者,用来完成adapter的数据组合
*/
class Builder<B> {
private var adapter: KotlinDataAdapter<B> = KotlinDataAdapter()
/**
* 设置数据
*/
fun setData(lists: ArrayList<B>): Builder<B> {
adapter.mDatalist = lists
return this
}
/**
* 设置布局id
*/
fun setLayoutId(layoutId: Int): Builder<B> {
adapter.mLayoutId = layoutId
return this
}
/**
* 绑定View和数据
*/
fun addBindView(itemBind: ((itemView: View, itemData: B) -> Unit)): Builder<B> {
adapter.addBindView = itemBind
return this
}
fun create(): KotlinDataAdapter<B> {
return adapter
}
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.model
data class BaseModel<out M>(
val code:Int,
val error : String?,
val data:M?
)
package com.ccwangluo.accelerator.model
data class LoginRes(
val createdAt: String?,
val phone: String?,
val token: String?
)
package com.ccwangluo.accelerator.model
data class NetState(
//延迟
var preNetDelay : Int,
var accNetDelay: Int,
var delay : Int,
//丢包率
var lossRate: String
)
\ No newline at end of file
package com.ccwangluo.accelerator.ui
import android.view.*
import androidx.viewpager.widget.ViewPager
import com.ccwangluo.accelerator.databinding.FragmentBtnNavBinding
import com.ccwangluo.accelerator.ui.home.AccelertorFragment
import com.ccwangluo.accelerator.ui.home.MineFragment
import com.ccwangluo.accelerator.ui.home.NewsFragment
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.utils.TitleBar
import com.xuexiang.xui.adapter.FragmentAdapter
import com.xuexiang.xutil.common.CollectionUtils
@Page(name = "主页")
class BottomNavigationFragment : XPageFragment(), ViewPager.OnPageChangeListener,
BottomNavigationView.OnNavigationItemSelectedListener {
lateinit var binding: FragmentBtnNavBinding
override fun inflateView(inflater: LayoutInflater?, container: ViewGroup?): View {
binding = FragmentBtnNavBinding.inflate(inflater!!, container, false)
return binding.root
}
override fun initTitleBar(): TitleBar? {
//不使用@Page标注的一定要注意覆盖这个方法
return null
}
var titles = arrayOf("加速", "资讯", "我的")
override fun initViews() {
val adapter = FragmentAdapter<XPageFragment>(
childFragmentManager
)
adapter.addFragment(AccelertorFragment.newInstance(), titles[0])
adapter.addFragment(NewsFragment.newInstance(), titles[1])
adapter.addFragment(MineFragment.newInstance(), titles[2])
binding.viewPager.setOffscreenPageLimit(titles.size - 1);
binding.viewPager.adapter = adapter
}
override fun initListeners() {
binding.viewPager.addOnPageChangeListener(this)
binding.bottomNavigation.setOnNavigationItemSelectedListener(this)
binding.bottomNavigation.setItemIconTintList(null);
binding.bottomNavigation.itemTextColor
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
// binding.bottomNavigation.menu.getItem(position).isChecked = true
}
override fun onPageSelected(position: Int) {
}
override fun onPageScrollStateChanged(index: Int) {
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
val index: Int = CollectionUtils.arrayIndexOf(titles, item.getTitle())
if (index != -1) {
binding.viewPager.setCurrentItem(index, true)
return true
}
return false
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
return super.onKeyDown(keyCode, event)
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui
import android.Manifest
import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import com.ccwangluo.accelerator.ui.dialog.PrivacyDialog
import com.ccwangluo.accelerator.utils.AcceleratorUtils
import com.ccwangluo.accelerator.utils.LoginUtils
import com.ccwangluo.accelerator.utils.PhoneUtils
import com.ccwangluo.accelerator.utils.http.HttpConfig
import com.ccwangluo.cc_quickly.utils.SettingSPUtils
import com.github.shadowsocks.utils.StartService
import com.hjq.toast.ToastUtils
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import com.tencent.mmkv.MMKV
import com.tencent.tauth.Tencent
import com.umeng.socialize.UMShareAPI
import com.xuexiang.xpage.base.XPageActivity
import com.xuexiang.xpage.core.PageOption
class MainActivity() : XPageActivity() {
private val connect = registerForActivityResult(StartService()) {
if (it) {
ToastUtils.show("开启vpn权限失败")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MMKV.initialize(this)
initPhoneUtils()
//获取权限
Dexter.withContext(this)
.withPermissions(
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(p0: MultiplePermissionsReport?) {
println(p0)
}
override fun onPermissionRationaleShouldBeShown(
p0: MutableList<PermissionRequest>?,
p1: PermissionToken?
) {
println(p0)
println(p1)
}
}).check()
PageOption.to(BottomNavigationFragment::class.java).open(this)
Tencent.setIsPermissionGranted(true)
//隐私协议
if (!SettingSPUtils.isAgreePrivacy) {
PrivacyDialog(this, HttpConfig.privacy_url, {
if (it) {
SettingSPUtils.isAgreePrivacy = true
} else {
finish()
}
}).show<PrivacyDialog>()
}
AcceleratorUtils.initConnect(this, connect)
}
private fun initPhoneUtils() {
PhoneUtils.getPhoneInfo()
}
override fun onStart() {
super.onStart()
AcceleratorUtils.onStart()
}
override fun onStop() {
super.onStop()
AcceleratorUtils.onStop()
}
override fun onDestroy() {
super.onDestroy()
LoginUtils.clearToken()
AcceleratorUtils.onDestroy(this)
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data)
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
activeFragment?.let {
if (activeFragment.onKeyDown(keyCode, event)) {
return true
}
}
return super.onKeyDown(keyCode, event)
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.dialog
import android.content.Context
import android.widget.TextView
import androidx.fragment.app.Fragment
import com.ccwangluo.accelerator.R
import com.xuexiang.xui.widget.dialog.materialdialog.CustomMaterialDialog
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
class CommonDialog(
var fragment: Fragment
) : CustomMaterialDialog(fragment.context) {
override fun getDialogBuilder(context: Context?): MaterialDialog.Builder {
return MaterialDialog.Builder(context!!)
.customView(R.layout.dialog_common, false);
}
override fun initViews(context: Context?) {
}
fun setTitle(title: String): CommonDialog {
val tx = findViewById<TextView>(R.id.title)
tx.setText(title)
return this
}
fun setContent(content: String): CommonDialog {
val dia_text = findViewById<TextView>(R.id.dia_text)
dia_text.text = content
return this
}
fun setBtnLeft(btnText: String, callback: () -> Unit): CommonDialog {
val btn_left = findViewById<TextView>(R.id.btn_left)
btn_left.text = btnText
btn_left.setOnClickListener {
dismiss<CommonDialog>()
callback()
}
return this
}
fun setBtnRight(btnText: String, callback: () -> Unit): CommonDialog {
val btn_right = findViewById<TextView>(R.id.btn_right)
btn_right.text = btnText
btn_right.setOnClickListener {
dismiss<CommonDialog>()
callback()
}
return this
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.dialog
import android.content.Context
import android.os.Bundle
import android.widget.ImageView
import com.ccwangluo.accelerator.R
import com.ccwangluo.accelerator.ui.web.CommonWebViewFragment
import com.ccwangluo.accelerator.utils.http.HttpConfig
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xui.widget.dialog.materialdialog.CustomMaterialDialog
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
/**
* 会员购买框
*/
class MemberDialog(
var fragment: XPageFragment,
) : CustomMaterialDialog(fragment.context) {
override fun getDialogBuilder(context: Context?): MaterialDialog.Builder {
return MaterialDialog.Builder(context!!)
.customView(R.layout.dialog_member, false);
}
override fun initViews(context: Context?) {
val btn = findViewById<ImageView>(R.id.dialog_memeber_btn)
btn.setOnClickListener {
dismiss<MemberDialog>()
val params = Bundle()
params.putString(CommonWebViewFragment.WEBVIEW_URL_KEY, HttpConfig.privacy_url)
fragment.openPage(CommonWebViewFragment::class.java, params)
}
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.dialog
import android.content.Context
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import com.ccwangluo.accelerator.R
import com.just.agentweb.core.AgentWeb
import com.just.agentweb.core.client.DefaultWebClient
import com.xuexiang.xpage.base.XPageActivity
import com.xuexiang.xui.widget.dialog.materialdialog.CustomMaterialDialog
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
class PrivacyDialog(
var xPageActivity: XPageActivity,
var privacy_url: String,
var callback: (Boolean) -> Unit
) : CustomMaterialDialog(xPageActivity) {
override fun getDialogBuilder(context: Context?): MaterialDialog.Builder {
return MaterialDialog.Builder(context!!)
.customView(R.layout.dialog_privacy, false);
}
override fun initViews(context: Context?) {
val disagree = findViewById<TextView>(R.id.privacy_disagree)
val agree = findViewById<TextView>(R.id.privacy_agree)
disagree.setOnClickListener {
callback(false);
dialog.dismiss()
}
agree.setOnClickListener {
callback(true)
dialog.dismiss()
}
}
init {
val container = findViewById<FrameLayout>(R.id.privacy_webview)
val agentWeb =
createAgentWeb(xPageActivity, container, privacy_url)
}
fun createAgentWeb(xPageActivity: XPageActivity, viewGroup: ViewGroup, url: String): AgentWeb {
return AgentWeb.with(xPageActivity)
.setAgentWebParent(
viewGroup!!,
-1,
FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
)
.useDefaultIndicator(-1, 3)
.setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.ASK)
.createAgentWeb()
.ready()
.go(url)
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.home
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import androidx.lifecycle.ViewModelProvider
import com.ccwangluo.accelerator.R
import com.ccwangluo.accelerator.databinding.FragmentQuickBinding
import com.ccwangluo.accelerator.ui.dialog.CommonDialog
import com.ccwangluo.accelerator.utils.AcceleratorUtils
import com.ccwangluo.accelerator.utils.SysUtils
import com.github.shadowsocks.bg.BaseService
import com.hjq.toast.ToastUtils
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.utils.TitleBar
class AccelertorFragment : XPageFragment() {
private lateinit var binding: FragmentQuickBinding
private lateinit var accelertorViewModel: AccelertorViewModel
private var acc_timer = 0L
override fun initTitleBar(): TitleBar? {
//不使用@Page标注的一定要注意覆盖这个方法
return null
}
override fun inflateView(inflater: LayoutInflater?, container: ViewGroup?): View {
binding = FragmentQuickBinding.inflate(inflater!!, container, false)
accelertorViewModel =
ViewModelProvider(requireActivity()).get(AccelertorViewModel::class.java)
return binding.root
}
override fun initViews() {
accelertorViewModel.netState.observe(this, {
if (it.preNetDelay != -1) { //有网络
binding.preDelay1.setText(it.preNetDelay.toString())
binding.preDelay2.setText(it.preNetDelay.toString())
binding.preDelay1Unit.visibility = View.VISIBLE
binding.preDelay2Unit.visibility = View.VISIBLE
} else { //无网络
binding.preDelay1.setText("--")
binding.preDelay2.setText("--")
binding.preDelay1Unit.visibility = View.GONE
binding.preDelay2Unit.visibility = View.GONE
}
if (it.accNetDelay != -1) {
binding.netDelay1.setText(it.accNetDelay.toString())
binding.netDelay2.setText(it.accNetDelay.toString())
binding.netDelay1Unit.visibility = View.VISIBLE
binding.netDelay2Unit.visibility = View.VISIBLE
} else {
binding.netDelay1.setText("__")
binding.netDelay2.setText("__")
binding.netDelay1Unit.visibility = View.GONE
binding.netDelay2Unit.visibility = View.GONE
}
if (!it.lossRate.isEmpty()) {
binding.netLost1.setText(it.lossRate)
binding.netLost2.setText(it.lossRate)
binding.netLost1Unit.visibility = View.VISIBLE
binding.netLost2Unit.visibility = View.VISIBLE
} else {
binding.netLost1.setText("__")
binding.netLost2.setText("__")
binding.netLost1Unit.visibility = View.GONE
binding.netLost2Unit.visibility = View.GONE
}
if (it.delay != -1) {
binding.netQuality.setText(SysUtils.getnetQuality(it.delay))
}
})
accelertorViewModel.accState.observe(this, {
freshData(it, acc_timer)
})
}
override fun initListeners() {
binding.btnExpend.setOnClickListener {
if (binding.expandableLayout1.isExpanded) {
binding.expandableLayout1.toggle()
binding.expandableLayout2.expand()
binding.btnExpendBg.setBackgroundResource(com.ccwangluo.accelerator.R.mipmap.quick_arrow_up)
} else {
binding.expandableLayout1.expand()
binding.expandableLayout2.toggle()
binding.btnExpendBg.setBackgroundResource(com.ccwangluo.accelerator.R.mipmap.quick_arrow_down)
}
}
binding.btnQuick.setOnClickListener {
accelertorViewModel.accState.value?.let {
if (it.canStop) {
CommonDialog(this).setTitle("加速停止确认")
.setContent("停止加速可能会导致游戏断线,是否确认停止?")
.setBtnLeft("取消", {}).setBtnRight("停止加速", {
AcceleratorUtils.stopAccelerator()
}).show<CommonDialog>()
return@setOnClickListener
}
}
// if (!LoginUtils.hasToken()) {
// LoginUtils.login(this, {
//
// })
// return@setOnClickListener
// }
if (!SysUtils.getConnectivityStatus()) {
binding.quickTopToast.visibility = View.VISIBLE
binding.quickTopToastTx.setText("网络异常,请检查网络后重试")
binding.quickTopToastTx.postDelayed({
binding.quickTopToastTx.visibility = View.GONE
}, 2000)
return@setOnClickListener
}
//用户是否有使用时长
// if (){
// MemberDialog(this).show<MemberDialog>()
// return@setOnClickListener
// }
//
AcceleratorUtils.startAccelerator()
startAnim()
}
}
override fun onResume() {
super.onResume()
AcceleratorUtils.registerStateListener({ state, l, net ->
accelertorViewModel.netState.postValue(net)
acc_timer = l
accelertorViewModel.accState.postValue(state)
})
}
fun freshData(state: BaseService.State, time: Long) {
if (state == BaseService.State.Connected) {
stopAnim()
binding.progressViewCircleSmall.progress = 100F
binding.accStateTx.setText(SysUtils.getAccTimeString(time))
binding.accStateTx.visibility = View.VISIBLE
binding.btnQuick.setBackgroundResource(R.mipmap.quick_stop)
} else if (state == BaseService.State.Stopped) {
stopAnim()
binding.accStateTx.visibility = View.GONE
binding.progressViewCircleSmall.progress = 0F
binding.btnQuick.setBackgroundResource(R.mipmap.quick_start)
}
}
override fun onPause() {
super.onPause()
AcceleratorUtils.unRegisterStateListener()
}
fun stopAnim() {
binding.progressViewCircleSmall.stopProgressAnimation()
binding.progressViewCircleSmall.setProgressTextVisibility(false)
binding.gamePicOut.clearAnimation()
binding.gamePicIn1.clearAnimation()
}
fun startAnim() {
binding.progressViewCircleSmall.setProgressTextVisibility(true)
binding.progressViewCircleSmall.startProgressAnimation()
binding.gamePicOut.startAnimation(getDefaultAnim())
binding.gamePicIn1.startAnimation(getDefaultAnim())
}
fun getDefaultAnim(): RotateAnimation {
val rotate = RotateAnimation(
0f,
360f,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f
)
val lin = LinearInterpolator()
rotate.interpolator = lin
rotate.duration = 2000 //设置动画持续周期
rotate.repeatCount = -1 //设置重复次数
rotate.fillAfter = true //动画执行完后是否停留在执行完的状态
rotate.startOffset = 10 //执行前的等待时间
return rotate
}
companion object {
fun newInstance(): AccelertorFragment {
val fragment = AccelertorFragment()
return fragment
}
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.home
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ccwangluo.accelerator.model.NetState
import com.ccwangluo.accelerator.utils.SysUtils
import com.github.shadowsocks.bg.BaseService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.BufferedReader
import java.io.InputStreamReader
class AccelertorViewModel : ViewModel() {
//网络状态
var netState = MutableLiveData<NetState>()
var accState = MutableLiveData<BaseService.State>()
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.home
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.fragment.app.Fragment
import com.ccwangluo.accelerator.databinding.FragmentMineBinding
import com.ccwangluo.accelerator.ui.web.AndroidInterface
import com.ccwangluo.accelerator.utils.http.HttpConfig
import com.just.agentweb.core.AgentWeb
import com.just.agentweb.core.client.DefaultWebClient
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.utils.TitleBar
class MineFragment : XPageFragment() {
private var _binding: FragmentMineBinding? = null
private val binding get() = _binding!!
var agentWeb: AgentWeb? = null
override fun initTitleBar(): TitleBar? {
//不使用@Page标注的一定要注意覆盖这个方法
return null
}
override fun inflateView(inflater: LayoutInflater?, container: ViewGroup?): View {
_binding = FragmentMineBinding.inflate(inflater!!, container, false)
return binding.root
}
override fun initViews() {
val agentWeb =
createAgentWeb(this, binding.mineWebview, HttpConfig.UI_MAIN_URL)
agentWeb.getJsInterfaceHolder().addJavaObject("android", AndroidInterface(this, agentWeb))
}
override fun initListeners() {
}
companion object {
fun newInstance(): MineFragment {
val fragment = MineFragment()
return fragment
}
}
fun createAgentWeb(fragment: Fragment?, viewGroup: ViewGroup, url: String): AgentWeb {
return AgentWeb.with(fragment!!)
.setAgentWebParent(
viewGroup!!,
-1,
FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
)
.useDefaultIndicator(-1, 3)
.setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.ASK)
.createAgentWeb()
.ready()
.go(url)
}
override fun onPause() {
agentWeb?.getWebLifeCycle()?.onPause()
super.onPause()
}
override fun onResume() {
agentWeb?.getWebLifeCycle()?.onResume()
super.onResume()
}
override fun onDestroyView() {
agentWeb?.getWebLifeCycle()?.onDestroy()
super.onDestroyView()
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.home
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import com.ccwangluo.accelerator.R
import com.ccwangluo.accelerator.databinding.FragmentNewsBinding
import com.ccwangluo.accelerator.ui.news.DemoCollectionAdapter
import com.google.android.material.tabs.TabLayoutMediator
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.utils.TitleBar
class NewsFragment : XPageFragment() {
private var _binding: FragmentNewsBinding? = null
private val binding get() = _binding!!
private lateinit var newsViewModel: NewsViewModel
override fun initTitleBar(): TitleBar? {
//不使用@Page标注的一定要注意覆盖这个方法
return null
}
override fun inflateView(inflater: LayoutInflater?, container: ViewGroup?): View {
_binding = FragmentNewsBinding.inflate(inflater!!, container, false)
newsViewModel = ViewModelProvider(requireActivity()).get(NewsViewModel::class.java)
return binding.root
}
val titles = arrayOf("动态", "攻略", "视频", "评价", "问答")
var adapter: DemoCollectionAdapter? = null
override fun initViews() {
newsViewModel.refreshState.observe(this, {
if (!it) {
binding.refreshLayout.isRefreshing = false
}
})
binding.tvMarquee.addDisplayString("【公告】韩服 DNF已经开启预约啦,小伙伴…")
binding.tvMarquee.startRoll()
adapter = DemoCollectionAdapter(this, titles)
binding.viewPager.adapter = adapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.setCustomView(R.layout.item_tab)
tab.text = titles[position]
}.attach()
}
override fun initListeners() {
binding.refreshLayout.setOnRefreshListener {
adapter?.refresh(binding.viewPager.currentItem)
binding.refreshLayout.postDelayed({
binding.refreshLayout.isRefreshing = false
}, 2000)
}
}
companion object {
fun newInstance(): NewsFragment {
val fragment = NewsFragment()
return fragment
}
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.home
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class NewsViewModel : ViewModel() {
/**
* 刷新状态
*/
val refreshState = MutableLiveData<Boolean>()
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.login
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ccwangluo.accelerator.model.LoginRes
import com.ccwangluo.accelerator.utils.LoginUtils
import com.ccwangluo.accelerator.utils.http.HttpGo
import com.hjq.toast.ToastUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class LoginViewModel : ViewModel() {
val sendCodeState = MutableLiveData<Boolean>()
val loginState = MutableLiveData<Boolean>()
val timerNumber = MutableLiveData<Int>()
fun login(phone: String, authCdoe: String) {
val map = mutableMapOf<String, String>()
map.put("phone", phone)
map.put("verifyCode", authCdoe)
viewModelScope.launch(Dispatchers.IO) {
val res = HttpGo.postSync<LoginRes>("/user/verifyCode/login", map)
res?.let {
if (it.code == 200) {
LoginUtils.token = it.data?.token
loginState.postValue(true)
} else {
ToastUtils.show(it.error)
}
}
}
}
fun getAuthCode(phone: String) {
val map = mutableMapOf<String, String>()
map.put("phone", phone)
viewModelScope.launch(Dispatchers.IO) {
val res = HttpGo.postSync<Boolean>("/user/sendSms", map)
res?.let {
if (it.code == 200) {
sendCodeState.postValue(true)
} else {
sendCodeState.postValue(false)
ToastUtils.show(it.error)
}
}
if (res == null) {
sendCodeState.postValue(false)
}
}
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.login
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.ccwangluo.accelerator.databinding.FragmentLoginPhoneBinding
import com.ccwangluo.accelerator.utils.LoginUtils
import com.hjq.toast.ToastUtils
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.utils.TitleBar
import com.xuexiang.xutil.common.StringUtils
import java.util.regex.Pattern
/**
* A simple [Fragment] subclass.
* Use the [PhoneLoginFragment.newInstance] factory method to
* create an instance of this fragment.
*/
@Page(name = "登录")
class PhoneLoginFragment : XPageFragment() {
override fun initTitleBar(): TitleBar? {
return null
}
private val mHandler: Handler = Handler(Looper.getMainLooper());
private var mCountTime = 60
private lateinit var loginViewModel: LoginViewModel
private lateinit var binding: FragmentLoginPhoneBinding
override fun inflateView(inflater: LayoutInflater?, container: ViewGroup?): View {
binding = FragmentLoginPhoneBinding.inflate(inflater!!, container, false)
loginViewModel = ViewModelProvider(requireActivity()).get(LoginViewModel::class.java)
return binding.root
}
override fun initViews() {
binding.phoneEt.addTextChangedListener {
val phone = it.toString().trim()
val authCdoe = binding.authCodeEt.text.toString()
if (phone.length > 0) {
binding.authCodeBtn.isEnabled = true
} else {
binding.authCodeBtn.isEnabled = false
}
if (isPhone(phone) && authCdoe.length > 0) {
binding.login.isEnabled = true
} else {
binding.login.isEnabled = false
}
}
binding.authCodeEt.addTextChangedListener {
val authCdoe = it.toString().trim()
val phone = binding.phoneEt.text.toString()
if (isPhone(phone) && authCdoe.length > 0) {
binding.login.isEnabled = true
} else {
binding.login.isEnabled = false
}
if (isPhone(phone) && authCdoe.length == 6 && binding.cbProtocol.isChecked) {
loginViewModel.login(phone, authCdoe)
}
}
loginViewModel.sendCodeState.observe(this, {
if (it) {
LoginUtils.startTimer()
} else {
binding.authCodeBtn.visibility = View.VISIBLE
binding.authCodeWait.visibility = View.GONE
binding.authCodeBtn.isEnabled = true
}
})
loginViewModel.loginState.observe(this, {
if (it) {
popToBack()
}
})
loginViewModel.timerNumber.observe(this, {
if (it > 0) {
binding.authCodeBtn.visibility = View.GONE
binding.authCodeWait.visibility = View.VISIBLE
binding.authCodeBtn.isEnabled = false
binding.authCodeWait.setText("${it}秒后重新获得验证码")
} else {
resetCounter()
}
})
}
override fun initListeners() {
binding.privacyAggreement.setOnClickListener({
})
binding.userAggreement.setOnClickListener {
}
binding.phoneClear.setOnClickListener {
binding.phoneEt.setText("")
}
binding.authCodeBtn.setOnClickListener {
val phone = binding.phoneEt.text.toString()
if (StringUtils.isEmpty(phone) || !isPhone(phone)) {
ToastUtils.show("输入正确的手机号")
return@setOnClickListener
}
binding.authCodeBtn.isEnabled = false
loginViewModel.getAuthCode(phone)
}
binding.btnBack.setOnClickListener {
popToBack()
}
binding.login.setOnClickListener {
//检查验证码,手机号格式
val phone = binding.phoneEt.text.toString()
val authCdoe = binding.authCodeEt.text.toString()
if (StringUtils.isEmpty(phone) || !isPhone(phone)) {
ToastUtils.show("输入正确的手机号")
return@setOnClickListener
}
if (StringUtils.isEmpty(authCdoe) || authCdoe.length < 6) {
ToastUtils.show("请输入验证码")
return@setOnClickListener
}
//检查ck
if (!binding.cbProtocol.isChecked) {
ToastUtils.show("先勾选协议哦")
return@setOnClickListener
}
loginViewModel.login(phone, authCdoe)
}
}
fun isPhone(phone: String): Boolean {
// 开头的"1"代表第一位为数字1,"[3-9]"代表第二位可以为3、4、5、6、7、8、9其中之一,"\\d{9}"代表后面是9位数字
val regex = "1[3-9]\\d{9}"
return Pattern.matches(regex, phone)
}
override fun onResume() {
super.onResume()
LoginUtils.registerTimerCallBack {
loginViewModel.timerNumber.postValue(it)
}
}
override fun onPause() {
super.onPause()
LoginUtils.unRegisterTimerCallBack()
}
//重置按钮状态
fun resetCounter() {
mCountTime = 60
binding.authCodeBtn.visibility = View.VISIBLE
binding.authCodeWait.visibility = View.GONE
binding.authCodeBtn.setText("重新获取验证码")
binding.authCodeBtn.isEnabled = true
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.news
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
class DemoCollectionAdapter(fragment: Fragment, val titles: Array<String>) :
FragmentStateAdapter(fragment) {
override fun getItemCount(): Int = titles.size
var list = mutableListOf<DemoObjectFragment>()
override fun createFragment(position: Int): Fragment {
val fragment = DemoObjectFragment()
fragment.arguments = Bundle().apply {
// Our object is just an integer :-P
putInt(ARG_OBJECT, position)
}
list.add(fragment)
return fragment
}
fun refresh(index:Int) {
list.get(index).refresh()
}
companion object {
val ARG_OBJECT = "object"
}
}
package com.ccwangluo.accelerator.ui.news
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.RecyclerView
import com.ccwangluo.accelerator.R
import com.ccwangluo.accelerator.ui.home.NewsViewModel
import com.ccwangluo.accelerator.ui.news.DemoCollectionAdapter.Companion.ARG_OBJECT
class DemoObjectFragment : Fragment() {
var recycle_view: RecyclerView? = null
private lateinit var newsViewModel: NewsViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
newsViewModel = ViewModelProvider(requireActivity()).get(NewsViewModel::class.java)
return inflater.inflate(R.layout.fragment_collection_object, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
arguments?.takeIf { it.containsKey(ARG_OBJECT) }?.apply {
val position = getInt(ARG_OBJECT).toString()
recycle_view = view.findViewById(R.id.recycle_view)
}
// val adapter = KotlinDataAdapter.Builder<DeviceModel>()
// .setData(deviceList)
// .setLayoutId(R.layout.item_device)
// .addBindView { itemView, itemData ->
// itemView.tv_device_name.text = if (itemData.platform.isEmpty()) "未命名" else
// }
// .create()
}
fun refresh() {
recycle_view?.postDelayed({
newsViewModel.refreshState.postValue(false )
}, 1000)
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.web
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.webkit.JavascriptInterface
import androidx.core.content.ContextCompat.checkSelfPermission
import com.ccwangluo.accelerator.utils.LoginUtils
import com.ccwangluo.accelerator.utils.SysUtils
import com.ccwangluo.cc_quickly.utils.XToastUtils
import com.just.agentweb.core.AgentWeb
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import com.xuexiang.xpage.base.XPageFragment
/**
* js注入的方法
*/
class AndroidInterface(val xPageFragment: XPageFragment, val agentWeb: AgentWeb) {
@JavascriptInterface
fun callAndroid(msg: String) {
XToastUtils.toast("这是Js调用Android的方法,内容:$msg")
}
@JavascriptInterface
fun close() {
xPageFragment.popToBack()
}
@JavascriptInterface
fun openNative(pageName: String) {
xPageFragment.openPage(pageName)
}
@JavascriptInterface
fun openWebview(url: String) {
val params = Bundle()
params.putString(CommonWebViewFragment.WEBVIEW_URL_KEY, url)
xPageFragment.openPage(CommonWebViewFragment::class.java, params)
}
@JavascriptInterface
fun login(callback: String) {
LoginUtils.login(xPageFragment, {
if (it) {
agentWeb.getJsAccessEntrace()
.quickCallJs(callback, LoginUtils.token)
}
})
}
/**
* 检查权限
*/
@JavascriptInterface
fun getPermissionState(key: String, callback: String) {
xPageFragment.context?.let {
val hasPermission: Boolean = if (checkSelfPermission(it, key) > 0) true else false
agentWeb.getJsAccessEntrace()
.quickCallJs(callback, key, hasPermission.toString())
}
}
/**
* 申请权限
*/
@JavascriptInterface
fun requirePermissionState(key: String, callback: String) {
xPageFragment.context?.let {
//获取权限
Dexter.withContext(it)
.withPermissions(key)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(p0: MultiplePermissionsReport?) {
p0?.let {
it.grantedPermissionResponses.forEach {
agentWeb.getJsAccessEntrace()
.quickCallJs(callback, key, "true")
}
it.deniedPermissionResponses.forEach {
agentWeb.getJsAccessEntrace()
.quickCallJs(callback, key, "false")
}
}
}
override fun onPermissionRationaleShouldBeShown(
p0: MutableList<PermissionRequest>?,
p1: PermissionToken?
) {
}
}).check()
}
}
/**
* 检查安装包
*/
@JavascriptInterface
fun getPackageState(packageName: String, callback: String) {
xPageFragment.context?.let {
val packageInstall = SysUtils.isPackageInstall(it, packageName)
agentWeb.getJsAccessEntrace()
.quickCallJs(callback, packageName, packageInstall.toString())
}
}
/**
* 卸载程序
*/
@JavascriptInterface
fun uninstallPackge(pageName: String) {
xPageFragment.context?.let {
//创建Intent意图
val intent = Intent(Intent.ACTION_DELETE)
//通过程序的包名创建URL
val packageURI = Uri.parse("package:${pageName}")
//设置Uri
intent.setData(packageURI)
//卸载程序
it.startActivity(intent)
}
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.ui.web
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.fragment.app.Fragment
import com.ccwangluo.accelerator.databinding.FragmentWebviewBinding
import com.just.agentweb.core.AgentWeb
import com.just.agentweb.core.client.DefaultWebClient
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xpage.base.XPageFragment
@Page(name = "webview")
class CommonWebViewFragment : XPageFragment() {
var agentWeb: AgentWeb? = null
lateinit var binding: FragmentWebviewBinding
override fun inflateView(inflater: LayoutInflater?, container: ViewGroup?): View {
binding = FragmentWebviewBinding.inflate(inflater!!, container, false)
return binding.root
}
override fun initViews() {
val url = arguments?.getString(WEBVIEW_URL_KEY)
agentWeb =
url?.let { createAgentWeb(this, binding.commonWebview, it) }
agentWeb?.getJsInterfaceHolder()
?.addJavaObject("android", AndroidInterface(this, agentWeb!!))
}
fun createAgentWeb(fragment: Fragment?, viewGroup: ViewGroup, url: String): AgentWeb {
return AgentWeb.with(fragment!!)
.setAgentWebParent(
viewGroup!!,
-1,
FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
)
.useDefaultIndicator(-1, 3)
.setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.ASK)
.createAgentWeb()
.ready()
.go(url)
}
override fun initListeners() {
}
override fun onPause() {
agentWeb?.getWebLifeCycle()?.onPause()
super.onPause()
}
override fun onResume() {
agentWeb?.getWebLifeCycle()?.onResume()
super.onResume()
}
override fun onDestroyView() {
agentWeb?.getWebLifeCycle()?.onDestroy()
super.onDestroyView()
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK) {
agentWeb?.let {
if (it.back()) {
return true
}
}
}
return super.onKeyDown(keyCode, event)
}
companion object {
var WEBVIEW_URL_KEY = "WEBVIEW_URL_KEY"
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.utils;
import android.content.Context;
import android.graphics.Point;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
/**
* 获得屏幕相关数据的辅助类
*/
public class AbScreenUtils {
private static Handler mainHandler;
private AbScreenUtils() {
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* 获得屏幕高度
*
* @param context
* @return
*/
public static int getScreenHeight(Context context, boolean isDp) {
int screenHeight = 0;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
int height = dm.heightPixels; // 屏幕高度(像素)
if (!isDp) {
return height;
}
float density = dm.density; // 屏幕密度(0.75 / 1.0 / 1.5)
screenHeight = (int) (height / density);// 屏幕高度(dp)
return screenHeight;
}
public static int getScreenWidth(Context context, boolean isDp) {
int screenWidth = 0;
int winWidth;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display defaultDisplay = wm.getDefaultDisplay();
Point point = new Point();
defaultDisplay.getSize(point);
if (point.x > point.y) {
winWidth = point.y;
} else {
winWidth = point.x;
}
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
if (!isDp) {
return winWidth;
}
float density = dm.density; // 屏幕密度(0.75 / 1.0 / 1.5)
screenWidth = (int) (winWidth / density);// 屏幕高度(dp)
return screenWidth;
}
/**
* dp转换成px
*/
public static int dp2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public static void showToast(final Context context, final String msg) {
mainHandler = new Handler(Looper.getMainLooper());
execute(new Runnable() {
@Override
public void run() {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
});
}
private static void execute(Runnable runnable) {
if (Looper.getMainLooper() == Looper.myLooper()) {
runnable.run();
} else {
mainHandler.post(runnable);
}
}
}
package com.ccwangluo.accelerator.utils
import android.annotation.SuppressLint
import android.content.Context
import android.os.RemoteException
import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.ccwangluo.accelerator.model.NetState
import com.github.shadowsocks.Core
import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.aidl.ShadowsocksConnection
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.database.ProfileManager
import com.xuexiang.xutil.net.NetworkUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
/**
* 加速功能工具类
*/
@SuppressLint("StaticFieldLeak")
object AcceleratorUtils {
private val connection = ShadowsocksConnection(true)
private lateinit var connect: ActivityResultLauncher<Void?>
private lateinit var context: AppCompatActivity
// service
var state = BaseService.State.Idle
//加速前延迟
var pre_net = -1
//加速后延迟
var acc_net = -1
var netState = NetState(-1, -1, -1, "0")
private val preStateList = mutableListOf<NetState>()
// 加速时长
var ACC_TIME = 0L
var stateListener: (BaseService.State, Long, NetState) -> Unit = { state, l, net ->
}
fun initConnect(context: AppCompatActivity, connect: ActivityResultLauncher<Void?>) {
this.context = context
this.connect = connect
connection.connect(context, shadowsocksConnection)
ProfileManager.ensureNotEmpty()
context.lifecycleScope.launch(Dispatchers.IO) {
while (true) {
val net = SysUtils.getNetPing("10.3.0.34")
if (state != BaseService.State.Connected) {
pre_net = net.delay
} else {
net.accNetDelay = if (net.delay > pre_net) pre_net else net.delay
}
net.preNetDelay = pre_net
netState = net
stateListener(state, getAccTime(), net)
delay(2000)
}
}
}
fun startAccelerator() {
connect.launch(null)
}
fun registerStateListener(listener: (BaseService.State, Long, NetState) -> Unit) {
stateListener = listener
stateListener(state, getAccTime(), netState)
}
fun unRegisterStateListener() {
stateListener = { state, l, net ->
}
}
fun stopAccelerator() {
Core.stopService()
}
private val shadowsocksConnection = object : ShadowsocksConnection.Callback {
override fun stateChanged(state: BaseService.State, profileName: String?, msg: String?) {
AcceleratorUtils.state = state
if(state == BaseService.State.Connected){
ACC_TIME = System.currentTimeMillis()
}
stateListener(state, getAccTime(), netState)
}
override fun onServiceConnected(service: IShadowsocksService) {
try {
state = BaseService.State.values()[service.state]
} catch (_: RemoteException) {
state = BaseService.State.Idle
}
stateListener(state, getAccTime(), netState)
}
override fun onBinderDied() {
connection.disconnect(context)
connection.connect(context, this)
}
}
fun getAccTime(): Long {
return if (ACC_TIME == 0L) 0 else System.currentTimeMillis() - ACC_TIME
}
fun onStart() {
connection.bandwidthTimeout = 500
}
fun onStop() {
connection.bandwidthTimeout = 0
}
fun onDestroy(context: Context) {
connection.disconnect(context)
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.utils
import android.content.Context
import androidx.lifecycle.lifecycleScope
import com.ccwangluo.accelerator.model.LoginRes
import com.ccwangluo.accelerator.ui.login.PhoneLoginFragment
import com.ccwangluo.accelerator.utils.http.HttpGo
import com.chuanglan.shanyan_sdk.OneKeyLoginManager
import com.hjq.toast.ToastUtils
import com.tencent.mmkv.MMKV
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.core.PageOption
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.*
object LoginUtils {
var loginRes: LoginRes? = null
var timeNumber = 60
private var timer: Timer? = null
private var timerTask: TimerTask? = null
private var timerCallBack: (Int) -> Unit? = {}
fun registerTimerCallBack(callBack: (Int) -> Unit) {
timerCallBack = callBack
}
fun unRegisterTimerCallBack() {
timerCallBack = {}
}
fun startTimer() {
timer?.cancel()
timerTask = object : TimerTask() {
override fun run() {
timeNumber--
timerCallBack(timeNumber)
if (timeNumber == 0) {
timer?.cancel()
}
}
}
timer = Timer();
timer?.schedule(timerTask, 0, 1000);
}
fun login(xPageFragment: XPageFragment, callBack: (Boolean) -> Unit) {
PhoneUtils.openLoginAuth(xPageFragment) { b, s ->
if (b) {
val map = mutableMapOf<String, String>()
map.put("token", s)
xPageFragment.lifecycleScope.launch(Dispatchers.IO) {
val res = HttpGo.postSync<LoginRes>("/user/flash/login", map)
res?.let {
if (it.code == 200) {
token = it.data?.token
loginRes = it.data
ToastUtils.show("登录成功")
OneKeyLoginManager.getInstance().finishAuthActivity()
withContext(Dispatchers.Main) {
callBack(true)
}
} else {
it.error?.let {
ToastUtils.show(it)
}
withContext(Dispatchers.Main) {
callBack(false)
}
}
}
}
} else {
PageOption.to(PhoneLoginFragment::class.java).open(xPageFragment)
}
}
}
private var sToken: String? = null
private const val KEY_TOKEN = "com.ccwangluo.KEY_TOKEN"
/**
* 初始化Token信息
*/
fun init(context: Context?) {
sToken = MMKV.defaultMMKV().decodeString(KEY_TOKEN, "")
}
fun clearToken() {
sToken = null
MMKV.defaultMMKV().remove(KEY_TOKEN)
}
var token: String?
get() = sToken
set(token) {
sToken = token
MMKV.defaultMMKV().putString(KEY_TOKEN, token)
}
fun hasToken(): Boolean {
return MMKV.defaultMMKV().containsKey(KEY_TOKEN)
}
fun logout() {
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.utils
import android.app.Application
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.util.Log
import android.util.TypedValue
import android.widget.RelativeLayout
import android.widget.TextView
import com.ccwangluo.accelerator.R
import com.ccwangluo.accelerator.ui.login.PhoneLoginFragment
import com.chuanglan.shanyan_sdk.OneKeyLoginManager
import com.chuanglan.shanyan_sdk.tool.ShanYanUIConfig
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.core.PageOption
import org.json.JSONObject
object PhoneUtils {
private val TAG: String = PhoneUtils.javaClass.name
fun initSdk(application: Application, callback: (Boolean) -> Unit = {}) {
val appid = "tqXxGGCH";
OneKeyLoginManager.getInstance().init(
application, appid
) { code, result ->
if (code == 1022) {
callback(true)
} else {
callback(false)
}
}
}
fun getPhoneInfo(callback: (Boolean, String) -> Unit = { t1, t2 -> {} }) {
OneKeyLoginManager.getInstance().getPhoneInfo { code, result ->
if (code == 1022) {
callback(true, result)
} else {
callback(false, "")
}
}
}
fun openLoginAuth(xPageFragment: XPageFragment, callback: (Boolean, String) -> Unit) {
xPageFragment.context?.let {
OneKeyLoginManager.getInstance().setAuthThemeConfig(getEConfig(it, xPageFragment))
OneKeyLoginManager.getInstance().openLoginAuth(false,
{ code, result ->
if (code != 1000) {
callback(false, "")
}
Log.i(TAG, "openLoginAuth: $result")
}
) { code, result ->
if (code == 1000) {
val json = JSONObject(result)
callback(true, json.getString("token"))
}
}
}
}
fun getEConfig(context: Context, xPageFragment: XPageFragment): ShanYanUIConfig? {
/************************************SDK固有控件 */
//登录按钮背景
// val mLoginBt: Drawable =
// context.getResources().getDrawable(R.drawable.login_demo_auth_bt_cus_e)
//协议复选框选中时图标
val mCheckedImg: Drawable =
context.getResources().getDrawable(R.mipmap.login_check_cus)
//协议复选框未选中时图标
val mCunheckedImg: Drawable =
context.getResources().getDrawable(R.mipmap.login_uncheck_cus)
//自定义控件(右上角“使用其他手机>”)
val mOtherTv = TextView(context)
mOtherTv.text = "其他方式登录"
mOtherTv.setTextColor(Color.parseColor("#FF408DFF"))
mOtherTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
val otherLayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
)
val screenHeight = AbScreenUtils.getScreenHeight(context, false)
val mOtherTvTop = AbScreenUtils.dp2px(context, 100f)
otherLayoutParams.setMargins(0, screenHeight - mOtherTvTop, 0, 0)
otherLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL)
mOtherTv.layoutParams = otherLayoutParams
// val mOtherTv2 = TextView(context)
// mOtherTv2.text = "新用户尊享3天免费VIP"
// mOtherTv2.setTextColor(Color.parseColor("#FFD0964E"))
// mOtherTv2.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
// val otherLayoutParams2 = RelativeLayout.LayoutParams(
// RelativeLayout.LayoutParams.WRAP_CONTENT,
// RelativeLayout.LayoutParams.WRAP_CONTENT
// )
// otherLayoutParams2.setMargins(0, AbScreenUtils.dp2px(context, 350f), 0, 0)
// otherLayoutParams2.addRule(RelativeLayout.CENTER_HORIZONTAL)
// mOtherTv.layoutParams = otherLayoutParams2
return ShanYanUIConfig.Builder()
/**设置弹窗样式
* @param isdialogTheme 是否是弹窗主题
* @param dialogWidth 弹窗宽度
* @param dialogHeight 弹窗高度
* @param dialogX 弹窗距离屏幕左测边距(左右等距)
* @param dialogY 弹窗距离屏幕顶部测边距
* @param isDialogBottom 弹窗是否显示到屏幕底部
*/
.setNavText("")
.setSloganHidden(true)
//导航栏标题设置成空
.setLogoHeight(130)
.setLogoWidth(130)
.setLogoOffsetY(30)
.setLogoImgPath(context.resources.getDrawable(R.mipmap.ic_launcher))
// .addCustomView(
// mOtherTv2, true, false, null
// )
.setNumFieldOffsetBottomY(330)
.setNumberSize(25)
.setLogBtnOffsetBottomY(230)
.setLogBtnWidth(AbScreenUtils.getScreenWidth(context, true) - 60)
.setLogBtnText("登录")
.setLogBtnTextSize(16)
.setLogBtnImgPath(context.resources.getDrawable(R.mipmap.login_btn_onekey))
.addCustomView(
mOtherTv, true, false
) { context, view -> PageOption.to(PhoneLoginFragment::class.java).open(xPageFragment) }
.setPrivacyState(false)
.setCheckedImgPath(mCheckedImg)
.setUncheckedImgPath(mCunheckedImg)
.setCheckBoxWH(20, 20)
.setPrivacyOffsetX(20)
.setcheckBoxOffsetXY(0, 5)
.setPrivacyOffsetBottomY(174)
.setPrivacyOffsetGravityLeft(true)
.setPrivacyTextSize(12)
.setOperatorPrivacyAtLast(true)
.setPrivacySmhHidden(true)
.setAppPrivacyColor(
Color.parseColor("#919095"),
Color.parseColor("#FF408DFF")
)
.setAppPrivacyOne(
"《用户协议》",
"https://api.253.com/api_doc/yin-si-zheng-ce/wei-hu-wang-luo-an-quan-sheng-ming.html"
)
.setAppPrivacyTwo(
"《隐私政策》",
"https://api.253.com/api_doc/yin-si-zheng-ce/ge-ren-xin-xi-bao-hu-sheng-ming.html"
) //设置隐私条款2名称和URL(名称,url)
//设置协议外部文字描述
.setPrivacyText("你已阅读并同意", "、", "和", "", "")
.build()
/**************************授权页配置(示例配置自上而下,可调整顺序) */
}
}
\ No newline at end of file
package com.ccwangluo.cc_quickly.utils
import com.tencent.mmkv.MMKV
/**
* SharedPreferences管理工具基类
*
* @author xuexiang
* @since 2018/11/27 下午5:16
*/
object SettingSPUtils {
private val IS_FIRST_OPEN_KEY = "is_first_open_key"
private val IS_AGREE_PRIVACY_KEY = "is_agree_privacy_key"
/**
* 是否是第一次启动
*/
/**
* 设置是否是第一次启动
*/
var isFirstOpen: Boolean
get() = MMKV.defaultMMKV().decodeBool(IS_FIRST_OPEN_KEY, true)
set(isFirstOpen) {
MMKV.defaultMMKV().putBoolean(IS_FIRST_OPEN_KEY, isFirstOpen)
}
/**
* @return 是否同意隐私政策
*/
var isAgreePrivacy: Boolean
get() = MMKV.defaultMMKV().decodeBool(IS_AGREE_PRIVACY_KEY, false)
set(isAgreePrivacy) {
MMKV.defaultMMKV().putBoolean(IS_AGREE_PRIVACY_KEY, isAgreePrivacy)
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.utils
import android.content.Context
import android.content.pm.PackageManager
import com.ccwangluo.accelerator.model.NetState
import com.xuexiang.xutil.net.NetworkUtils
import java.io.BufferedReader
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
object SysUtils {
fun getConnectivityStatus(): Boolean {
return NetworkUtils.isNetworkAvailable()
}
/**
* ping 网络状态
*/
suspend fun getNetPing(ip: String): NetState {
var delay: Int = -1
var lost = ""
val p = Runtime.getRuntime().exec("ping -c 4 ${ip}")
val buf = BufferedReader(InputStreamReader(p.inputStream))
var str: String? = String()
while (buf.readLine().also { str = it } != null) {
str?.let {
if (it.contains("packet loss")) {
val i = it.indexOf("received")
val j = it.indexOf("%")
// System.out.println("丢包率:"+str.substring(j-3, j+1));
lost = it.substring(i + 10, j)
}
if (it.contains("avg")) {
val i = it.indexOf("/", 20)
val j = it.indexOf(".", i)
delay = it.substring(i + 1, j).toInt()
}
}
}
return NetState(-1, -1, delay, lost)
}
/**
* 判断包是否安装
*/
fun isPackageInstall(context: Context, packageName: String): Boolean {
val packageManager: PackageManager = context.getPackageManager()
val packageInfos = packageManager.getInstalledPackages(0)
val packageNames: MutableList<String> = ArrayList()
if (packageInfos != null) {
for (i in packageInfos.indices) {
val packName = packageInfos[i].packageName
packageNames.add(packName)
}
}
return packageNames.contains(packageName)
}
fun getnetQuality(delay: Int): String {
when (delay) {
in (1..30) -> return "极快"
in (31..50) -> return "良好"
in (51..100) -> return "一般"
else -> return "差"
}
}
fun getAccTimeString(time: Long): String {
return "加速中 ${tranlateTime(time)} "
}
fun tranlateTime(long: Long): String {
val formatter = SimpleDateFormat("HH:mm:ss");//这里想要只保留分秒可以写成"mm:ss"
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
val hms = formatter.format(long);
return hms
}
}
\ No newline at end of file
/*
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
*
* 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 com.ccwangluo.cc_quickly.utils
import androidx.annotation.MainThread
import androidx.annotation.StringRes
import com.xuexiang.xui.XUI
import com.xuexiang.xui.widget.toast.XToast
/**
* xtoast 工具类
*
* @author xuexiang
* @since 2019-06-30 19:04
*/
object XToastUtils {
init {
XToast.Config.get()
.setYOffset(300)
.setToastTypeface(XUI.getDefaultTypeface())
.allowQueue(false)
}
@MainThread
fun toast(message: CharSequence) {
XToast.normal(XUI.getContext(), message).show()
}
@MainThread
fun toast(@StringRes message: Int) {
XToast.normal(XUI.getContext(), message).show()
}
@MainThread
fun toast(message: CharSequence, duration: Int) {
XToast.normal(XUI.getContext(), message, duration).show()
}
@MainThread
fun toast(@StringRes message: Int, duration: Int) {
XToast.normal(XUI.getContext(), message, duration).show()
}
//=============//
@MainThread
fun error(message: CharSequence) {
XToast.error(XUI.getContext(), message).show()
}
@MainThread
fun error(error: Exception) {
XToast.error(XUI.getContext(), error.message!!).show()
}
@MainThread
fun error(@StringRes message: Int) {
XToast.error(XUI.getContext(), message).show()
}
@MainThread
fun error(message: CharSequence, duration: Int) {
XToast.error(XUI.getContext(), message, duration).show()
}
@MainThread
fun error(@StringRes message: Int, duration: Int) {
XToast.error(XUI.getContext(), message, duration).show()
}
//=============//
@MainThread
fun success(message: CharSequence) {
XToast.success(XUI.getContext(), message).show()
}
@MainThread
fun success(@StringRes message: Int) {
XToast.success(XUI.getContext(), message).show()
}
@MainThread
fun success(message: CharSequence, duration: Int) {
XToast.success(XUI.getContext(), message, duration).show()
}
@MainThread
fun success(@StringRes message: Int, duration: Int) {
XToast.success(XUI.getContext(), message, duration).show()
}
//=============//
@MainThread
fun info(message: CharSequence) {
XToast.info(XUI.getContext(), message).show()
}
@MainThread
fun info(@StringRes message: Int) {
XToast.info(XUI.getContext(), message).show()
}
@MainThread
fun info(message: CharSequence, duration: Int) {
XToast.info(XUI.getContext(), message, duration).show()
}
@MainThread
fun info(@StringRes message: Int, duration: Int) {
XToast.info(XUI.getContext(), message, duration).show()
}
//=============//
@MainThread
fun warning(message: CharSequence) {
XToast.warning(XUI.getContext(), message).show()
}
@MainThread
fun warning(@StringRes message: Int) {
XToast.warning(XUI.getContext(), message).show()
}
@MainThread
fun warning(message: CharSequence, duration: Int) {
XToast.warning(XUI.getContext(), message, duration).show()
}
@MainThread
fun warning(@StringRes message: Int, duration: Int) {
XToast.warning(XUI.getContext(), message, duration).show()
}
}
\ No newline at end of file
package com.ccwangluo.accelerator.utils.http
object HttpConfig {
val baseUrl = "http://10.16.1.98:9002/api"
val UI_MAIN_URL = "http:wwww.baidu.com"
//隐私协议地址
val privacy_url = "http:wwww.baidu.com"
}
\ No newline at end of file
package com.ccwangluo.accelerator.utils.http
import com.ccwangluo.accelerator.model.BaseModel
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hjq.toast.ToastUtils
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.IOException
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
object HttpGo {
val okHttpClient: OkHttpClient
val gson: Gson
init {
okHttpClient = OkHttpClient().newBuilder()
.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(60, TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
//https支持
.hostnameVerifier { hostname, session -> true }
.sslSocketFactory(initSSLSocketFactory(), initTrustManager())
.build()
gson = Gson()
}
fun getClient(): OkHttpClient {
return okHttpClient;
}
inline fun <reified T> getSync(url: String): T? {
val request: Request = Request.Builder()
.url(HttpConfig.baseUrl + url)
.get()
.build()
val call = okHttpClient.newCall(request)
val response: Response = call.execute()
if (response.isSuccessful) {
return gson.fromJson(response.body?.string(), T::class.java)
} else {
ToastUtils.show("网络错误")
return null
}
}
val jsonType get() = "application/json; charset=utf-8".toMediaTypeOrNull()
/**
* 异步请求
*/
inline fun <reified T> postASync(
url: String,
param: MutableMap<String, String>,
crossinline callback: (T) -> Unit
) {
val body: RequestBody = gson.toJson(param).toString().toRequestBody(jsonType)
val request: Request = Request.Builder()
.url(HttpConfig.baseUrl + url)
.post(body)
.build()
val call = okHttpClient.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
ToastUtils.show("网络错误")
}
override fun onResponse(call: Call, response: Response) {
callback(gson.fromJson(response.body?.string(), T::class.java))
}
})
}
/**
* 同步请求
*/
inline fun <reified T> postSync(url: String, param: MutableMap<String, String>): BaseModel<T>? {
try {
val body: RequestBody = gson.toJson(param).toString().toRequestBody(jsonType)
val request: Request = Request.Builder()
.url(HttpConfig.baseUrl + url)
.post(body)
.build()
val call = okHttpClient.newCall(request)
val response: Response = call.execute()
if (response.isSuccessful) {
val string = response.body?.string()
println(string)
val type = object : TypeToken<BaseModel<T>>() {}.type
return gson.fromJson(string, type)
}
} catch (e : java.lang.Exception){
println(e)
ToastUtils.show("网络错误")
}
return null
}
private fun initSSLSocketFactory(): SSLSocketFactory {
var sslContext: SSLContext? = null
try {
sslContext = SSLContext.getInstance("SSL")
val xTrustArray = arrayOf(initTrustManager())
sslContext.init(
null,
xTrustArray, SecureRandom()
)
} catch (e: Exception) {
e.printStackTrace()
}
return sslContext!!.socketFactory
}
private fun initTrustManager(): X509TrustManager {
return object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
}
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
}
}
}
}
package com.ccwangluo.accelerator.wxapi;
import com.umeng.socialize.weixin.view.WXCallbackActivity;
public class WXEntryActivity extends WXCallbackActivity {
}
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="359"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2000"
android:repeatCount="-1">
</rotate>
</rotate>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="@color/colorPrimary"/>
<item android:state_checked="false" android:color="@color/colorPrimaryDark" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:color="@color/btn_blue_2"/>
<item android:state_enabled="false" android:color="#D8D8DA" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:color="#408DFF"/>
<item android:state_enabled="false" android:color="#D8D8DA" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#FF000000"/>
<item android:state_selected="false" android:color="#9E9E9E" />
</selector>
\ No newline at end of file
<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>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_pressed="true" android:drawable="@mipmap/back_icon_white"/>
<item android:state_checked="false" android:state_pressed="false" android:drawable="@mipmap/back_icon_black"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@mipmap/login_check_cus"/>
<item android:state_checked="false" android:drawable="@mipmap/login_uncheck_cus"/>
</selector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M3,13h8L11,3L3,3v10zM3,21h8v-6L3,15v6zM13,21h8L21,11h-8v10zM13,3v6h8L21,3h-8z" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z" />
</vector>
<?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>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@mipmap/mine_bu"/>
<item android:state_checked="false" android:drawable="@mipmap/mine_ga"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@mipmap/news_bu"/>
<item android:state_checked="false" android:drawable="@mipmap/news_ga"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@mipmap/quick_bu"/>
<item android:state_checked="false" android:drawable="@mipmap/quick_ga"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@mipmap/tab_bg_selected"/>
<item android:state_selected="false" android:drawable="@color/white"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="302dp"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="22dp"
android:textColor="#FF000000"
android:textSize="16sp" />
<TextView
android:id="@+id/dia_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FF4A4A4A"
android:textSize="15sp"
android:layout_marginLeft="29.5dp"
android:layout_marginTop="21dp"
android:layout_marginRight="29.5dp" />
<View
android:layout_width="302dp"
android:layout_marginTop="30dp"
android:layout_height="0.5dp"
android:background="#FFF0F0F0" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="53dp"
android:orientation="horizontal">
<TextView
android:id="@+id/btn_left"
android:gravity="center"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="取消"
android:textColor="#FFA8A8A8"
android:textSize="15sp" />
<View
android:layout_width="0.5dp"
android:layout_height="match_parent"
android:background="#FFF0F0F0" />
<TextView
android:id="@+id/btn_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textColor="#FF3CA4FD"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="308dp"
android:layout_height="381dp"
android:background="@mipmap/dialog_member"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="178.25dp"
android:text="您的加速特权已到期"
android:textColor="#FF000000"
android:textSize="18sp" />
<TextView
android:layout_width="232dp"
android:layout_height="47.5dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="14dp"
android:text="此游戏加速为会员服务,成为会员,体验一件加速的超快感吧!"
android:textColor="#FF343434"
android:textSize="15sp" />
<ImageView
android:id="@+id/dialog_memeber_btn"
android:layout_width="235dp"
android:layout_height="49dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="35dp"
android:background="@mipmap/dialog_member_btn" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="302dp"
android:orientation="vertical"
android:layout_height="418.5dp">
<FrameLayout
android:id="@+id/privacy_webview"
android:layout_width="match_parent"
android:layout_height="364.5dp"/>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="53.5dp">
<TextView
android:id="@+id/privacy_disagree"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="不同意"
android:textColor="#FFA8A8A8"
android:textSize="15sp"
android:layout_weight="1"
android:gravity="center"
/>
<TextView
android:id="@+id/privacy_agree"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="同意"
android:textColor="#FF3CA4FD"
android:textSize="15sp"
android:gravity="center"
/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?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"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:labelVisibilityMode="labeled"
app:itemTextColor="@color/color_state_menu_navi"
android:background="@color/nr_gray"
app:menu="@menu/bottom_nav_menu" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
\ No newline at end of file
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:background="@color/white"
android:focusableInTouchMode="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_marginTop="41.5dp"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/btn_back"
android:layout_marginLeft="20dp"
android:layout_width="10dp"
android:layout_height="17dp"
android:background="@drawable/back_icon"
/>
</LinearLayout>
<TextView
android:layout_marginTop="31.5dp"
android:layout_marginLeft="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入您的手机号"
android:textColor="#FF000000"
android:textSize="19.5sp"
/>
<TextView
android:layout_marginLeft="30dp"
android:layout_marginTop="11dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新用户尊享3天免费VIP"
android:textColor="#FFD0964E"
android:textSize="13sp"
/>
<com.xuexiang.xui.widget.layout.XUILinearLayout
android:layout_width="match_parent"
android:layout_height="49dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_marginBottom="10dp"
android:background="#F9F9F9"
android:orientation="horizontal"
app:xui_radius="10dp">
<EditText
android:id="@+id/phone_et"
android:layout_width="match_parent"
android:layout_height="30dp"
android:inputType="number"
android:background="@null"
android:layout_marginLeft="10dp"
android:textColor="#FF000000"
android:layout_weight="1"
android:hint="请输入手机号"
android:maxLength="11"
android:textSize="15sp"/>
<ImageView
android:id="@+id/phone_clear"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginRight="10dp"
android:background="@mipmap/edit_del"
/>
</com.xuexiang.xui.widget.layout.XUILinearLayout>
<com.xuexiang.xui.widget.layout.XUILinearLayout
android:layout_width="match_parent"
android:layout_height="49dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:gravity="center_vertical"
android:layout_marginBottom="10dp"
android:background="#F9F9F9"
android:orientation="horizontal"
app:xui_radius="10dp">
<EditText
android:id="@+id/auth_code_et"
android:layout_width="match_parent"
android:layout_height="30dp"
android:inputType="number"
android:background="@null"
android:layout_marginLeft="10dp"
android:textColor="#FF000000"
android:layout_weight="1"
android:hint="请输入验证码"
android:maxLength="6"
android:textSize="15sp"/>
<TextView
android:id="@+id/auth_code_wait"
android:layout_width="wrap_content"
android:layout_height="18.5dp"
android:visibility="gone"
android:text="60秒后重新获得验证码"
android:layout_marginRight="10dp"
android:textColor="#FFBEBEBE"
android:textSize="13sp"
/>
<TextView
android:id="@+id/auth_code_btn"
android:layout_width="wrap_content"
android:layout_height="18.5dp"
android:text="获取验证码"
android:layout_marginRight="10dp"
android:enabled="false"
android:textColor="@color/login_text_color"
android:textSize="13sp"
/>
</com.xuexiang.xui.widget.layout.XUILinearLayout>
<com.xuexiang.xui.widget.button.roundbutton.RoundButton
android:id="@+id/login"
android:layout_width="302dp"
android:layout_height="44dp"
android:layout_marginTop="21dp"
android:layout_gravity="center_horizontal"
android:text="登录"
android:textColor="#FFFFFFFF"
android:textSize="16sp"
android:enabled="false"
app:rb_backgroundColor="@color/login_btn_color"
app:rb_radius="44dp"/>
<LinearLayout
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="20dp"
android:gravity="center"
android:orientation="horizontal">
<CheckBox
android:id="@+id/cb_protocol"
android:layout_width="14dp"
android:layout_height="14dp"
style="@style/btn_checkbox"
/>
<TextView
android:layout_marginLeft="5dp"
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="您已阅读并同意"
android:textColor="#FF494949"
android:textSize="12sp"/>
<TextView
android:id="@+id/user_aggreement"
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="用户协议"
android:textColor="#FF408DFF"
android:textSize="12sp"/>
<TextView
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="和"
android:textColor="#FF494949"
android:textSize="12sp"/>
<TextView
android:id="@+id/privacy_aggreement"
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="隐私协议"
android:textColor="#FF408DFF"
android:textSize="12sp"/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" 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" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_browse_fragment"
android:name="com.github.shadowsocks.tv.MainFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context=".MainActivity"
tools:deviceIds="tv" <FrameLayout
tools:ignore="MergeRootFrame"/> android:id="@+id/mine_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout 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/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="36dp"
android:gravity="center_horizontal"
android:text="地下城与勇士 韩服"
android:textColor="#FFFFFFFF"
android:textSize="16sp" />
<com.xuexiang.xui.widget.layout.XUILinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="16dp"
android:background="@color/white"
android:orientation="vertical"
app:xui_hideRadiusSide="bottom"
app:xui_radius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:orientation="vertical">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:background="@mipmap/game_download" />
<TextView
android:layout_width="70dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="游戏下载"
android:textColor="#FF3B3B3B"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:orientation="vertical">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:background="@mipmap/game_group" />
<TextView
android:layout_width="70dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="万能宝藏群"
android:textColor="#FF3B3B3B"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:orientation="vertical">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:background="@mipmap/game_google" />
<TextView
android:layout_width="70dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="谷歌套件"
android:textColor="#FF3B3B3B"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="21dp"
android:layout_marginRight="20dp">
<ImageView
android:layout_width="17.95dp"
android:layout_height="14.6dp"
android:layout_gravity="center_vertical"
android:background="@mipmap/icon_notice" />
<com.xuexiang.xui.widget.textview.MarqueeTextView
android:id="@+id/tv_marquee"
android:layout_width="299dp"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:gravity="center"
android:text=""
android:textColor="#FF1A1A1A"
android:textSize="14sp"
app:mtv_isAutoDisplay="true"
app:mtv_isAutoFit="true" />
</LinearLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
style="@style/MyTablayoutstyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.xuexiang.xui.widget.layout.XUILinearLayout>
</LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/common_webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
\ No newline at end of file
<?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"
android:layout_width="32dp"
android:layout_height="22.5dp">
<ImageView
android:layout_alignParentBottom="true"
android:id="@+id/tab_icon"
android:layout_width="32dp"
android:layout_height="10.5dp"
android:src="@drawable/tab_bg" />
<com.google.android.material.textview.MaterialTextView
android:id="@android:id/text1"
android:layout_centerInParent="true"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/tab_color" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/quick"
android:title="加速"/>
<item
android:id="@+id/navigation_home"
android:icon="@drawable/news"
android:title="资讯"/>
<item
android:id="@+id/navigation_notifications"
android:icon="@drawable/mine"
android:title="我的"/>
</menu>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment