Commit e52e272f by amateur

'1'

0 parents
Showing 110 changed files with 5621 additions and 0 deletions
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="delegatedBuild" value="false" />
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
</configurations>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
/build
\ No newline at end of file
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 29
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.polysoft.nafmii"
minSdkVersion 24
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField "String", "API_HOST", "\"http://new.ynyc6666.com/shop/server/\""
buildConfigField "String", "WX_APPID", "\"1234567890\""
ndk {
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}
}
buildTypes {
release {
minifyEnabled true //是否混淆
zipAlignEnabled true //是否设置zip对齐优化
shrinkResources true // 移除无用的resource文件
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
pro { // 预生产
resValue "string", "app_name", "Nafmii-pro"
}
beta { // 测试
resValue "string", "app_name", "Nafmii-beta"
applicationIdSuffix "beta"
}
dev {
minifyEnabled false
resValue "string", "app_name", "Nafmii-dev"
applicationIdSuffix "dev"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
ndkVersion '20.0.5594570'
}
dependencies {
implementation 'androidx.wear:wear:1.0.0'
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'ren.yale.android:cachewebviewlib:2.1.8'
implementation 'com.alibaba:fastjson:1.1.72.android'
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:6.7.0'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
implementation 'com.github.bumptech.glide:glide:4.12.0'
implementation 'me.jessyan:autosize:1.2.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
compileOnly 'com.google.android.wearable:wearable:2.6.0'
}
\ 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 dalvik.**
-dontwarn com.tencent.smtt.**
-keep class com.tencent.smtt.** {
*;
}
-keep class com.tencent.tbs.** {
*;
}
\ No newline at end of file
package com.polysoft.nafmii;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.polysoft.nafmill", appContext.getPackageName());
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.polysoft.nafmii">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_TASKS" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Nafmii.Fullscreen"
android:usesCleartextTraffic="true">
<activity android:name=".activity.InputUrlActivity"></activity>
<meta-data
android:name="design_width_in_dp"
android:value="360" />
<meta-data
android:name="design_height_in_dp"
android:value="750" />
<activity
android:name=".activity.MainActivity"
android:theme="@style/Nafmii.Fullscreen.NoTitleBar.Main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.BaseActivity" />
<activity android:name=".activity.WebviewActivity" />
<activity
android:name=".activity.HomeActivity"
android:theme="@style/Nafmii.Fullscreen.NoTitleBar" />
<activity
android:name=".activity.GuideActivity"
android:theme="@style/Nafmii.Fullscreen.NoTitleBar" />
<service
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
android:label="dexopt"
android:process=":dexopt" />
</application>
</manifest>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,maximun-scale=1,mininum-scsle=1,user-scale=1">
<title>file chooser</title>
<style>
.filechooser{
width:95%;
height: 50px;
-webkit-background-clip: border-box;
}
</style>
<script >
var display=function (){
var path=document.getElementById("file_chooser").textContent;
document.getElementById("filechooser_display").innerHTML("<b>"+path+"</b>");
}
</script>
</head>
<body style="padding-top:100px;">
<ul class="listview">
<li class="listviewItem">
<fieldset class="itemset">
<input class="filechooser" id="file_chooser" type="file" placeholder="file path" onchange="display()" oninput="display()"><br>
<p id="filechooser_display"></p>
<div class="line_black"></div>
</fieldset>
</li>
</ul>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, maximum-scale=1, minimum-scale=1, user-scale=1">
<title></title>
<style type="text/css" rel="stylesheet">
.line{
width:100%;
background: #000000;
height: 1px;
margin-top: 5px;
margin-bottom: 5px;
}
</style>
</head>
<body>
<video style="width:100%; height: auto;" controls>
<source src=http://125.64.133.74/data9/userfiles/video02/2014/12/11/2796948-280-068-1452.mp4 >
</video>
<div style="width:100%;height: 25px;"></div>
<button onclick="click_x5()" style="width:50%;height: 50px; float: left"> x5模式全屏</button>
<button onclick="click_normal()" style="width:50%;height: 50px;"> 普通模式全屏</button>
<div class="line"></div>
<button onclick="click_LiteWnd()" style="width:50%;height: 50px; float: left"> 小窗模式</button>
<button onclick="click_normal()" style="width:50%;height: 50px;"> 关闭小窗模式</button>
<div class="line"></div>
<button onclick="click_PageVideo()" style="width:50%;height: 50px; float: left"> 页面内全屏</button>
<button onclick="click_normal()" style="width:50%;height: 50px;"> 关闭页面内全屏</button>
</body>
<script type="text/javascript" >
function click_x5 (){
Android.onX5ButtonClicked();
location.reload(false);
}
function click_normal(){
Android.onCustomButtonClicked();
location.reload(false);
}
function click_LiteWnd(){
Android.onLiteWndButtonClicked();
location.reload(false);
}
function click_PageVideo(){
Android.onPageVideoClicked();
location.reload(false);
}
</script>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<meta name="viewport" context="width=device-width, maximum-scale=1, minimum-scale=0.5, user-scale=no">
<title><h2>请长按一下html元素</h2></title>
<style type="text/css" rel="stylesheet">
h2,p,input{
font-size: 50px;
}
</style>
</head>
<body>
<h2>请长按一下html元素</h2><br>
<p style="width:100%;">hello world!</p><br>
<input style="width: 100%;" placeholder="文本编辑区" type="text"><br>
<img src="image/nearly.png" style="width: 100% ; height: auto;" ><br>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,maximun-scale=1,mininum-scsle=1,user-scale=1">
<title>首页</title>
<style>
</style>
<script >
</script>
</head>
<body>
</body>
</html>
\ No newline at end of file
const NativeInteface = [
'callNativePay',
'callNativeShare',
'callNativeAppInfo',
'callNativeCamera',
'callNativeAlbum',
'callNativeUpdate',
'callNativeMobile'
]
const JsInteface = [
'payResult',
'shareResult',
'photoResult',
'appInfoResult'
]
class Inteface {
constructor() {
this.listeners = {}
this.__init()
}
on (methodName, callback) {
this.listeners[methodName] = callback
}
__init () {
NativeInteface.forEach(methodName => {
this[methodName] = (data, jsMethodName, callback) => {
try {
if (jsMethodName) {
this.listeners[jsMethodName] = callback
}
const json = JSON.stringify(jsMethodName && { jsMethodName, data } || { data })
if (window.$NativeApi) {
window.$NativeApi[methodName](json)
} else if (window.webkit) {
window.webkit.messageHandlers[methodName](json)
}
} catch (e) {
callback && callback()
console.warn("===========无效,非内置调用", methodName);
}
}
})
JsInteface.forEach(methodName => {
this[methodName] = (data) => {
const objValue = data ? JSON.parse(data) : data
this.listeners[methodName](objValue)
}
})
}
}
window.$api = new Inteface()
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h3>WebSocket 测试</h3>
<p id="result"></p>
</body>
<script type="text/javascript">
var my_websocket = new WebSocket("ws://127.0.0.1:55555");
var result = document.getElementById("result");
if(!my_websocket){
result.innerHTML += "无法创建websocket实例<br>";
window.console.log("websocket can not be created!");
}else{
window.console.log("websocket create success!");
}
my_websocket.onerror = function(){
result.innerHTML+="websocket连接失败<br>";
}
my_websocket.onclose = function(){
result.innerHTML+="websocket 关闭<br>";
}
my_websocket.onmessage = function(event){
result.innerHTML+="收到数据:"+event.data+" <br>";
}
</script>
</html>
\ No newline at end of file
package com.polysoft.nafmii;
import android.app.Application;
import com.polysoft.nafmii.utils.CtxUtils;
import com.polysoft.nafmii.webview.X5Core;
import me.jessyan.autosize.AutoSizeConfig;
import ren.yale.android.cachewebviewlib.WebViewCacheInterceptor;
import ren.yale.android.cachewebviewlib.WebViewCacheInterceptorInst;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
CtxUtils.setApplication(this);
AutoSizeConfig.getInstance()
.setDesignWidthInDp(414)
.setDesignHeightInDp(896);
WebViewCacheInterceptor.Builder builder = new WebViewCacheInterceptor.Builder(this);
builder.setDebug(BuildConfig.DEBUG);
WebViewCacheInterceptorInst.getInstance().init(builder);
}
}
package com.polysoft.nafmii.activity;
import android.os.Bundle;
import android.view.KeyEvent;
import androidx.appcompat.app.AppCompatActivity;
import com.polysoft.nafmii.utils.StatusBarUtils;
import com.polysoft.nafmii.utils.ToastUtils;
import java.util.Timer;
import java.util.TimerTask;
public class BaseActivity extends AppCompatActivity {
private boolean mBackKeyPressed = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
this.initStatusBar();
}
private void initStatusBar() {
//沉浸式代码配置
//当FitsSystemWindows设置 true 时,会在屏幕最上方预留出状态栏高度的 padding
StatusBarUtils.setRootViewFitsSystemWindows(this, false);
//设置状态栏透明
StatusBarUtils.setTranslucentStatus(this);
//一般的手机的状态栏文字和图标都是白色的, 可如果你的应用也是纯白色的, 或导致状态栏文字看不清
//所以如果你是这种情况,请使用以下代码, 设置状态使用深色文字图标风格, 否则你可以选择性注释掉这个if内容
if (!StatusBarUtils.setStatusBarDarkTheme(this, true)) {
//如果不支持设置深色风格 为了兼容总不能让状态栏白白的看不清, 于是设置一个状态栏颜色为半透明,
//这样半透明+白=灰, 状态栏的文字能看得清
StatusBarUtils.setStatusBarColor(this, 0x55000000);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (!this.mBackKeyPressed) {
ToastUtils.showLong("再点击一次退出程序");
this.mBackKeyPressed = true;
new Timer().schedule(new TimerTask() {
@Override
public void run() {
mBackKeyPressed = false;
}
}, 1000);
} else {
finish();
System.exit(0);
}
return false;
}
return super.onKeyDown(keyCode, event);
}
}
\ No newline at end of file
package com.polysoft.nafmii.activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RadioButton;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.polysoft.nafmii.R;
import com.polysoft.nafmii.utils.IntentUtils;
import com.polysoft.nafmii.utils.SpUtils;
import java.util.ArrayList;
import java.util.List;
public class GuideActivity extends BaseActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_guide);
this.initView();
}
private void initView() {
ViewPager viewPager = super.findViewById(R.id.guide_viewpager);
List<View> viewList = this.initGuideImage();
viewPager.setAdapter(new ViewPagerAdapter(viewList));
viewPager.setCurrentItem(0);
RadioButton point1 = super.findViewById(R.id.guide_point1);
RadioButton point2 = super.findViewById(R.id.guide_point2);
RadioButton point3 = super.findViewById(R.id.guide_point3);
RadioButton[] points = new RadioButton[]{point1, point2, point3};
View goHomeBtn = super.findViewById(R.id.guide_btn_gohome);
goHomeBtn.setOnClickListener(this);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
points[position].setChecked(true);
boolean show = viewList.size() == (position + 1);
goHomeBtn.setVisibility(show ? View.VISIBLE : View.GONE);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private List<View> initGuideImage() {
int[] arrays = new int[]{R.mipmap.guide1_bg, R.mipmap.guide2_bg, R.mipmap.guide3_bg};
List<View> viewList = new ArrayList<>();
int match = ViewGroup.LayoutParams.MATCH_PARENT;
for (int i = 0; i < arrays.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setImageResource(arrays[i]);
imageView.setLayoutParams(new ViewGroup.LayoutParams(match, match));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
viewList.add(imageView);
}
return viewList;
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.guide_btn_gohome) {
SpUtils.putBoolean("isFirstRun", true);
IntentUtils.startActivity(this, HomeActivity.class);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return false;
}
class ViewPagerAdapter extends PagerAdapter {
private List<View> viewList = new ArrayList<>();
ViewPagerAdapter(List<View> viewList) {
this.viewList = viewList;
}
@Override
public int getCount() {
return this.viewList.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View view = this.viewList.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(viewList.get(position));
}
}
}
\ No newline at end of file
package com.polysoft.nafmii.activity;
import android.view.KeyEvent;
import android.view.View;
import android.widget.RadioButton;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.polysoft.nafmii.R;
import com.polysoft.nafmii.enums.ModulesEnum;
import com.polysoft.nafmii.fragment.FingerprintDialogFragment;
import com.polysoft.nafmii.fragment.ModulesFragmentMgr;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HomeActivity extends WebviewActivity implements View.OnClickListener, ModulesFragmentMgr.OnChangeModuleListener {
private ModulesFragmentMgr modulesMgr;
private HashMap<ModulesEnum, RadioButton> moduleViewsMap;
@Override
public void onCoreInitFinished(boolean flag) {
super.setContentView(R.layout.activity_home);
this.initView();
this.initHomeModule();
}
private void initView() {
super.findViewById(R.id.home_footer_group).setVisibility(View.VISIBLE);
HashMap<ModulesEnum, RadioButton> modulesMap = new HashMap<>();
modulesMap.put(ModulesEnum.HOME, super.findViewById(R.id.home_btn_home));
modulesMap.put(ModulesEnum.MEMBER, super.findViewById(R.id.home_btn_member));
modulesMap.put(ModulesEnum.LEARN, super.findViewById(R.id.home_btn_learn));
modulesMap.put(ModulesEnum.MY, super.findViewById(R.id.home_btn_my));
Iterator<Map.Entry<ModulesEnum, RadioButton>> iterator = modulesMap.entrySet().iterator();
while (iterator.hasNext()) {
iterator.next().getValue().setOnClickListener(this);
}
this.moduleViewsMap = modulesMap;
}
private void initHomeModule() {
FragmentManager fragmentManager = super.getSupportFragmentManager();
int containerId = R.id.home_container_framelayout;
this.modulesMgr = new ModulesFragmentMgr(fragmentManager, containerId);
this.modulesMgr.addChangeModuleLsitener(this);
this.modulesMgr.showInitFragment(new ModulesEnum[]{
ModulesEnum.HOME, ModulesEnum.MEMBER,
ModulesEnum.LEARN, ModulesEnum.MY
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.home_btn_home:
this.modulesMgr.showModule(ModulesEnum.HOME);
break;
case R.id.home_btn_member:
this.modulesMgr.showModule(ModulesEnum.MEMBER);
break;
case R.id.home_btn_learn:
this.modulesMgr.showModule(ModulesEnum.LEARN);
break;
case R.id.home_btn_my:
this.modulesMgr.showModule(ModulesEnum.MY);
break;
default:
break;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (!this.modulesMgr.onBackStack()) {
return false;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public void changeModule(ModulesEnum module, Fragment fragment) {
RadioButton moduleButton = this.moduleViewsMap.get(module);
if (null != moduleButton) {
moduleButton.setChecked(true);
}
}
}
\ No newline at end of file
package com.polysoft.nafmii.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import com.polysoft.nafmii.R;
public class InputUrlActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_input_url);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText inputUrl = findViewById(R.id.input_url);
String url = inputUrl.getText().toString();
}
});
}
}
\ No newline at end of file
package com.polysoft.nafmii.activity;
import android.Manifest;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.polysoft.nafmii.R;
import com.polysoft.nafmii.constants.ServerApi;
import com.polysoft.nafmii.enums.StateEnum;
import com.polysoft.nafmii.fragment.AdvertisementFragment;
import com.polysoft.nafmii.fragment.FingerprintDialogFragment;
import com.polysoft.nafmii.net.RequestBack;
import com.polysoft.nafmii.utils.IntentUtils;
import com.polysoft.nafmii.utils.PermissionUtils;
import com.polysoft.nafmii.utils.SpUtils;
import com.polysoft.nafmii.utils.ToastUtils;
import com.polysoft.nafmii.webview.X5Core;
public class MainActivity extends BaseActivity {
private static final String TAG = MainActivity.class.getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.checkAndRequestPermission();
}
private void checkAndRequestPermission() {
String[] permissions = new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
};
PermissionUtils.requestMorePermissions(this, permissions);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode != PermissionUtils.REQUEST_CODE) {
return;
}
if (this.checkPermissionSetting()) {
X5Core.init();
this.showAdvertisement();
}
}
private boolean checkPermissionSetting() {
// 必要读写权限申请失败
if (!PermissionUtils.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ToastUtils.showLong("请授权APP必要运行权限");
new CountDownTimer(2000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
}
@Override
public void onFinish() {
PermissionUtils.toAppSetting(MainActivity.this);
}
}.start();
return false;
}
return true;
}
private void showAdvertisement() {
if (!SpUtils.getBoolean("isFirstRun", false)) {
IntentUtils.startActivity(this, GuideActivity.class);
return;
}
ServerApi.get(ServerApi.getAdvertSettings, new RequestBack<JSONObject>() {
@Override
protected void onResponse(StateEnum state, JSONObject data, String message) {
if (state == StateEnum.OK) {
JSONArray jsonArray = data.getJSONArray("item");
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject item = jsonArray.getJSONObject(i);
Fragment fragment = AdvertisementFragment.getInstance(item.toJSONString());
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.main_framelayout, fragment).commit();
return;
}
}
}
});
}
}
\ No newline at end of file
package com.polysoft.nafmii.activity;
import android.os.Bundle;
import com.polysoft.nafmii.webview.X5Core;
public abstract class WebviewActivity extends BaseActivity implements X5Core.InitCallback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
X5Core.setInitCallback(this);
}
}
\ No newline at end of file
package com.polysoft.nafmii.broadcast;
import android.content.Context;
import android.content.Intent;
public class PhotosReceiver extends Receiver<String> {
public static final String ACTION_CAMERA = "com.polysoft.nafmii.action_camera";
public static final String ACTION_ALBUM = "com.polysoft.nafmii.action_album";
protected PhotosReceiver(Context context) {
super(context);
}
public static Receiver<String> getInstance(Context context) {
Receiver<String> receiver = getReceiver(PhotosReceiver.class);
return null != receiver ? receiver : new PhotosReceiver(context.getApplicationContext());
}
public static void sendBroadcastCamera(Context context, String filepath) {
Intent intent = new Intent().setAction(ACTION_CAMERA);
intent.putExtra("data", filepath);
onSendBroadcast(context, intent);
}
public static void sendBroadcastAlbum(Context context, String filepath) {
Intent intent = new Intent().setAction(ACTION_ALBUM);
intent.putExtra("data", filepath);
onSendBroadcast(context, intent);
}
@Override
protected String[] getActions() {
return new String[]{ACTION_CAMERA, ACTION_ALBUM};
}
@Override
protected String onReceiverData(String action, Intent intent) {
if (ACTION_CAMERA.equals(action)) {
return intent.getStringExtra("data");
} else if (ACTION_ALBUM.equals(action)) {
return intent.getStringExtra("data");
}
return null;
}
}
package com.polysoft.nafmii.broadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public abstract class Receiver<T> extends BroadcastReceiver {
private static final Map<String, Receiver> registerMap = new HashMap<>();
protected final Context context;
protected final Map<String, ReceiverListener<T>> listenerMap = new HashMap<>();
private final String KEY_DEFAULT_LISTENER = "DEFAULT_LISTENER";
protected Receiver(Context context) {
this.context = context;
}
protected static <T> Receiver<T> getReceiver(Class<? extends Receiver> receiver) {
return registerMap.get(receiver.getName());
}
protected static void onSendBroadcast(Context context, Intent intent) {
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
protected abstract String[] getActions();
protected abstract T onReceiverData(String action, Intent intent);
public void register() {
if (null != getReceiver(this.getClass())) {
return;
}
IntentFilter filter = new IntentFilter();
String[] actions = this.getActions();
for (int i = 0; i < actions.length; i++) {
filter.addAction(actions[i]);
}
LocalBroadcastManager.getInstance(this.context).registerReceiver(this, filter);
registerMap.put(this.getClass().getName(), this);
}
public void unregister() {
this.listenerMap.clear();
if (null == getReceiver(this.getClass())) {
return;
}
registerMap.remove(this.getClass().getName());
LocalBroadcastManager.getInstance(this.context).unregisterReceiver(this);
}
public void addDefaultListener(ReceiverListener<T> listener) {
this.addListener(KEY_DEFAULT_LISTENER, listener);
}
public void addListener(String key, ReceiverListener<T> listener) {
this.listenerMap.put(key, listener);
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
T data = this.onReceiverData(action, intent);
Iterator<String> iterator = this.listenerMap.keySet().iterator();
while (iterator.hasNext()) {
ReceiverListener<T> listener = this.listenerMap.get(iterator.next());
// 同步判断
if (null != listener) {
listener.onReceiverResult(action, data);
}
}
}
}
package com.polysoft.nafmii.broadcast;
public interface ReceiverListener<T> {
void onReceiverResult(String action, T data);
}
package com.polysoft.nafmii.broadcast;
import android.content.Context;
import android.content.Intent;
import com.alibaba.fastjson.JSON;
import com.polysoft.nafmii.wechat.ShareResult;
public class ShareReceiver extends Receiver<ShareResult> {
public static final String ACTION = "com.polysoft.nafmii.action_share";
protected ShareReceiver(Context context) {
super(context);
}
public static Receiver<ShareResult> getInstance(Context context) {
Receiver<ShareResult> receiver = getReceiver(ShareReceiver.class);
return null != receiver ? receiver : new ShareReceiver(context.getApplicationContext());
}
public static void sendBroadcast(Context context, ShareResult data) {
Intent intent = new Intent().setAction(ACTION);
intent.putExtra("data", JSON.toJSONString(data));
onSendBroadcast(context, intent);
}
@Override
protected String[] getActions() {
return new String[]{ACTION};
}
@Override
protected ShareResult onReceiverData(String action, Intent intent) {
if (ACTION.equals(action)) {
String dataJson = intent.getStringExtra("data");
return JSON.parseObject(dataJson, ShareResult.class);
}
return null;
}
}
package com.polysoft.nafmii.constants;
import com.polysoft.nafmii.BuildConfig;
import com.polysoft.nafmii.enums.StateEnum;
import com.polysoft.nafmii.net.OkhttpApi;
import com.polysoft.nafmii.net.RequestBack;
import java.util.Map;
public class ServerApi {
public static final String url_version = "";
public static final String getAdvertSettings = "storeSetting/getAdvertSettings";
public static <T> void get(String url, RequestBack<T> callback) {
get(url, null, callback);
}
public static <T> void get(String url, Map<String, String> param, RequestBack<T> callback) {
String newUrl = BuildConfig.API_HOST + url;
OkhttpApi.doGet(newUrl, param, callback);
}
public static <T> void post(String url, String param, RequestBack<T> callback) {
String newUrl = BuildConfig.API_HOST + url;
OkhttpApi.doPost(newUrl, param, callback);
}
}
package com.polysoft.nafmii.enums;
public enum ModulesEnum {
HOME("home", "file:///android_asset/webpage/fileChooser.html"),
MEMBER("member", "file:///android_asset/webpage/fileChooser.html"),
LEARN("learn", "http://debugtbs.qq.com"),
MY("my", "http://192.168.43.183:8080");
public final String name;
public final String webUrl;
ModulesEnum(String tag, String url) {
this.name = tag;
this.webUrl = url;
}
public static ModulesEnum findModule(String name) {
if (HOME.name.equals(name)) {
return HOME;
} else if (MEMBER.name.equals(name)) {
return MEMBER;
} else if (LEARN.name.equals(name)) {
return LEARN;
} else if (MY.name.equals(name)) {
return MY;
}
return null;
}
}
package com.polysoft.nafmii.enums;
public enum StateEnum {
OK(0, "成功"),
FAIL(-1, "失败");
public final int state;
public final String name;
StateEnum(int state, String name) {
this.state = state;
this.name = name;
}
}
package com.polysoft.nafmii.fragment;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.DrawableImageViewTarget;
import com.bumptech.glide.request.transition.Transition;
import com.polysoft.nafmii.R;
import com.polysoft.nafmii.activity.HomeActivity;
import com.polysoft.nafmii.utils.IntentUtils;
public class AdvertisementFragment extends Fragment implements View.OnClickListener {
private ImageView mImgView;
private TextView mCountDown;
private AdvertisementFragment() {
}
public static Fragment getInstance(String data) {
Fragment fragment = new AdvertisementFragment();
Bundle bundle = new Bundle();
bundle.putString("data", data);
fragment.setArguments(bundle);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_advertisement, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.advertisement_pass).setOnClickListener(this);
this.mImgView = view.findViewById(R.id.advertisement_imgview);
this.mCountDown = view.findViewById(R.id.advertisement_countdown);
this.loadAdvertisementImage();
}
@Override
public void onClick(View v) {
this.gotoHome();
}
private void loadAdvertisementImage() {
String json = getArguments().getString("data");
JSONObject item = JSON.parseObject(json);
String id = item.getString("id");
String description = item.getString("description");
String picture = item.getString("picture");
String url = item.getString("url");
Glide.with(getContext()).load(picture).into(new DrawableImageViewTarget(this.mImgView){
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
super.onResourceReady(resource, transition);
startCountDown();
}
});
}
private void startCountDown() {
long unit = 1000, maxSecond = 5;
mCountDown.setText(String.format("%ds", maxSecond));
new CountDownTimer(maxSecond * unit, unit) {
@Override
public void onTick(long millisUntilFinished) {
long second = millisUntilFinished / unit;
Log.d("CountDownTimer", "onTick: " + second);
mCountDown.setText(String.format("%ds", second));
}
@Override
public void onFinish() {
gotoHome();
}
}.start();
}
private synchronized void gotoHome() {
if (null != getActivity() && !getActivity().isFinishing()) {
IntentUtils.startActivity(getActivity(), HomeActivity.class);
}
}
}
package com.polysoft.nafmii.fragment;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import com.polysoft.nafmii.R;
import javax.crypto.Cipher;
@TargetApi(23)
public class FingerprintDialogFragment extends DialogFragment {
private FingerprintManager fingerprintManager;
private CancellationSignal mCancellationSignal;
private Cipher mCipher;
private Activity mActivity;
private TextView errorMsg;
/**
* 标识是否是用户主动取消的认证。
*/
private boolean isSelfCancelled;
public void setCipher(Cipher cipher) {
mCipher = cipher;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mActivity = getActivity();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fingerprintManager = getContext().getSystemService(FingerprintManager.class);
setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fingerprint_dialog, container, false);
errorMsg = v.findViewById(R.id.error_msg);
TextView cancel = v.findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
stopListening();
}
});
return v;
}
@Override
public void onResume() {
super.onResume();
// 开始指纹认证监听
startListening(mCipher);
}
@Override
public void onPause() {
super.onPause();
// 停止指纹认证监听
stopListening();
}
private void startListening(Cipher cipher) {
isSelfCancelled = false;
mCancellationSignal = new CancellationSignal();
fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), mCancellationSignal, 0, new FingerprintManager.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
if (!isSelfCancelled) {
errorMsg.setText(errString);
if (errorCode == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {
Toast.makeText(mActivity, errString, Toast.LENGTH_SHORT).show();
dismiss();
}
}
}
@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
errorMsg.setText(helpString);
}
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
Toast.makeText(mActivity, "指纹认证成功", Toast.LENGTH_SHORT).show();
mActivity.finish();
}
@Override
public void onAuthenticationFailed() {
errorMsg.setText("指纹认证失败,请再试一次");
}
}, null);
}
private void stopListening() {
if (mCancellationSignal != null) {
mCancellationSignal.cancel();
mCancellationSignal = null;
isSelfCancelled = true;
}
}
}
package com.polysoft.nafmii.fragment;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.List;
public class HomeViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments;
public HomeViewPagerAdapter(@NonNull FragmentManager fm, List<Fragment> fragments) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
this.mFragments = fragments;
}
@NonNull
@Override
public Fragment getItem(int position) {
return this.mFragments.get(position);
}
@Override
public int getCount() {
return this.mFragments.size();
}
}
package com.polysoft.nafmii.fragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.polysoft.nafmii.enums.ModulesEnum;
import java.util.List;
public class ModulesFragmentMgr implements FragmentManager.OnBackStackChangedListener {
private FragmentManager manager;
private int containerId;
private ModulesEnum currentModule;
private OnChangeModuleListener changeListener;
public ModulesFragmentMgr(FragmentManager manager, int containerId) {
this.manager = manager;
this.containerId = containerId;
}
public void addChangeModuleLsitener(OnChangeModuleListener listener) {
this.changeListener = listener;
}
public void showInitFragment(ModulesEnum[] modules) {
for (int i = 1; i < modules.length; i++) {
this.addModuleFragment(modules[i]);
}
Fragment fragment = this.addModuleFragment(modules[0]);
FragmentTransaction transaction = this.manager.beginTransaction();
transaction.show(fragment).commitNow();
this.setCurrentModule(modules[0]);
}
public Fragment getCurrentFragment() {
String tag = this.currentModule.name;
return this.manager.findFragmentByTag(tag);
}
public boolean onBackStack() {
if (this.manager.getBackStackEntryCount() > 0) {
this.manager.addOnBackStackChangedListener(this);
this.manager.popBackStack();
return false;
}
return true;
}
public void showModule(ModulesEnum module) {
if (module.name.equals(this.currentModule.name)) {
return;
}
Fragment fragment = this.findFragment(module);
FragmentTransaction transaction = this.manager.beginTransaction();
transaction.hide(this.getCurrentFragment());
transaction.addToBackStack("").show(fragment).commit();
this.setCurrentModule(module);
}
public Fragment findFragment(ModulesEnum module) {
Fragment fragment = this.manager.findFragmentByTag(module.name);
if (null == fragment) {
return this.addModuleFragment(module);
}
return fragment;
}
private Fragment addModuleFragment(ModulesEnum module) {
FragmentTransaction transaction = this.manager.beginTransaction();
Fragment fragment = WebViewFragment.newInstances(module.webUrl);
transaction.add(this.containerId, fragment, module.name).hide(fragment).commitNow();
return fragment;
}
private void setCurrentModule(ModulesEnum module) {
this.currentModule = module;
if (null != this.changeListener) {
Fragment fragment = this.getCurrentFragment();
this.changeListener.changeModule(module, fragment);
}
}
@Override
public void onBackStackChanged() {
List<Fragment> fragments = this.manager.getFragments();
for (int i = 0; i < fragments.size(); i++) {
Fragment fragment = fragments.get(i);
if (fragment.isVisible()) {
setCurrentModule(ModulesEnum.findModule(fragment.getTag()));
return ;
}
}
}
public static interface OnChangeModuleListener {
void changeModule(ModulesEnum module, Fragment fragment);
}
}
package com.polysoft.nafmii.fragment;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ValueCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.polysoft.nafmii.R;
import com.polysoft.nafmii.webview.JavaToJsinterface;
import com.polysoft.nafmii.webview.JsToJavaInterface;
import com.polysoft.nafmii.webview.MyWebViewClient;
import com.polysoft.nafmii.webview.WebviewLoadListener;
import com.polysoft.nafmii.webview.X5WebviewUtils;
import com.tencent.smtt.sdk.WebView;
public class WebViewFragment extends Fragment implements WebviewLoadListener {
private View rootView;
private ViewGroup layout;
private WebView webView;
public static WebViewFragment newInstances(String url) {
WebViewFragment fragment = new WebViewFragment();
Bundle bundle = new Bundle();
bundle.putString("url", url);
fragment.setArguments(bundle);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
if (null == this.rootView) {
this.rootView = inflater.inflate(R.layout.fragment_webview, container, false);
}
return this.rootView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.layout = view.findViewById(R.id.webview_layout);
this.initWebview();
}
private void initWebview() {
WebView webView = X5WebviewUtils.create(getActivity());
webView.setWebViewClient(new MyWebViewClient(this));
JsToJavaInterface nativeApi = new JsToJavaInterface(getActivity(), new JavaToJsinterface(webView));
webView.addJavascriptInterface(nativeApi, "$NativeApi");
this.layout.removeAllViews();
int match = ViewGroup.LayoutParams.MATCH_PARENT;
this.layout.addView(webView, new ViewGroup.LayoutParams(match, match));
this.webView = webView;
Bundle bundle = getArguments();
String url = bundle.getString("url", "");
this.webView.loadUrl(url);
}
@Override
public void onDestroy() {
super.onDestroy();
X5WebviewUtils.destroy(this.webView);
}
@Override
public void onWebviewLoad(int type, Object param) {
if (type == WebviewLoadListener.TYPE_FINISH) {
} else if (type == WebviewLoadListener.TYPE_ERROR) {
}
}
@Override
public void onShowFileChooser(ValueCallback<Uri[]> filePathCallback, String[] acceptTypes, boolean isCapture) {
}
}
\ No newline at end of file
package com.polysoft.nafmii.net;
import com.polysoft.nafmii.utils.IOUtils;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class OkhttpApi {
private static OkHttpClient client = null;
private OkhttpApi() {
}
public static OkHttpClient getInstance() {
if (client == null) {
synchronized (OkhttpApi.class) {
if (client == null) {
client = new OkHttpClient();
}
}
}
return client;
}
public static void doGet(String url, RequestBack callback) {
doGet(url, null, callback);
}
public static void doGet(String url, Map<String, String> param, RequestBack callback) {
HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder();
if (null != param && !param.isEmpty()) {
for (Map.Entry<String, String> entry : param.entrySet()) {
builder.addQueryParameter(entry.getKey(), entry.getValue());
}
}
Request.Builder request = buildRequest(1);
request.url(builder.build()).get();
getInstance().newCall(request.build()).enqueue(new CallbackImpl(callback));
}
public static void doPost(String url, String param, RequestBack callback) {
MediaType mediaType = MediaType.parse("application/json;charset=UTF-8");
RequestBody body = RequestBody.create(param, mediaType);
Request.Builder request = buildRequest(1);
request.url(url).post(body);
getInstance().newCall(request.build()).enqueue(new CallbackImpl(callback));
}
public static void doUpload(String url, File file, RequestBack callback) {
doUpload(url, file, null, callback);
}
public static void doUpload(String url, File file, Map<String, String> param, RequestBack callback) {
}
public static void doDownload(String url, final File file) {
Request request = new Request.Builder().url(url).build();
getInstance().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (!response.isSuccessful()) {
return;
}
ResponseBody body = response.body();
long total = body.contentLength();
FileOutputStream fos = new FileOutputStream(file);
InputStream stream = body.byteStream();
try {
int len = 0;
long sum = 0;
byte[] buffer = new byte[1024 * 4];
while ((len = stream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
// sum += len;
// int progress = (int) (sum * 100 / total );
}
} catch (Exception e) {
IOUtils.close(fos);
IOUtils.close(stream);
}
}
});
}
private static Request.Builder buildRequest(int type) {
Request.Builder request = new Request.Builder();
request.addHeader("X-Requested-With", "XMLHttpRequest");
if (type == 1) { // post / get
request.addHeader("Content-Type", "application/json");
} else if (type == 2) {
request.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
} else if (type == 3) { // 文件上传下载
request.addHeader("Content-Type", "multipart/form-data");
}
return request;
}
private static class CallbackImpl implements Callback {
private final RequestBack callback;
public CallbackImpl(RequestBack callback) {
this.callback = callback;
}
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
if (null != this.callback) {
this.callback.onParseResponse(call, null, e);
}
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (null != this.callback) {
this.callback.onParseResponse(call, response, null);
}
}
}
}
package com.polysoft.nafmii.net;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.polysoft.nafmii.enums.StateEnum;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import okhttp3.Call;
import okhttp3.Response;
public abstract class RequestBack<T> {
void onParseResponse(Call call, Response response, Exception e) {
int resCode = response.code();
if (resCode < 200 && resCode >= 300) {
String message = String.format("网络错误(%d)", resCode);
this.onResponse(StateEnum.FAIL, null, message);
return;
}
String string = null;
try {
string = response.body().string();
} catch (IOException ioException) {
ioException.printStackTrace();
}
if (TextUtils.isEmpty(string)) {
String message = "返回数据格式错误";
this.onResponse(StateEnum.FAIL, null, message);
return;
}
JSONObject res = JSON.parseObject(string);
int status = res.getInteger("status");
if (status == 200) {
String json = res.getString("obj");
Log.d("onParseResponse", "onParseResponse: " + json);
Type type = this.getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] arguments = parameterizedType.getActualTypeArguments();
if (this.isTypeCalss(arguments[0], String.class)) {
this.onResponse(StateEnum.OK, (T) json, null);
} else if (this.isTypeCalss(arguments[0], JSONObject.class)) {
JSONObject data = res.getJSONObject("obj");
this.onResponse(StateEnum.OK, (T) data, null);
} else {
T data = JSON.parseObject(json, type);
this.onResponse(StateEnum.OK, data, null);
}
} else {
this.onResponse(StateEnum.FAIL, null, "解析异常");
}
} else {
String message = res.getString("msg");
this.onResponse(StateEnum.FAIL, null, message);
}
}
protected abstract void onResponse(StateEnum state, T data, String message);
private boolean isTypeCalss(Type type, Class c) {
return c.toString().equals(type.toString());
}
}
package com.polysoft.nafmii.utils;
import android.app.Application;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
public class CtxUtils {
private static Application application;
public static void setApplication(Application application) {
CtxUtils.application = application;
}
public static Application getApplication() {
return CtxUtils.application;
}
public static PackageInfo getPackageInfo() {
PackageManager manager = getApplication().getPackageManager();
String name = getApplication().getPackageName();
try {
return manager.getPackageInfo(name, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
package com.polysoft.nafmii.utils;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import androidx.core.content.FileProvider;
import java.io.File;
public class FileProviderUtils {
public static Uri getUriForFile(Context context, File file) {
if (Build.VERSION.SDK_INT >= 24) {
return getUriForFile24(context, file);
} else {
return Uri.fromFile(file);
}
}
public static Uri getUriForFile24(Context context, File file) {
String authority = context.getPackageName() + ".fileprovider";
return FileProvider.getUriForFile(context, authority, file);
}
public static String getUriPath(Context context, Uri uri) {
String[] filePathColumn = {MediaStore.MediaColumns.DATA};
Cursor cursor = context.getContentResolver().query(uri, filePathColumn, null, null, null);
try {
if (null != cursor) {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(filePathColumn[0]);
return cursor.getString(idx);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != cursor) {
cursor.close();
}
}
return uri.getPath();
}
public static void setIntentDataAndType(Context context,
Intent intent,
String type,
File file,
boolean writeAble) {
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(getUriForFile(context, file), type);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (writeAble) {
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
} else {
intent.setDataAndType(Uri.fromFile(file), type);
}
}
}
package com.polysoft.nafmii.utils;
import java.io.Closeable;
import java.io.IOException;
public class IOUtils {
public static void close(Closeable io) {
if (null == io) {
return;
}
try {
io.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.polysoft.nafmii.utils;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import java.io.File;
public class IntentUtils {
public static final int ACTIVITY_CODE_CHOOSERFILE = 0x1000;
public static final int ACTIVITY_CODE_CAMERA = 0x1001;
public static final int ACTIVITY_CODE_ALBUM = 0x1002;
public static Intent chooserIntent(Context context) {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (null != captureIntent.resolveActivity(context.getPackageManager())) {
String filePath = getTakePhotoPath(context);
File imgFile = new File(filePath);
if (!imgFile.getParentFile().exists()) {
imgFile.getParentFile().mkdirs();
}
Uri imageUri = FileProviderUtils.getUriForFile(context, imgFile);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件
}
Intent Photo = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent chooserIntent = Intent.createChooser(Photo, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
return chooserIntent;
}
return null;
}
public static Intent openCamera(Context context) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(getTakePhotoPath(context));
Uri imgUri = FileProviderUtils.getUriForFile(context, file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
return intent;
}
public static Intent openAlbum(Context context) {
Intent intent = new Intent(Intent.ACTION_PICK, null);
File file = new File(getTakePhotoPath(context));
FileProviderUtils.setIntentDataAndType(context, intent, "image/*", file, false);
return intent;
}
public static void startActivity(Activity activity, Class<? extends Activity> target) {
startActivity(activity, new Intent(activity, target));
}
public static void startActivity(Activity activity, Class<? extends Activity> target, Bundle bundle) {
Intent intent = new Intent(activity, target);
intent.putExtra("data", bundle);
startActivity(activity, intent);
}
public static void startActivity(Activity activity, Intent intent) {
activity.startActivity(intent);
activity.finish();
}
public static String getTakePhotoPath(Context context) {
return Environment.getExternalStorageDirectory()
+ File.separator + "Android"
+ File.separator + "data"
+ File.separator + context.getPackageName()
+ File.separator + "temp.jpg";
}
}
package com.polysoft.nafmii.utils;
import android.os.Environment;
import android.text.TextUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class OSUtils {
private static final String KEY_DISPLAY_ID = "ro.build.display.id";
private static final String KEY_BASE_OS_VERSION = "ro.build.version.base_os";
private static final String KEY_CLIENT_ID_BASE = "ro.com.google.clientidbase";
// 小米 : MIUI
private static final String KEY_MIUI_VERSION = "ro.build.version.incremental"; // "7.6.15"
private static final String KEY_MIUI_VERSION_NANE = "ro.miui.ui.version.name"; // "V8"
private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code"; // "6"
private static final String VALUE_MIUI_CLIENT_ID_BASE = "android-xiaomi";
// 华为 : EMUI
private static final String KEY_EMUI_VERSION = "ro.build.version.emui"; // "EmotionUI_3.0"
private static final String KEY_EMUI_API_LEVEL = "ro.build.hw_emui_api_level"; //
private static final String KEY_EMUI_SYSTEM_VERSION = "ro.confg.hw_systemversion"; //
// "T1-A21wV100R001C233B008_SYSIMG"
// 魅族 : Flyme
private static final String KEY_FLYME_PUBLISHED = "ro.flyme.published"; // "true"
private static final String KEY_FLYME_SETUP = "ro.meizu.setupwizard.flyme"; // "true"
private static final String VALUE_FLYME_DISPLAY_ID_CONTAIN = "Flyme"; // "Flyme OS 4.5.4.2U"
// OPPO : ColorOS
private static final String KEY_COLOROS_VERSION = "ro.oppo.theme.version"; // "703"
private static final String KEY_COLOROS_THEME_VERSION = "ro.oppo.version"; // ""
private static final String KEY_COLOROS_ROM_VERSION = "ro.rom.different.version"; //
private static final String VALUE_COLOROS_BASE_OS_VERSION_CONTAIN = "OPPO"; // "OPPO/R7sm
// "ColorOS2.1"
// /R7sm:5.1.1/LMY47V/1440928800:user/release-keys"
private static final String VALUE_COLOROS_CLIENT_ID_BASE = "android-oppo";
// vivo : FuntouchOS
private static final String KEY_FUNTOUCHOS_BOARD_VERSION = "ro.vivo.board.version"; // "MD"
private static final String KEY_FUNTOUCHOS_OS_NAME = "ro.vivo.os.name"; // "Funtouch"
private static final String KEY_FUNTOUCHOS_OS_VERSION = "ro.vivo.os.version"; // "3.0"
private static final String KEY_FUNTOUCHOS_DISPLAY_ID = "ro.vivo.os.build.display.id"; //
// "FuntouchOS_3.0"
private static final String KEY_FUNTOUCHOS_ROM_VERSION = "ro.vivo.rom.version"; // "rom_3.1"
private static final String VALUE_FUNTOUCHOS_CLIENT_ID_BASE = "android-vivo";
// Samsung
private static final String VALUE_SAMSUNG_BASE_OS_VERSION_CONTAIN = "samsung"; // "samsung
// /zeroltezc/zeroltechn:6.0.1/MMB29K/G9250ZCU2DQD1:user/release-keys"
private static final String VALUE_SAMSUNG_CLIENT_ID_BASE = "android-samsung";
// Sony
private static final String KEY_SONY_PROTOCOL_TYPE = "ro.sony.irremote.protocol_type"; // "2"
private static final String KEY_SONY_ENCRYPTED_DATA = "ro.sony.fota.encrypteddata"; //
private static final String VALUE_SONY_CLIENT_ID_BASE = "android-sonyericsson";
// "supported"
// 乐视 : eui
private static final String KEY_EUI_VERSION = "ro.letv.release.version"; // "5.9.023S"
private static final String KEY_EUI_VERSION_DATE = "ro.letv.release.version_date"; // "5.9
// .023S_03111"
private static final String KEY_EUI_NAME = "ro.product.letv_name"; // "乐1s"
private static final String KEY_EUI_MODEL = "ro.product.letv_model"; // "Letv X500"
// 金立 : amigo
private static final String KEY_AMIGO_ROM_VERSION = "ro.gn.gnromvernumber"; // "GIONEE ROM5.0
// .16"
private static final String KEY_AMIGO_SYSTEM_UI_SUPPORT = "ro.gn.amigo.systemui.support"; //
private static final String VALUE_AMIGO_DISPLAY_ID_CONTAIN = "amigo"; // "amigo3.5.1"
// "yes"
private static final String VALUE_AMIGO_CLIENT_ID_BASE = "android-gionee";
// 酷派 : yulong
private static final String KEY_YULONG_VERSION_RELEASE = "ro.yulong.version.release"; // "5.1
// .046.P1.150921.8676_M01"
private static final String KEY_YULONG_VERSION_TAG = "ro.yulong.version.tag"; // "LC"
private static final String VALUE_YULONG_CLIENT_ID_BASE = "android-coolpad";
// HTC : Sense
private static final String KEY_SENSE_BUILD_STAGE = "htc.build.stage"; // "2"
private static final String KEY_SENSE_BLUETOOTH_SAP = "ro.htc.bluetooth.sap"; // "true"
private static final String VALUE_SENSE_CLIENT_ID_BASE = "android-htc-rev";
// LG : LG
private static final String KEY_LG_SW_VERSION = "ro.lge.swversion"; // "D85720b"
private static final String KEY_LG_SW_VERSION_SHORT = "ro.lge.swversion_short"; // "V20b"
private static final String KEY_LG_FACTORY_VERSION = "ro.lge.factoryversion"; // "LGD857AT-00
// -V20b-CUO-CN-FEB-17-2015+0"
// 联想
private static final String KEY_LENOVO_DEVICE = "ro.lenovo.device"; // "phone"
private static final String KEY_LENOVO_PLATFORM = "ro.lenovo.platform"; // "qualcomm"
private static final String KEY_LENOVO_ADB = "ro.lenovo.adb"; // "apkctl,speedup"
private static final String VALUE_LENOVO_CLIENT_ID_BASE = "android-lenovo";
/**
* ROM 类型
*/
private static final ROM ROM_TYPE = initRomType();
/**
* 获取 ROM 类型
*
* @return ROM
*/
public static ROM getRomType() {
return ROM_TYPE;
}
public static boolean isMiui() {
return getRomType() == ROM.EMUI;
}
public static boolean isFlyme() {
return getRomType() == ROM.Flyme;
}
/**
* 初始化 ROM 类型
*/
private static ROM initRomType() {
ROM rom = ROM.Other;
FileInputStream is = null;
try {
Properties buildProperties = new Properties();
is = new FileInputStream(new File(Environment.getRootDirectory(), "build.prop"));
buildProperties.load(is);
if (buildProperties.containsKey(KEY_MIUI_VERSION_NANE) || buildProperties.containsKey(KEY_MIUI_VERSION_CODE)) {
// MIUI
rom = ROM.MIUI;
if (buildProperties.containsKey(KEY_MIUI_VERSION_NANE)) {
String versionName = buildProperties.getProperty(KEY_MIUI_VERSION_NANE);
if (!TextUtils.isEmpty(versionName) && versionName.matches("[Vv]\\d+")) { // V8
try {
rom.setBaseVersion(Integer.parseInt(versionName.split("[Vv]")[1]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (buildProperties.containsKey(KEY_MIUI_VERSION)) {
String versionStr = buildProperties.getProperty(KEY_MIUI_VERSION);
if (!TextUtils.isEmpty(versionStr) && versionStr.matches("[\\d.]+")) {
rom.setVersion(versionStr);
}
}
} else if (buildProperties.containsKey(KEY_EMUI_VERSION) || buildProperties.containsKey(KEY_EMUI_API_LEVEL)
|| buildProperties.containsKey(KEY_EMUI_SYSTEM_VERSION)) {
// EMUI
rom = ROM.EMUI;
if (buildProperties.containsKey(KEY_EMUI_VERSION)) {
String versionStr = buildProperties.getProperty(KEY_EMUI_VERSION);
Matcher matcher = Pattern.compile("EmotionUI_([\\d.]+)").matcher(versionStr); // EmotionUI_3.0
if (!TextUtils.isEmpty(versionStr) && matcher.find()) {
try {
String version = matcher.group(1);
rom.setVersion(version);
rom.setBaseVersion(Integer.parseInt(version.split("\\.")[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (buildProperties.containsKey(KEY_FLYME_SETUP) || buildProperties.containsKey(KEY_FLYME_PUBLISHED)) {
// Flyme
rom = ROM.Flyme;
if (buildProperties.containsKey(KEY_DISPLAY_ID)) {
String versionStr = buildProperties.getProperty(KEY_DISPLAY_ID);
Matcher matcher =
Pattern.compile("Flyme[^\\d]*([\\d.]+)[^\\d]*").matcher(versionStr);
// Flyme OS 4.5.4.2U
if (!TextUtils.isEmpty(versionStr) && matcher.find()) {
try {
String version = matcher.group(1);
rom.setVersion(version);
rom.setBaseVersion(Integer.parseInt(version.split("\\.")[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (buildProperties.containsKey(KEY_COLOROS_VERSION) || buildProperties.containsKey(KEY_COLOROS_THEME_VERSION)
|| buildProperties.containsKey(KEY_COLOROS_ROM_VERSION)) {
// ColorOS
rom = ROM.ColorOS;
if (buildProperties.containsKey(KEY_COLOROS_ROM_VERSION)) {
String versionStr = buildProperties.getProperty(KEY_COLOROS_ROM_VERSION);
Matcher matcher = Pattern.compile("ColorOS([\\d.]+)").matcher(versionStr); //
// ColorOS2.1
if (!TextUtils.isEmpty(versionStr) && matcher.find()) {
try {
String version = matcher.group(1);
rom.setVersion(version);
rom.setBaseVersion(Integer.parseInt(version.split("\\.")[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (buildProperties.containsKey(KEY_FUNTOUCHOS_OS_NAME) || buildProperties.containsKey(KEY_FUNTOUCHOS_OS_VERSION)
|| buildProperties.containsKey(KEY_FUNTOUCHOS_DISPLAY_ID)) {
// FuntouchOS
rom = ROM.FuntouchOS;
if (buildProperties.containsKey(KEY_FUNTOUCHOS_OS_VERSION)) {
String versionStr = buildProperties.getProperty(KEY_FUNTOUCHOS_OS_VERSION);
if (!TextUtils.isEmpty(versionStr) && versionStr.matches("[\\d.]+")) { // 3.0
try {
rom.setVersion(versionStr);
rom.setBaseVersion(Integer.parseInt(versionStr.split("\\.")[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (buildProperties.containsKey(KEY_EUI_VERSION) || buildProperties.containsKey(KEY_EUI_NAME)
|| buildProperties.containsKey(KEY_EUI_MODEL)) {
// EUI
rom = ROM.EUI;
if (buildProperties.containsKey(KEY_EUI_VERSION)) {
String versionStr = buildProperties.getProperty(KEY_EUI_VERSION);
Matcher matcher = Pattern.compile("([\\d.]+)[^\\d]*").matcher(versionStr); //
// 5.9.023S
if (!TextUtils.isEmpty(versionStr) && matcher.find()) {
try {
String version = matcher.group(1);
rom.setVersion(version);
rom.setBaseVersion(Integer.parseInt(version.split("\\.")[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (buildProperties.containsKey(KEY_AMIGO_ROM_VERSION) || buildProperties.containsKey(KEY_AMIGO_SYSTEM_UI_SUPPORT)) {
// amigo
rom = ROM.AmigoOS;
if (buildProperties.containsKey(KEY_DISPLAY_ID)) {
String versionStr = buildProperties.getProperty(KEY_DISPLAY_ID);
Matcher matcher =
Pattern.compile("amigo([\\d.]+)[a-zA-Z]*").matcher(versionStr); //
// "amigo3.5.1"
if (!TextUtils.isEmpty(versionStr) && matcher.find()) {
try {
String version = matcher.group(1);
rom.setVersion(version);
rom.setBaseVersion(Integer.parseInt(version.split("\\.")[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (buildProperties.containsKey(KEY_SONY_PROTOCOL_TYPE) || buildProperties.containsKey(KEY_SONY_ENCRYPTED_DATA)) {
// Sony
rom = ROM.Sony;
} else if (buildProperties.containsKey(KEY_YULONG_VERSION_RELEASE) || buildProperties.containsKey(KEY_YULONG_VERSION_TAG)) {
// YuLong
rom = ROM.YuLong;
} else if (buildProperties.containsKey(KEY_SENSE_BUILD_STAGE) || buildProperties.containsKey(KEY_SENSE_BLUETOOTH_SAP)) {
// Sense
rom = ROM.Sense;
} else if (buildProperties.containsKey(KEY_LG_SW_VERSION) || buildProperties.containsKey(KEY_LG_SW_VERSION_SHORT)
|| buildProperties.containsKey(KEY_LG_FACTORY_VERSION)) {
// LG
rom = ROM.LG;
} else if (buildProperties.containsKey(KEY_LENOVO_DEVICE) || buildProperties.containsKey(KEY_LENOVO_PLATFORM)
|| buildProperties.containsKey(KEY_LENOVO_ADB)) {
// Lenovo
rom = ROM.Lenovo;
} else if (buildProperties.containsKey(KEY_DISPLAY_ID)) {
String displayId = buildProperties.getProperty(KEY_DISPLAY_ID);
if (!TextUtils.isEmpty(displayId)) {
if (displayId.contains(VALUE_FLYME_DISPLAY_ID_CONTAIN)) {
return ROM.Flyme;
} else if (displayId.contains(VALUE_AMIGO_DISPLAY_ID_CONTAIN)) {
return ROM.AmigoOS;
}
}
} else if (buildProperties.containsKey(KEY_BASE_OS_VERSION)) {
String baseOsVersion = buildProperties.getProperty(KEY_BASE_OS_VERSION);
if (!TextUtils.isEmpty(baseOsVersion)) {
if (baseOsVersion.contains(VALUE_COLOROS_BASE_OS_VERSION_CONTAIN)) {
return ROM.ColorOS;
} else if (baseOsVersion.contains(VALUE_SAMSUNG_BASE_OS_VERSION_CONTAIN)) {
return ROM.SamSung;
}
}
} else if (buildProperties.containsKey(KEY_CLIENT_ID_BASE)) {
String clientIdBase = buildProperties.getProperty(KEY_CLIENT_ID_BASE);
switch (clientIdBase) {
case VALUE_MIUI_CLIENT_ID_BASE:
return ROM.MIUI;
case VALUE_COLOROS_CLIENT_ID_BASE:
return ROM.ColorOS;
case VALUE_FUNTOUCHOS_CLIENT_ID_BASE:
return ROM.FuntouchOS;
case VALUE_SAMSUNG_CLIENT_ID_BASE:
return ROM.SamSung;
case VALUE_SONY_CLIENT_ID_BASE:
return ROM.Sony;
case VALUE_YULONG_CLIENT_ID_BASE:
return ROM.YuLong;
case VALUE_SENSE_CLIENT_ID_BASE:
return ROM.Sense;
case VALUE_LENOVO_CLIENT_ID_BASE:
return ROM.Lenovo;
case VALUE_AMIGO_CLIENT_ID_BASE:
return ROM.AmigoOS;
default:
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return rom;
}
public enum ROM {
MIUI, // 小米
Flyme, // 魅族
EMUI, // 华为
ColorOS, // OPPO
FuntouchOS, // vivo
SmartisanOS, // 锤子
EUI, // 乐视
Sense, // HTC
AmigoOS, // 金立
_360OS, // 奇酷360
NubiaUI, // 努比亚
H2OS, // 一加
YunOS, // 阿里巴巴
YuLong, // 酷派
SamSung, // 三星
Sony, // 索尼
Lenovo, // 联想
LG, // LG
Google, // 原生
Other; // CyanogenMod, Lewa OS, 百度云OS, Tencent OS, 深度OS, IUNI OS, Tapas OS, Mokee
private int baseVersion = -1;
private String version;
public int getBaseVersion() {
return baseVersion;
}
void setBaseVersion(int baseVersion) {
this.baseVersion = baseVersion;
}
public String getVersion() {
return version;
}
void setVersion(String version) {
this.version = version;
}
}
}
package com.polysoft.nafmii.utils;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.List;
public class PermissionUtils {
public static final int REQUEST_CODE = 10000;
/**
* 检测权限
*
* @return true:已授权; false:未授权;
*/
public static boolean checkPermission(Context context, String permission) {
if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED)
return true;
else
return false;
}
/**
* 检测多个权限
*
* @return 未授权的权限
*/
public static List<String> checkMorePermissions(Context context, String[] permissions) {
List<String> permissionList = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
if (!checkPermission(context, permissions[i]))
permissionList.add(permissions[i]);
}
return permissionList;
}
/**
* 请求权限
*/
public static void requestPermission(Context context, String permission) {
ActivityCompat.requestPermissions((Activity) context, new String[]{permission}, REQUEST_CODE);
}
/**
* 请求多个权限
*/
public static void requestMorePermissions(Context context, List permissionList) {
String[] permissions = (String[]) permissionList.toArray(new String[permissionList.size()]);
requestMorePermissions(context, permissions);
}
/**
* 请求多个权限
*/
public static void requestMorePermissions(Context context, String[] permissions) {
ActivityCompat.requestPermissions((Activity) context, permissions, REQUEST_CODE);
}
/**
* 判断是否已拒绝过权限
*
* @return
* @describe :如果应用之前请求过此权限但用户拒绝,此方法将返回 true;
* -----------如果应用第一次请求权限或 用户在过去拒绝了权限请求,
* -----------并在权限请求系统对话框中选择了 Don't ask again 选项,此方法将返回 false。
*/
public static boolean judgePermission(Context context, String permission) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, permission))
return true;
else
return false;
}
/**
* 检测权限并请求权限:如果没有权限,则请求权限
*/
public static boolean checkAndRequestPermission(Context context, String permission) {
if (!checkPermission(context, permission)) {
requestPermission(context, permission);
return false;
}
return true;
}
/**
* 检测并请求多个权限
*/
public static boolean checkAndRequestMorePermissions(Context context, String[] permissions) {
List<String> permissionList = checkMorePermissions(context, permissions);
if (!permissionList.isEmpty()) {
requestMorePermissions(context, permissionList);
return false;
}
return true;
}
/**
* 检测权限
*
* @describe:具体实现由回调接口决定
*/
public static void checkPermission(Context context, String permission, PermissionCheckCallBack callBack) {
if (checkPermission(context, permission)) { // 用户已授予权限
callBack.onHasPermission();
} else {
if (judgePermission(context, permission)) // 用户之前已拒绝过权限申请
callBack.onUserHasAlreadyTurnedDown(permission);
else // 用户之前已拒绝并勾选了不在询问、用户第一次申请权限。
callBack.onUserHasAlreadyTurnedDownAndDontAsk(permission);
}
}
/**
* 检测多个权限
*
* @describe:具体实现由回调接口决定
*/
public static void checkMorePermissions(Context context, String[] permissions, PermissionCheckCallBack callBack) {
List<String> permissionList = checkMorePermissions(context, permissions);
if (permissionList.size() == 0) { // 用户已授予权限
callBack.onHasPermission();
} else {
boolean isFirst = true;
for (int i = 0; i < permissionList.size(); i++) {
String permission = permissionList.get(i);
if (judgePermission(context, permission)) {
isFirst = false;
break;
}
}
String[] unauthorizedMorePermissions = (String[]) permissionList.toArray(new String[permissionList.size()]);
if (isFirst)// 用户之前已拒绝过权限申请
callBack.onUserHasAlreadyTurnedDownAndDontAsk(unauthorizedMorePermissions);
else // 用户之前已拒绝并勾选了不在询问、用户第一次申请权限。
callBack.onUserHasAlreadyTurnedDown(unauthorizedMorePermissions);
}
}
/**
* 检测并申请权限
*/
public static void checkAndRequestPermission(Context context, String permission, PermissionRequestSuccessCallBack callBack) {
if (checkPermission(context, permission)) {// 用户已授予权限
callBack.onHasPermission();
} else {
requestPermission(context, permission);
}
}
/**
* 检测并申请多个权限
*/
public static void checkAndRequestMorePermissions(Context context, String[] permissions, PermissionRequestSuccessCallBack callBack) {
List<String> permissionList = checkMorePermissions(context, permissions);
if (permissionList.size() == 0) { // 用户已授予权限
callBack.onHasPermission();
} else {
requestMorePermissions(context, permissionList);
}
}
/**
* 判断权限是否申请成功
*/
public static boolean isPermissionRequestSuccess(int[] grantResults) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
return true;
else
return false;
}
/**
* 用户申请权限返回
*/
public static void onRequestPermissionResult(Context context, String permission, int[] grantResults, PermissionCheckCallBack callback) {
if (PermissionUtils.isPermissionRequestSuccess(grantResults)) {
callback.onHasPermission();
} else {
if (PermissionUtils.judgePermission(context, permission)) {
callback.onUserHasAlreadyTurnedDown(permission);
} else {
callback.onUserHasAlreadyTurnedDownAndDontAsk(permission);
}
}
}
/**
* 用户申请多个权限返回
*/
public static void onRequestMorePermissionsResult(Context context, String[] permissions, PermissionCheckCallBack callback) {
boolean isBannedPermission = false;
List<String> permissionList = checkMorePermissions(context, permissions);
if (permissionList.size() == 0)
callback.onHasPermission();
else {
for (int i = 0; i < permissionList.size(); i++) {
if (!judgePermission(context, permissionList.get(i))) {
isBannedPermission = true;
break;
}
}
// 已禁止再次询问权限
if (isBannedPermission)
callback.onUserHasAlreadyTurnedDownAndDontAsk(permissions);
else // 拒绝权限
callback.onUserHasAlreadyTurnedDown(permissions);
}
}
/**
* 跳转到权限设置界面
*/
public static void toAppSetting(Context context) {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
intent.setAction(Intent.ACTION_VIEW);
intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
intent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
}
context.startActivity(intent);
}
public interface PermissionRequestSuccessCallBack {
/**
* 用户已授予权限
*/
void onHasPermission();
}
public interface PermissionCheckCallBack {
/**
* 用户已授予权限
*/
void onHasPermission();
/**
* 用户已拒绝过权限
*
* @param permission:被拒绝的权限
*/
void onUserHasAlreadyTurnedDown(String... permission);
/**
* 用户已拒绝过并且已勾选不再询问选项、用户第一次申请权限;
*
* @param permission:被拒绝的权限
*/
void onUserHasAlreadyTurnedDownAndDontAsk(String... permission);
}
}
package com.polysoft.nafmii.utils;
import android.content.Context;
import android.content.SharedPreferences;
public class SpUtils {
private static final String SP_NAME = "NAFMII";
public static void putBoolean(String key, boolean val) {
SharedPreferences.Editor edit = getSpMgr().edit();
edit.putBoolean(key, val).commit();
}
public static boolean getBoolean(String key, boolean def) {
return getSpMgr().getBoolean(key, def);
}
public static void putString(String key, String val) {
SharedPreferences.Editor edit = getSpMgr().edit();
edit.putString(key, val).commit();
}
public static String getString(String key, String def) {
return getSpMgr().getString(key, def);
}
private static SharedPreferences getSpMgr() {
return CtxUtils.getApplication().getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
}
}
package com.polysoft.nafmii.utils;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.annotation.IntDef;
import com.polysoft.nafmii.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class StatusBarUtils {
public final static int TYPE_MIUI = 0;
public final static int TYPE_FLYME = 1;
public final static int TYPE_M = 3;//6.0
@IntDef({TYPE_MIUI, TYPE_FLYME, TYPE_M})
@Retention(RetentionPolicy.SOURCE)
@interface ViewType {
}
/**
* 修改状态栏颜色,支持4.4以上版本
*
* @param colorId 颜色
*/
public static void setStatusBarColor(Activity activity, int colorId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.setStatusBarColor(colorId);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//使用SystemBarTintManager,需要先将状态栏设置为透明
setTranslucentStatus(activity);
SystemBarTintManager systemBarTintManager = new SystemBarTintManager(activity);
systemBarTintManager.setStatusBarTintEnabled(true);//显示状态栏
systemBarTintManager.setStatusBarTintColor(colorId);//设置状态栏颜色
}
}
/**
* 设置状态栏透明
*/
@TargetApi(19)
public static void setTranslucentStatus(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
//导航栏颜色也可以正常设置
//window.setNavigationBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
attributes.flags |= flagTranslucentStatus;
//int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; //attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
/**
* 代码实现android:fitsSystemWindows
*
* @param activity
*/
public static void setRootViewFitsSystemWindows(Activity activity, boolean fitSystemWindows) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ViewGroup winContent = (ViewGroup) activity.findViewById(android.R.id.content);
if (winContent.getChildCount() > 0) {
ViewGroup rootView = (ViewGroup) winContent.getChildAt(0);
if (rootView != null) {
rootView.setFitsSystemWindows(fitSystemWindows);
}
}
}
}
/**
* 设置状态栏深色浅色切换
*/
public static boolean setStatusBarDarkTheme(Activity activity, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setStatusBarFontIconDark(activity, TYPE_M, dark);
} else if (OSUtils.isMiui()) {
setStatusBarFontIconDark(activity, TYPE_MIUI, dark);
} else if (OSUtils.isFlyme()) {
setStatusBarFontIconDark(activity, TYPE_FLYME, dark);
} else {//其他情况
return false;
}
return true;
}
return false;
}
/**
* 设置 状态栏深色浅色切换
*/
public static boolean setStatusBarFontIconDark(Activity activity, @ViewType int type, boolean dark) {
switch (type) {
case TYPE_MIUI:
return setMiuiUI(activity, dark);
case TYPE_FLYME:
return setFlymeUI(activity, dark);
case TYPE_M:
default:
return setCommonUI(activity, dark);
}
}
//设置6.0 状态栏深色浅色切换
public static boolean setCommonUI(Activity activity, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decorView = activity.getWindow().getDecorView();
if (decorView != null) {
int vis = decorView.getSystemUiVisibility();
if (dark) {
vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
if (decorView.getSystemUiVisibility() != vis) {
decorView.setSystemUiVisibility(vis);
}
return true;
}
}
return false;
}
//设置Flyme 状态栏深色浅色切换
public static boolean setFlymeUI(Activity activity, boolean dark) {
try {
Window window = activity.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
if (dark) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//设置MIUI 状态栏深色浅色切换
public static boolean setMiuiUI(Activity activity, boolean dark) {
try {
Window window = activity.getWindow();
Class<?> clazz = activity.getWindow().getClass();
@SuppressLint("PrivateApi") Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
int darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getDeclaredMethod("setExtraFlags", int.class, int.class);
extraFlagField.setAccessible(true);
if (dark) { //状态栏亮色且黑色字体.
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
} else {
extraFlagField.invoke(window, 0, darkModeFlag);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//获取状态栏高度
public static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
package com.polysoft.nafmii.utils;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import java.lang.reflect.Method;
public class SystemBarTintManager {
static {
// Android allows a system property to override the presence of the navigation bar.
// Used by the emulator.
// See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Class c = Class.forName("android.os.SystemProperties");
Method m = c.getDeclaredMethod("get", String.class);
m.setAccessible(true);
sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
} catch (Throwable e) {
sNavBarOverride = null;
}
}
}
/**
* The default system bar tint color value.
*/
public static final int DEFAULT_TINT_COLOR = 0x99000000;
private static String sNavBarOverride;
private final SystemBarConfig mConfig;
private boolean mStatusBarAvailable;
private boolean mNavBarAvailable;
private boolean mStatusBarTintEnabled;
private boolean mNavBarTintEnabled;
private View mStatusBarTintView;
private View mNavBarTintView;
/**
* Constructor. Call this in the host activity onCreate method after its
* content view has been set. You should always create new instances when
* the host activity is recreated.
*
* @param activity The host activity.
*/
@SuppressLint("ResourceType")
@TargetApi(19)
public SystemBarTintManager(Activity activity) {
Window win = activity.getWindow();
ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// check theme attrs
int[] attrs = {android.R.attr.windowTranslucentStatus,
android.R.attr.windowTranslucentNavigation};
TypedArray a = activity.obtainStyledAttributes(attrs);
try {
mStatusBarAvailable = a.getBoolean(0, false);
mNavBarAvailable = a.getBoolean(1, false);
} finally {
a.recycle();
}
// check window flags
WindowManager.LayoutParams winParams = win.getAttributes();
int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
if ((winParams.flags & bits) != 0) {
mStatusBarAvailable = true;
}
bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
if ((winParams.flags & bits) != 0) {
mNavBarAvailable = true;
}
}
mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
// device might not have virtual navigation keys
if (!mConfig.hasNavigtionBar()) {
mNavBarAvailable = false;
}
if (mStatusBarAvailable) {
setupStatusBarView(activity, decorViewGroup);
}
if (mNavBarAvailable) {
setupNavBarView(activity, decorViewGroup);
}
}
/**
* Enable tinting of the system status bar.
* <p>
* If the platform is running Jelly Bean or earlier, or translucent system
* UI modes have not been enabled in either the theme or via window flags,
* then this method does nothing.
*
* @param enabled True to enable tinting, false to disable it (default).
*/
public void setStatusBarTintEnabled(boolean enabled) {
mStatusBarTintEnabled = enabled;
if (mStatusBarAvailable) {
mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
}
/**
* Enable tinting of the system navigation bar.
* <p>
* If the platform does not have soft navigation keys, is running Jelly Bean
* or earlier, or translucent system UI modes have not been enabled in either
* the theme or via window flags, then this method does nothing.
*
* @param enabled True to enable tinting, false to disable it (default).
*/
public void setNavigationBarTintEnabled(boolean enabled) {
mNavBarTintEnabled = enabled;
if (mNavBarAvailable) {
mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
}
/**
* Apply the specified color tint to all system UI bars.
*
* @param color The color of the background tint.
*/
public void setTintColor(int color) {
setStatusBarTintColor(color);
setNavigationBarTintColor(color);
}
/**
* Apply the specified drawable or color resource to all system UI bars.
*
* @param res The identifier of the resource.
*/
public void setTintResource(int res) {
setStatusBarTintResource(res);
setNavigationBarTintResource(res);
}
/**
* Apply the specified drawable to all system UI bars.
*
* @param drawable The drawable to use as the background, or null to remove it.
*/
public void setTintDrawable(Drawable drawable) {
setStatusBarTintDrawable(drawable);
setNavigationBarTintDrawable(drawable);
}
/**
* Apply the specified alpha to all system UI bars.
*
* @param alpha The alpha to use
*/
public void setTintAlpha(float alpha) {
setStatusBarAlpha(alpha);
setNavigationBarAlpha(alpha);
}
/**
* Apply the specified color tint to the system status bar.
*
* @param color The color of the background tint.
*/
public void setStatusBarTintColor(int color) {
if (mStatusBarAvailable) {
mStatusBarTintView.setBackgroundColor(color);
}
}
/**
* Apply the specified drawable or color resource to the system status bar.
*
* @param res The identifier of the resource.
*/
public void setStatusBarTintResource(int res) {
if (mStatusBarAvailable) {
mStatusBarTintView.setBackgroundResource(res);
}
}
/**
* Apply the specified drawable to the system status bar.
*
* @param drawable The drawable to use as the background, or null to remove it.
*/
@SuppressWarnings("deprecation")
public void setStatusBarTintDrawable(Drawable drawable) {
if (mStatusBarAvailable) {
mStatusBarTintView.setBackgroundDrawable(drawable);
}
}
/**
* Apply the specified alpha to the system status bar.
*
* @param alpha The alpha to use
*/
@TargetApi(11)
public void setStatusBarAlpha(float alpha) {
if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mStatusBarTintView.setAlpha(alpha);
}
}
/**
* Apply the specified color tint to the system navigation bar.
*
* @param color The color of the background tint.
*/
public void setNavigationBarTintColor(int color) {
if (mNavBarAvailable) {
mNavBarTintView.setBackgroundColor(color);
}
}
/**
* Apply the specified drawable or color resource to the system navigation bar.
*
* @param res The identifier of the resource.
*/
public void setNavigationBarTintResource(int res) {
if (mNavBarAvailable) {
mNavBarTintView.setBackgroundResource(res);
}
}
/**
* Apply the specified drawable to the system navigation bar.
*
* @param drawable The drawable to use as the background, or null to remove it.
*/
@SuppressWarnings("deprecation")
public void setNavigationBarTintDrawable(Drawable drawable) {
if (mNavBarAvailable) {
mNavBarTintView.setBackgroundDrawable(drawable);
}
}
/**
* Apply the specified alpha to the system navigation bar.
*
* @param alpha The alpha to use
*/
@TargetApi(11)
public void setNavigationBarAlpha(float alpha) {
if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mNavBarTintView.setAlpha(alpha);
}
}
/**
* Get the system bar configuration.
*
* @return The system bar configuration for the current device configuration.
*/
public SystemBarConfig getConfig() {
return mConfig;
}
/**
* Is tinting enabled for the system status bar?
*
* @return True if enabled, False otherwise.
*/
public boolean isStatusBarTintEnabled() {
return mStatusBarTintEnabled;
}
/**
* Is tinting enabled for the system navigation bar?
*
* @return True if enabled, False otherwise.
*/
public boolean isNavBarTintEnabled() {
return mNavBarTintEnabled;
}
private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {
mStatusBarTintView = new View(context);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());
params.gravity = Gravity.TOP;
if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {
params.rightMargin = mConfig.getNavigationBarWidth();
}
mStatusBarTintView.setLayoutParams(params);
mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
mStatusBarTintView.setVisibility(View.GONE);
decorViewGroup.addView(mStatusBarTintView);
}
private void setupNavBarView(Context context, ViewGroup decorViewGroup) {
mNavBarTintView = new View(context);
FrameLayout.LayoutParams params;
if (mConfig.isNavigationAtBottom()) {
params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());
params.gravity = Gravity.BOTTOM;
} else {
params = new FrameLayout.LayoutParams(mConfig.getNavigationBarWidth(), FrameLayout.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.RIGHT;
}
mNavBarTintView.setLayoutParams(params);
mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
mNavBarTintView.setVisibility(View.GONE);
decorViewGroup.addView(mNavBarTintView);
}
/**
* Class which describes system bar sizing and other characteristics for the current
* device configuration.
*/
public static class SystemBarConfig {
private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";
private final boolean mTranslucentStatusBar;
private final boolean mTranslucentNavBar;
private final int mStatusBarHeight;
private final int mActionBarHeight;
private final boolean mHasNavigationBar;
private final int mNavigationBarHeight;
private final int mNavigationBarWidth;
private final boolean mInPortrait;
private final float mSmallestWidthDp;
private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {
Resources res = activity.getResources();
mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
mSmallestWidthDp = getSmallestWidthDp(activity);
mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
mActionBarHeight = getActionBarHeight(activity);
mNavigationBarHeight = getNavigationBarHeight(activity);
mNavigationBarWidth = getNavigationBarWidth(activity);
mHasNavigationBar = (mNavigationBarHeight > 0);
mTranslucentStatusBar = translucentStatusBar;
mTranslucentNavBar = traslucentNavBar;
}
@TargetApi(14)
private int getActionBarHeight(Context context) {
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
}
return result;
}
@TargetApi(14)
private int getNavigationBarHeight(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
String key;
if (mInPortrait) {
key = NAV_BAR_HEIGHT_RES_NAME;
} else {
key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
}
return getInternalDimensionSize(res, key);
}
}
return result;
}
@TargetApi(14)
private int getNavigationBarWidth(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
}
}
return result;
}
@TargetApi(14)
private boolean hasNavBar(Context context) {
Resources res = context.getResources();
int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
if (resourceId != 0) {
boolean hasNav = res.getBoolean(resourceId);
// check override flag (see static block)
if ("1".equals(sNavBarOverride)) {
hasNav = false;
} else if ("0".equals(sNavBarOverride)) {
hasNav = true;
}
return hasNav;
} else { // fallback
return !ViewConfiguration.get(context).hasPermanentMenuKey();
}
}
private int getInternalDimensionSize(Resources res, String key) {
int result = 0;
int resourceId = res.getIdentifier(key, "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
return result;
}
@SuppressLint("NewApi")
private float getSmallestWidthDp(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
} else {
// TODO this is not correct, but we don't really care pre-kitkat
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
float widthDp = metrics.widthPixels / metrics.density;
float heightDp = metrics.heightPixels / metrics.density;
return Math.min(widthDp, heightDp);
}
/**
* Should a navigation bar appear at the bottom of the screen in the current
* device configuration? A navigation bar may appear on the right side of
* the screen in certain configurations.
*
* @return True if navigation should appear at the bottom of the screen, False otherwise.
*/
public boolean isNavigationAtBottom() {
return (mSmallestWidthDp >= 600 || mInPortrait);
}
/**
* Get the height of the system status bar.
*
* @return The height of the status bar (in pixels).
*/
public int getStatusBarHeight() {
return mStatusBarHeight;
}
/**
* Get the height of the action bar.
*
* @return The height of the action bar (in pixels).
*/
public int getActionBarHeight() {
return mActionBarHeight;
}
/**
* Does this device have a system navigation bar?
*
* @return True if this device uses soft key navigation, False otherwise.
*/
public boolean hasNavigtionBar() {
return mHasNavigationBar;
}
/**
* Get the height of the system navigation bar.
*
* @return The height of the navigation bar (in pixels). If the device does not have
* soft navigation keys, this will always return 0.
*/
public int getNavigationBarHeight() {
return mNavigationBarHeight;
}
/**
* Get the width of the system navigation bar when it is placed vertically on the screen.
*
* @return The width of the navigation bar (in pixels). If the device does not have
* soft navigation keys, this will always return 0.
*/
public int getNavigationBarWidth() {
return mNavigationBarWidth;
}
/**
* Get the layout inset for any system UI that appears at the top of the screen.
*
* @param withActionBar True to include the height of the action bar, False otherwise.
* @return The layout inset (in pixels).
*/
public int getPixelInsetTop(boolean withActionBar) {
return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);
}
/**
* Get the layout inset for any system UI that appears at the bottom of the screen.
*
* @return The layout inset (in pixels).
*/
public int getPixelInsetBottom() {
if (mTranslucentNavBar && isNavigationAtBottom()) {
return mNavigationBarHeight;
} else {
return 0;
}
}
/**
* Get the layout inset for any system UI that appears at the right of the screen.
*
* @return The layout inset (in pixels).
*/
public int getPixelInsetRight() {
if (mTranslucentNavBar && !isNavigationAtBottom()) {
return mNavigationBarWidth;
} else {
return 0;
}
}
}
}
\ No newline at end of file
package com.polysoft.nafmii.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.telephony.TelephonyManager;
import java.util.Locale;
public class SystemUtils {
/**
* 获取当前手机系统语言。
*
* @return 返回当前系统语言。例如:当前设置的是“中文-中国”,则返回“zh-CN”
*/
public static String getSystemLanguage() {
return Locale.getDefault().getLanguage();
}
/**
* 获取当前系统上的语言列表(Locale列表)
*
* @return 语言列表
*/
public static Locale[] getSystemLanguageList() {
return Locale.getAvailableLocales();
}
/**
* 获取当前手机系统版本号
*
* @return 系统版本号
*/
public static String getSystemVersion() {
return android.os.Build.VERSION.RELEASE;
}
/**
* 获取手机型号
*
* @return 手机型号
*/
public static String getSystemModel() {
return android.os.Build.MODEL;
}
/**
* 获取手机厂商
*
* @return 手机厂商
*/
public static String getDeviceBrand() {
return android.os.Build.BRAND;
}
/**
* 获取手机IMEI(需要“android.permission.READ_PHONE_STATE”权限)
*
* @return 手机IMEI
*/
public static String getIMEI(Context ctx) {
TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Activity.TELEPHONY_SERVICE);
if (tm != null && PermissionUtils.checkAndRequestPermission(ctx, Manifest.permission.READ_PHONE_STATE)) {
return tm.getDeviceId();
}
return null;
}
}
\ No newline at end of file
package com.polysoft.nafmii.utils;
import android.widget.Toast;
public class ToastUtils {
public static void showLong(String message) {
Toast toast = Toast.makeText(CtxUtils.getApplication(), null, Toast.LENGTH_LONG);
toast.setText(message);
toast.show();
// Toast.makeText(CtxUtils.getApplication(), message, Toast.LENGTH_LONG).show();
}
public static void showShort(String message) {
Toast toast = Toast.makeText(CtxUtils.getApplication(), null, Toast.LENGTH_SHORT);
toast.setText(message);
toast.show();
// Toast.makeText(CtxUtils.getApplication(), message, Toast.LENGTH_SHORT).show();
}
}
package com.polysoft.nafmii.webview;
public interface IWebview {
void loadUrl(String url);
boolean onBack();
}
package com.polysoft.nafmii.webview;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebView;
public class JavaToJsinterface {
private static final String TAG = JavaToJsinterface.class.getName();
protected WebView mWebView;
public JavaToJsinterface(WebView webView) {
this.mWebView = webView;
}
public void callJs(String methodName, String json) {
String param = JSON.toJSONString(json);
String script = String.format("javascript:$api.%s(%s)", methodName, param);
this.mWebView.evaluateJavascript(script, new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.d(TAG, String.format("JavaToJsinterface: callJs is %s result : %s", methodName, value));
}
});
}
}
package com.polysoft.nafmii.webview;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
public class JsResult {
public static final String SUCCESS = "0";
public static final String FAIL = "1";
@JSONField(name = "status")
protected String status;
@JSONField(name = "statusText")
protected String statusText;
@JSONField(name = "data")
protected Object data;
private JsResult() {
}
private JsResult(String status, String statusText, Object data) {
this.status = status;
this.statusText = statusText;
this.data = data;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
public static JsResult success(String statusText, Object data) {
return new JsResult(SUCCESS, statusText, data);
}
public static JsResult success(Object data) {
return success("success", data);
}
public static JsResult fail(String statusText, Object data) {
return new JsResult(FAIL, statusText, data);
}
public static JsResult fail(String statusText) {
return fail(statusText, null);
}
}
package com.polysoft.nafmii.webview;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.text.TextUtils;
import android.webkit.JavascriptInterface;
import androidx.fragment.app.Fragment;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.polysoft.nafmii.broadcast.Receiver;
import com.polysoft.nafmii.broadcast.ReceiverListener;
import com.polysoft.nafmii.broadcast.ShareReceiver;
import com.polysoft.nafmii.utils.CtxUtils;
import com.polysoft.nafmii.utils.IntentUtils;
import com.polysoft.nafmii.utils.PermissionUtils;
import com.polysoft.nafmii.utils.StatusBarUtils;
import com.polysoft.nafmii.wechat.ShareBean;
import com.polysoft.nafmii.wechat.ShareResult;
import com.polysoft.nafmii.wechat.WechatApi;
import java.util.HashMap;
import java.util.Map;
public class JsToJavaInterface {
private Activity mActivity;
private JavaToJsinterface javaTojs;
private Fragment mFragment;
public JsToJavaInterface(Activity activity, JavaToJsinterface javaTojs) {
this.mActivity = activity;
this.javaTojs = javaTojs;
}
public JsToJavaInterface(Fragment fragment, JavaToJsinterface javaTojs) {
this(fragment.getActivity(), javaTojs);
this.mFragment = fragment;
}
@JavascriptInterface
public void nativeAppInfo(String params) {
String jsMethodName = null;
try {
JSONObject json = JSONObject.parseObject(params);
jsMethodName = json.getString("jsMethodName");
final Map<String, Object> dataMap = new HashMap<>();
PackageInfo packageInfo = CtxUtils.getPackageInfo();
dataMap.put("versionCode", packageInfo.versionCode);
dataMap.put("versionName", packageInfo.versionName);
dataMap.put("statusBarHeight", StatusBarUtils.getStatusBarHeight(this.mActivity));
this.sendMessage2Js(jsMethodName, JSON.toJSONString(dataMap));
}catch (Exception e) {
e.printStackTrace();
}
}
@JavascriptInterface
public void nativeLogin(String params) {
try{
final JSONObject json = JSONObject.parseObject(params);
final String jsMethodName = json.getString("jsMethodName");
final String data = json.getString("data");
} catch (Exception e) {
e.printStackTrace();
}
}
@JavascriptInterface
public void nativeShare(String params) {
final JSONObject json = JSONObject.parseObject(params);
final String jsMethodName = json.getString("jsMethodName");
this.mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
WechatApi instance = WechatApi.getInstance(mActivity);
if (!instance.isWXAppInstalled()) {
String dataJson = JSON.toJSONString(ShareResult.shareFail("未安装应用"));
javaTojs.callJs(jsMethodName, dataJson);
} else {
final Receiver<ShareResult> shareReceiver = ShareReceiver.getInstance(mActivity);
shareReceiver.addDefaultListener(new ReceiverListener<ShareResult>() {
@Override
public void onReceiverResult(String action, ShareResult data) {
javaTojs.callJs(jsMethodName, JSON.toJSONString(data));
shareReceiver.addDefaultListener(null);
}
});
instance.share(mActivity, json.getObject("data", ShareBean.class));
}
}
});
}
@JavascriptInterface
public void nativeCamera(String params) {
final JSONObject json = JSONObject.parseObject(params);
final String jsMethodName = json.getString("jsMethodName");
final JSONObject data = json.getJSONObject("data");
String permissions[] = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
};
// if (PermissionUtils.checkPermissions(this.mActivity, permissions)) {
// this.photosReceiverListener(jsMethodName);
// Intent intent = IntentUtils.openCamera(this.mActivity);
// this.mFragment.startActivityForResult(intent, IntentUtils.ACTIVITY_CODE_CAMERA);
// }
}
//
// @JavascriptInterface
// public void callNativeAlbum(String params) {
// final JSONObject json = JSONObject.parseObject(params);
// final String jsMethodName = json.getString("jsMethodName");
// final JSONObject data = json.getJSONObject("data");
//
// String permissions[] = {
// Manifest.permission.WRITE_EXTERNAL_STORAGE,
// Manifest.permission.READ_EXTERNAL_STORAGE,
// };
// if (PermissionUtils.checkPermissions(this.mActivity, permissions)) {
// this.photosReceiverListener(jsMethodName);
// Intent intent = IntentUtils.openAlbum(this.mActivity);
// this.mFragment.startActivityForResult(intent, IntentUtils.ACTIVITY_CODE_ALBUM);
// }
// }
//
// @JavascriptInterface
// public void callNativeUpdate(String params) {
// final JSONObject json = JSONObject.parseObject(params);
// final String jsMethodName = json.getString("jsMethodName");
// final JSONObject data = json.getJSONObject("data");
// final String downloadUrl = data.getString("url");
// final String version = data.getString("version");
//
// if (!TextUtils.isEmpty(version)) {
// PackageInfo packageInfo = UITools.getVersionInfo(this.mActivity);
// int localVersion = packageInfo.versionCode;
// double updateVersion = Double.parseDouble(version);
// if (updateVersion <= localVersion) {
// return;
// }
// }
// this.mActivity.runOnUiThread(new Runnable() {
// @Override
// public void run() {
// UITools.showMustUpdataDialog(downloadUrl, mActivity);
// }
// });
// }
//
// @JavascriptInterface
// public void callNativeMobile(String params) {
// final JSONObject json = JSONObject.parseObject(params);
// final String jsMethodName = json.getString("jsMethodName");
// final JSONObject data = json.getJSONObject("data");
// final String tel = data.getString("tel");
//
// Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + tel));
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// this.mActivity.startActivity(intent);
//
// if (TextUtils.isEmpty((jsMethodName))) {
// return;
// }
//
// this.mActivity.runOnUiThread(new Runnable() {
// @Override
// public void run() {
// javaTojs.callJs(jsMethodName, "");
// }
// });
// }
//
// @JavascriptInterface
// public void callNativeClearCache(String params) {
// JSONObject json = TextUtils.isEmpty(params) ? new JSONObject() : JSONObject.parseObject(params);
// final String jsMethodName = json.getString("jsMethodName");
// this.mActivity.runOnUiThread(new Runnable() {
// @Override
// public void run() {
// WebViewCacheInterceptorInst.getInstance().clearCache();
// if (!TextUtils.isEmpty(jsMethodName)) {
// javaTojs.callJs(jsMethodName, "");
// }
// }
// });
// }
private void sendMessage2Js(String jsMethodName, String json) {
if (TextUtils.isEmpty(jsMethodName)) {
return;
}
if ("'main'".equals(Thread.currentThread().getName())) {
javaTojs.callJs(jsMethodName, json);
return;
}
this.mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
javaTojs.callJs(jsMethodName, json);
}
});
}
}
package com.polysoft.nafmii.webview;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import com.tencent.smtt.export.external.interfaces.SslError;
import com.tencent.smtt.export.external.interfaces.SslErrorHandler;
import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
import com.tencent.smtt.export.external.interfaces.WebResourceResponse;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;
import java.util.Map;
import ren.yale.android.cachewebviewlib.WebViewCacheInterceptorInst;
public class MyWebViewClient extends WebViewClient {
private WebviewLoadListener listener;
public MyWebViewClient(WebviewLoadListener listener) {
this.listener = listener;
}
/**
* 在开始加载网页时会回调
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (null != this.listener) {
this.listener.onWebviewLoad(WebviewLoadListener.TYPE_START, null);
}
}
/**
* 在结束加载网页时会回调
*/
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (null != this.listener) {
this.listener.onWebviewLoad(WebviewLoadListener.TYPE_FINISH, null);
}
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
/**
* 加载错误的时候会回调,在其中可做错误处理,比如再请求加载一次,或者提示404的错误页面
*/
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
if (null != this.listener) {
this.listener.onWebviewLoad(WebviewLoadListener.TYPE_ERROR, description);
}
}
/**
* 当接收到https错误时,会回调此函数,在其中可以做错误处理
*/
@Override
public void onReceivedSslError(WebView webView, SslErrorHandler sslErrorHandler, SslError sslError) {
// super.onReceivedSslError(webView, sslErrorHandler, sslError);
sslErrorHandler.proceed();
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, String s) {
// return super.shouldInterceptRequest(webView, s);
android.webkit.WebResourceResponse response = WebViewCacheInterceptorInst.getInstance().interceptRequest(s);
if (null == response) {
return super.shouldInterceptRequest(webView, s);
}
return buildResponse(response);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest request) {
android.webkit.WebResourceRequest res = new android.webkit.WebResourceRequest() {
@Override
public Uri getUrl() {
return request.getUrl();
}
@Override
public boolean isForMainFrame() {
return request.isForMainFrame();
}
@Override
public boolean isRedirect() {
return request.isRedirect();
}
@Override
public boolean hasGesture() {
return request.hasGesture();
}
@Override
public String getMethod() {
return request.getMethod();
}
@Override
public Map<String, String> getRequestHeaders() {
return request.getRequestHeaders();
}
};
android.webkit.WebResourceResponse response = WebViewCacheInterceptorInst.getInstance().interceptRequest(res);
if (null == response) {
return super.shouldInterceptRequest(webView, request);
}
return buildResponse(response);
}
private WebResourceResponse buildResponse(android.webkit.WebResourceResponse response) {
WebResourceResponse res = new WebResourceResponse();
res.setMimeType(response.getMimeType());
res.setEncoding(response.getEncoding());
res.setData(response.getData());
res.setResponseHeaders(response.getResponseHeaders());
res.setStatusCodeAndReasonPhrase(response.getStatusCode(), response.getReasonPhrase());
return res;
}
}
package com.polysoft.nafmii.webview;
import android.net.Uri;
import android.webkit.ValueCallback;
public interface WebviewLoadListener {
public static final int TYPE_ERROR = -1;
public static final int TYPE_START = 1;
public static final int TYPE_PROGRESS = 2;
public static final int TYPE_FINISH = 3;
void onWebviewLoad(int type, Object param);
void onShowFileChooser(ValueCallback<Uri[]> filePathCallback, String[] acceptTypes, boolean isCapture);
}
package com.polysoft.nafmii.webview;
import android.util.Log;
import com.polysoft.nafmii.utils.CtxUtils;
import com.tencent.smtt.export.external.TbsCoreSettings;
import com.tencent.smtt.sdk.QbSdk;
import com.tencent.smtt.sdk.TbsListener;
import java.util.HashMap;
public class X5Core {
private static volatile X5Core.InitCallback callback;
private static volatile boolean initfinished = false;
public static void init() {
HashMap<String, Object> map = new HashMap<>();
map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true);
map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true);
QbSdk.initTbsSettings(map);
QbSdk.setTbsListener(new TbsListener() {
@Override
public void onDownloadFinish(int i) {
Log.d("QbSdk", "onDownloadFinish -->下载X5内核完成:" + i);
}
@Override
public void onInstallFinish(int i) {
Log.d("QbSdk", "onInstallFinish -->安装X5内核进度:" + i);
}
@Override
public void onDownloadProgress(int i) {
Log.d("QbSdk", "onDownloadProgress -->下载X5内核进度:" + i);
}
});
QbSdk.initX5Environment(CtxUtils.getApplication(), new QbSdk.PreInitCallback() {
@Override
public void onCoreInitFinished() {
//内核初始化完毕
Log.d("QbSdk", "内核初始化完毕");
}
@Override
public void onViewInitFinished(boolean b) {
// x5內核初始化完成的回调,true表x5内核加载成功,否则表加载失败,会自动切换到系统内核。
Log.d("QbSdk", " 内核加载 " + b);
X5Core.initfinished = true;
callInitFinish();
}
});
}
public static void setInitCallback(InitCallback callback) {
X5Core.callback = callback;
callInitFinish();
}
private static synchronized void callInitFinish() {
if (null == X5Core.callback) return;
if (X5Core.initfinished || QbSdk.isTbsCoreInited()) {
X5Core.callback.onCoreInitFinished(QbSdk.isTbsCoreInited());
reset();
}
}
private static void reset() {
X5Core.callback = null;
X5Core.initfinished = false;
}
public interface InitCallback {
void onCoreInitFinished(boolean flag);
}
}
package com.polysoft.nafmii.webview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import com.polysoft.nafmii.BuildConfig;
import com.tencent.smtt.export.external.extension.interfaces.IX5WebSettingsExtension;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
public class X5WebviewUtils {
public static WebView create(Context context) {
WebView webView = new WebView(context);
/** 设置透明色背景*/
webView.setBackgroundColor(0);
// 解决部分机型加载 背景为黑色问题
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
// webView.clearCache(true);
webView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
setWebView(webView);
return webView;
}
public static void destroy(WebView webView) {
if (null == webView) {
return;
}
webView.stopLoading();
webView.clearHistory();
webView.removeAllViews();
webView.setVisibility(View.GONE);
webView.loadUrl("about:blank");
webView.destroy();
ViewGroup parent = (ViewGroup) webView.getParent();
parent.removeAllViews();
}
@SuppressLint({"SetJavaScriptEnabled", "InlinedApi"})
private static void setWebView(WebView webView) {
WebSettings settings = webView.getSettings();
/** 支持javaScript*/
settings.setJavaScriptEnabled(true);
/** 设置页面文字的编码*/
settings.setDefaultTextEncodingName("utf-8");
/** 设置webview布局方式*/
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
/** 是否允许WebView度超出以概览的方式载入页面,默认false。
* 即缩小内容以适应屏幕宽度。该项设置在内容宽度超出WebView控件的宽度时生效,
* 例如当getUseWideViewPort() 返回true时*/
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(true);
/** 支持访问Content Provider的资源*/
settings.setAllowContentAccess(true);
/** 支持访问本地文件*/
settings.setAllowFileAccess(true);
/** 支持通过file url加载的Javascript读取本地文件*/
settings.setAllowFileAccessFromFileURLs(true);
/** 支持https/http 混合加载*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
/** 支持通过file url加载的Javascript读取全部资源(包括文件,http,https)*/
settings.setAllowUniversalAccessFromFileURLs(true);
/** 禁止页面缩放*/
settings.setBuiltInZoomControls(false);
settings.setSupportZoom(false);
/** 禁止显示缩放图标*/
settings.setDisplayZoomControls(false);
// settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
// settings.setAppCacheEnabled(true);
settings.setDomStorageEnabled(true);
IX5WebSettingsExtension extension = webView.getSettingsExtension();
if (null != extension) {
/** 对于刘海屏机器如果webview被遮挡会自动padding */
extension.setDisplayCutoutEnable(true);
/** 正常加载显示所有图片 */
extension.setPicModel(IX5WebSettingsExtension.PicModel_NORMAL);
}
}
}
package com.polysoft.nafmii.wechat;
import com.alibaba.fastjson.annotation.JSONField;
public class ShareBean {
@JSONField(name = "shareType")
private String shareType;//分享类型 0文字 1图片 2url网址
@JSONField(name = "title")
private String title;//分享标题
@JSONField(name = "content")
private String content;//分享内容 文字 图片 展示的网页描述
@JSONField(name = "scene")
private String scene;//场景 0朋友圈 1好友
@JSONField(name = "webUrl")
private String webUrl;//分享链接
@JSONField(name = "webImg")
private String webImg;//网页位图
public String getWebImg() {
return webImg;
}
public void setWebImg(String webImg) {
this.webImg = webImg;
}
public String getShareType() {
return shareType;
}
public void setShareType(String shareType) {
this.shareType = shareType;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getScene() {
return scene;
}
public void setScene(String scene) {
this.scene = scene;
}
public String getWebUrl() {
return webUrl;
}
public void setWebUrl(String webUrl) {
this.webUrl = webUrl;
}
@Override
public String toString() {
return "WeChatShareBean{" +
"shareType='" + shareType + '\'' +
", title='" + title + '\'' +
", content='" + content + '\'' +
", scene='" + scene + '\'' +
", webUrl='" + webUrl + '\'' +
", webImg='" + webImg + '\'' +
'}';
}
}
package com.polysoft.nafmii.wechat;
import android.text.TextUtils;
import com.alibaba.fastjson.annotation.JSONField;
import java.io.Serializable;
public class ShareResult implements Serializable {
@JSONField(name = "status")
private String status;
@JSONField(name = "statusText")
private String statusText;
private ShareResult() {
}
private ShareResult(String status, String statusText) {
this.status = status;
this.statusText = statusText;
}
public static ShareResult shareSuccess() {
return new ShareResult("0", "分享成功");
}
public static ShareResult shareFail(String text) {
String statusText = TextUtils.isEmpty(text) ? text : "分享失败";
return new ShareResult("-1", statusText);
}
public static ShareResult shareCancel() {
return new ShareResult("-2", "分享取消");
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getStatusText() {
return statusText;
}
public void setStatusText(String statusText) {
this.statusText = statusText;
}
}
package com.polysoft.nafmii.wechat;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.alibaba.fastjson.JSON;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.polysoft.nafmii.BuildConfig;
import com.polysoft.nafmii.R;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
public class WechatApi {
private static WechatApi INSTANCE = null;
private final Context ctx;
private final IWXAPI api;
private WechatApi(Context ctx, boolean isDebug) {
this.ctx = ctx;
this.api = WXAPIFactory.createWXAPI(ctx, BuildConfig.WX_APPID, isDebug);
this.api.registerApp(BuildConfig.WX_APPID);
}
public static WechatApi getInstance(Context ctx) {
return getInstance(ctx, false);
}
public static WechatApi getInstance(Context ctx, boolean isDebug) {
if (null == WechatApi.INSTANCE) {
WechatApi.INSTANCE = new WechatApi(ctx, isDebug);
}
return WechatApi.INSTANCE;
}
public void sendRequest(BaseReq req) {
this.api.sendReq(req);
}
public boolean isWXAppInstalled() {
return this.api.isWXAppInstalled();
}
public void handleIntent(Intent intent, IWXAPIEventHandler handler) {
this.api.handleIntent(intent, handler);
}
public void pay(String payInfo) {
this.sendRequest(JSON.parseObject(payInfo, PayReq.class));
}
public void share(Context ctx, final ShareBean bean) {
String webImg = bean.getWebImg();
String shareType = bean.getShareType();
if ("0".equals(shareType)) { // 分享文字
this.shareText(bean);
} else if ("1".equals(shareType)) { // 分享图片
this.shareImage(bean);
} else if ("2".equals(shareType)) { // 分享url地址
this.loadImageUrl(ctx, webImg, new Callback<Bitmap>() {
@Override
public void onBack(Bitmap data) {
shareWebPage(bean, data);
}
});
}
}
private void shareText(ShareBean bean) {
}
private void shareImage(ShareBean bean) {
}
private void shareWebPage(ShareBean bean, Bitmap bitmap) {
WXWebpageObject web = new WXWebpageObject();
web.webpageUrl = bean.getWebUrl();
WXMediaMessage msg = new WXMediaMessage(web);
// 填写网页标题、描述、位图
msg.title = bean.getTitle();
//网页描述
msg.description = bean.getContent();
msg.setThumbImage(bitmap);
bitmap.recycle();
SendMessageToWX.Req req = new SendMessageToWX.Req();
// transaction用于唯一标识一个请求(可自定义)
req.transaction = "webpage";
// 上文的WXMediaMessage对象
req.message = msg;
req.scene = this.getShareScene(bean);
// 向微信发送请求
this.sendRequest(req);
}
private int getShareScene(ShareBean bean) {
String scene = bean.getScene();
if ("0".equals(scene)) { // 朋友圈
return SendMessageToWX.Req.WXSceneTimeline;
} else if ("1".equals(scene)) { // 分享到好友
return SendMessageToWX.Req.WXSceneSession;
} else if ("2".equals(scene)) { // 分享到收藏夹
return SendMessageToWX.Req.WXSceneFavorite;
}
// 默认分享到好友
return SendMessageToWX.Req.WXSceneSession;
}
private void loadImageUrl(Context ctx, String url, final Callback<Bitmap> callback) {
SimpleTarget<Bitmap> target = new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
callback.onBack(resource);
}
};
if (TextUtils.isEmpty(url)) {
Glide.with(ctx).asBitmap().load(R.mipmap.ic_launcher).override(120, 120).into(target);
} else {
Glide.with(ctx).asBitmap().load(url).override(120, 120).into(target);
}
}
private static interface Callback<T> {
public void onBack(T data);
}
}
package com.polysoft.nafmii.wxapi;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import com.polysoft.nafmii.broadcast.ShareReceiver;
import com.polysoft.nafmii.wechat.ShareResult;
import com.polysoft.nafmii.wechat.WechatApi;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WechatApi.getInstance(this).handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
WechatApi.getInstance(this).handleIntent(intent, this);
}
@Override
public void onReq(BaseReq baseReq) {
}
@Override
public void onResp(BaseResp resp) {
if (resp instanceof SendAuth.Resp) {
}
int code = resp.errCode;
if (code == BaseResp.ErrCode.ERR_OK) { // 分享成功
ShareReceiver.sendBroadcast(this, ShareResult.shareSuccess());
} else if (code == BaseResp.ErrCode.ERR_USER_CANCEL) { // 用户取消
ShareReceiver.sendBroadcast(this, ShareResult.shareCancel());
} else { // 分享失败
String errStr = resp.errStr;
ShareReceiver.sendBroadcast(this, ShareResult.shareFail(errStr));
}
super.finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
package com.polysoft.nafmii.wxapi;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.polysoft.nafmii.wechat.WechatApi;
import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String TAG = WXPayEntryActivity.class.getName();
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WechatApi.getInstance(this).handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
WechatApi.getInstance(this).handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
}
@Override
public void onResp(BaseResp resp) {
Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() != ConstantsAPI.COMMAND_PAY_BY_WX) {
return;
}
int code = resp.errCode;
if (code == BaseResp.ErrCode.ERR_OK) { // 支付成功
// PayReceiver.sendBroadcast(this, PayResult.success(PayMode.WECHATPAY, null));
} else if (code == BaseResp.ErrCode.ERR_USER_CANCEL) { // 用户取消
// PayReceiver.sendBroadcast(this, PayResult.cancel(PayMode.WECHATPAY));
} else { // 支付失败
String errStr = resp.errStr;
// PayReceiver.sendBroadcast(this, PayResult.fail(PayMode.WECHATPAY, errStr));
}
super.finish();
}
}
\ 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="false">
<shape android:shape="oval">
<solid android:color="@color/black" />
<size android:width="15dp" android:height="15dp" />
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="oval">
<solid android:color="@color/teal_200" />
<size android:width="15dp" android:height="15dp" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" />
<solid android:color="#10DDDDDD" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" />
<solid android:color="#20DDDDDD" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" />
<solid android:color="#40DDDDDD" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" />
<solid android:color="#50DDDDDD" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" />
<solid android:color="#60DDDDDD" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="@android:color/white" />
</shape>
</item>
</layer-list>
\ 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:color="@color/black" android:state_checked="false" />
<item android:color="@color/teal_200" android:state_checked="true" />
</selector>
\ No newline at end of file
<?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>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.GuideActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/guide_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/guide_btn_gohome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
android:text="立即体验"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/guide_point_group"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints" />
<RadioGroup
android:id="@+id/guide_point_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints">
<RadioButton
android:id="@+id/guide_point1"
style="@style/Nafmii.Widget.Guide.RadioButton"
android:checked="true" />
<RadioButton
android:id="@+id/guide_point2"
style="@style/Nafmii.Widget.Guide.RadioButton" />
<RadioButton
android:id="@+id/guide_point3"
style="@style/Nafmii.Widget.Guide.RadioButton" />
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".activity.HomeActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/home_container_viewpager"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/home_footer_group"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/home_container_framelayout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/home_footer_group"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<RadioGroup
android:id="@+id/home_footer_group"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@drawable/home_bottom_menu_bg"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent">
<RadioButton
android:id="@+id/home_btn_home"
style="@style/Nafmii.Widget.Home.RadioButton"
android:checked="true"
android:text="首页" />
<RadioButton
android:id="@+id/home_btn_member"
style="@style/Nafmii.Widget.Home.RadioButton"
android:text="会员" />
<RadioButton
android:id="@+id/home_btn_learn"
style="@style/Nafmii.Widget.Home.RadioButton"
android:text="学习" />
<RadioButton
android:id="@+id/home_btn_my"
style="@style/Nafmii.Widget.Home.RadioButton"
android:text="我的" />
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:fitsSystemWindows="false"
android:padding="20dp"
tools:context=".activity.InputUrlActivity">
<EditText
android:id="@+id/input_url"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="请输入完整url地址"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="进入"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/input_url" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<FrameLayout
android:id="@+id/main_framelayout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"></FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ 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:orientation="vertical"
android:layout_height="match_parent">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/icon_zhiwen" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="请验证指纹解锁"
android:textColor="#000"
android:textSize="16sp" />
<TextView
android:id="@+id/error_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:maxLines="1"
android:textColor="#f45"
android:textSize="12sp" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="10dp"
android:background="#ccc" />
<TextView
android:id="@+id/cancel"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="取消"
android:textColor="#5d7883"
android:textSize="16sp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.AdvertisementFragment">
<ImageView
android:id="@+id/advertisement_imgview"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/advertisement_countdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5s"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="@+id/advertisement_pass"
app:layout_constraintEnd_toStartOf="@+id/advertisement_pass"
app:layout_constraintTop_toTopOf="@+id/advertisement_pass" />
<TextView
android:id="@+id/advertisement_pass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginRight="40dp"
android:padding="20dp"
android:text="跳过"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.WebViewFragment">
<LinearLayout
android:id="@+id/webview_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Nafmii" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="android:windowBackground">@mipmap/splash1</item>
<!-- Customize your theme here. -->
</style>
<style name="Nafmii.Fullscreen" parent="Theme.Nafmii">
<!-- 设置全屏-->
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@mipmap/splash1</item>
</style>
<style name="Nafmii.Fullscreen.NoTitleBar" parent="Nafmii.Fullscreen">
<!-- 取消Actionbar-->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
</resources>
\ No newline at end of file
<resources>
<string name="hello_world">Hello Round World!</string>
</resources>
\ No newline at end of file
<resources>
<declare-styleable name="FullscreenAttrs">
<attr name="fullscreenBackgroundColor" format="color" />
<attr name="fullscreenTextColor" format="color" />
</declare-styleable>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="light_blue_600">#FF039BE5</color>
<color name="light_blue_900">#FF01579B</color>
<color name="light_blue_A200">#FF40C4FF</color>
<color name="light_blue_A400">#FF00B0FF</color>
<color name="black_overlay">#66000000</color>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
Because the window insets on round devices are larger than 15dp, this padding only applies
to square screens.
-->
<dimen name="box_inset_layout_padding">0dp</dimen>
<!--
This padding applies to both square and round screens. The total padding between the buttons
and the window insets is box_inset_layout_padding (above variable) on square screens and
inner_frame_layout_padding (below variable) on round screens.
-->
<dimen name="inner_frame_layout_padding">5dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">nafmii</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="title_activity_base">BaseActivity</string>
<!--
This string is used for square devices and overridden by hello_world in
values-round/strings.xml for round devices.
-->
<string name="hello_world">Hello Square World!</string>
</resources>
\ No newline at end of file
<resources>
<style name="Nafmii.Widget.Home.RadioButton" parent="">
<item name="android:textSize">16sp</item>
<item name="android:layout_weight">1</item>
<item name="android:button">@null</item>
<item name="android:gravity">center</item>
<item name="android:textColor">@drawable/home_radio_selector</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
</style>
<style name="Nafmii.Widget.Guide.RadioButton" parent="">
<item name="android:textSize">0sp</item>
<item name="android:button">@null</item>
<item name="android:gravity">center</item>
<item name="android:layout_width">25dp</item>
<item name="android:layout_height">25dp</item>
<item name="android:drawableTop">@drawable/guide_radio_selector</item>
</style>
</resources>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Nafmii" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
<style name="Nafmii.Fullscreen" parent="Theme.Nafmii">
<!-- 设置全屏-->
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@mipmap/splash1</item>
</style>
<style name="Nafmii.Fullscreen.NoTitleBar" parent="">
<item name="android:windowBackground">@android:color/white</item>
<!-- 避免控件会顶到状态栏上 -->
<item name="android:fitsSystemWindows">false</item>
<!-- 取消Actionbar-->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Nafmii.Fullscreen.NoTitleBar.Main" parent="Nafmii.Fullscreen.NoTitleBar">
<item name="android:windowBackground">@mipmap/splash1</item>
</style>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
<!-- <domain-config cleartextTrafficPermitted="true">-->
<!-- <domain includeSubdomains="true">android.bugly.qq.com</domain>-->
<!-- <domain includeSubdomains="true">cfg.imtt.qq.com</domain>-->
<!-- <domain includeSubdomains="true">tbs.imtt.qq.com</domain>-->
<!-- <domain includeSubdomains="true">x5.tencent.com</domain>-->
<!-- </domain-config>-->
</network-security-config>
\ No newline at end of file
package com.polysoft.nafmii;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.1"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
\ No newline at end of file
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
\ No newline at end of file
No preview for this file type
#Tue Apr 20 17:55:49 CST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
include ':app'
rootProject.name = "nafmill"
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!