├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── tbs_sdk_thirdapp_v3.5.0.1004_43500_sharewithdownload_withoutGame_obfs_20170801_113025.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── administrator │ │ └── sharex5webviewdemo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── administrator │ │ │ └── sharex5webviewdemo │ │ │ ├── cookie │ │ │ ├── AddCookiesInterceptor.java │ │ │ ├── SaCookieManger.java │ │ │ ├── SaasCookieManager.java │ │ │ └── SaveCookiesInterceptor.java │ │ │ ├── model │ │ │ ├── MVPLoginBean.java │ │ │ └── MVPLoginResultBean.java │ │ │ ├── mvp │ │ │ ├── mvp_use │ │ │ │ ├── ImpLoginPresenter.java │ │ │ │ ├── MVPLoginPresenter.java │ │ │ │ └── MVPLoginView.java │ │ │ └── mvpbase │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BasePresenter.java │ │ │ │ ├── BaseView.java │ │ │ │ ├── HomeApplication.java │ │ │ │ └── ImpBasePresenter.java │ │ │ ├── tools │ │ │ ├── ActivityUtils.java │ │ │ ├── CheckNetUtil.java │ │ │ ├── HttpUrlConstance.java │ │ │ ├── LogTAG.java │ │ │ ├── Logger.java │ │ │ ├── OkHttpRequestUtil.java │ │ │ ├── ProjectDataDescribe.java │ │ │ ├── SystemBarTintManager.java │ │ │ └── X5NetService.java │ │ │ ├── ui │ │ │ ├── MainActivity.java │ │ │ ├── UseCookieActivity.java │ │ │ └── X5WebGameActivity.java │ │ │ └── widget │ │ │ └── MyX5WebView.java │ ├── jniLibs │ │ └── armeabi │ │ │ └── liblbs.so │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── color_progressbar.xml │ │ ├── gamesdk_pwd_icon.png │ │ ├── gamesdk_username.png │ │ ├── ic_launcher_background.xml │ │ ├── shape_login.xml │ │ ├── shape_login_register.xml │ │ └── shape_login_register_new.xml │ │ ├── layout │ │ ├── activity_cookie.xml │ │ ├── activity_main.xml │ │ └── layout_x5.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── splash.jpg │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── administrator │ └── sharex5webviewdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android-X5WebView基本封装和使用 2 | ===== 3 | 4 | 通过OkHttp拦截器、自定义CookieJar有效完成客户端与H5端的Cookie同步管理 5 | ----- 6 | 7 | 监听WebView的加载进度 8 | ----- 9 | 10 | 滚动条的设置(隐藏或者显示,内侧显示还是外侧显示) 11 | ----- 12 | 优化X5WebView的预加载问题(使用IntentService规避风险) 13 | ------- 14 |   15 | 16 | 17 | 18 | 19 | [项目文字说明](https://www.jianshu.com/p/88084a66c256)  20 | 21 | 22 | 23 | 24 | 25 | 26 | 著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用、开源项目仅供学习交流、也希望大家尊重笔者的劳动成果,谢谢。 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | 6 | defaultConfig { 7 | applicationId "com.example.administrator.sharex5webviewdemo" 8 | minSdkVersion 14 9 | targetSdkVersion 21 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | 15 | /* ndk { 16 | abiFilters"armeabi","armeabi-v7a","x86","mips" 17 | }*/ 18 | 19 | } 20 | 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | 29 | } 30 | 31 | dependencies { 32 | implementation fileTree(dir: 'libs', include: ['*.jar']) 33 | 34 | implementation 'com.android.support:appcompat-v7:26.1.0' 35 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 36 | testImplementation 'junit:junit:4.12' 37 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 38 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 39 | 40 | compile 'com.android.support:support-v4:26.1.0' 41 | compile "com.android.support:design:26.1.0" 42 | compile 'com.google.code.gson:gson:2.8.2' 43 | compile 'com.squareup.okio:okio:1.13.0' 44 | compile 'com.squareup.okhttp3:okhttp:3.9.0' 45 | compile 'com.squareup.okhttp3:logging-interceptor:3.9.0' 46 | compile files('libs/tbs_sdk_thirdapp_v3.5.0.1004_43500_sharewithdownload_withoutGame_obfs_20170801_113025.jar') 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/libs/tbs_sdk_thirdapp_v3.5.0.1004_43500_sharewithdownload_withoutGame_obfs_20170801_113025.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/libs/tbs_sdk_thirdapp_v3.5.0.1004_43500_sharewithdownload_withoutGame_obfs_20170801_113025.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/administrator/sharex5webviewdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.example.administrator.sharex5webviewdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 52 | 53 | 56 | 57 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/cookie/AddCookiesInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.cookie; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.text.TextUtils; 6 | import android.util.Log; 7 | 8 | 9 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.HomeApplication; 10 | import com.example.administrator.sharex5webviewdemo.tools.LogTAG; 11 | 12 | import java.io.IOException; 13 | 14 | import okhttp3.Interceptor; 15 | import okhttp3.Request; 16 | import okhttp3.Response; 17 | 18 | /** 19 | * Created by tzw on 2018/3/13. 20 | * 21 | */ 22 | 23 | public class AddCookiesInterceptor implements Interceptor { 24 | 25 | private static final String COOKIE_PREF = "cookies_prefs"; 26 | @Override 27 | public Response intercept(Chain chain) throws IOException { 28 | 29 | Request request = chain.request(); 30 | Request.Builder builder = request.newBuilder(); 31 | String cookie = getCookie(request.url().toString(), request.url().host()); 32 | if (!TextUtils.isEmpty(cookie)) { 33 | builder.addHeader("Cookie", cookie); 34 | Log.i(LogTAG.cookie, "interceptor addHeader Cookie: "+cookie); 35 | } 36 | return chain.proceed(builder.build()); 37 | } 38 | 39 | private String getCookie(String url, String domain) { 40 | 41 | SharedPreferences sp = HomeApplication.getInstance().getSharedPreferences(COOKIE_PREF, 42 | Context.MODE_PRIVATE); 43 | 44 | String cookie = sp.getString(domain, ""); 45 | Log.i(LogTAG.cookie, "interceptor getCookie: "+cookie); 46 | 47 | 48 | if (!TextUtils.isEmpty(domain) && sp.contains(domain) && ! 49 | TextUtils.isEmpty(sp.getString(domain, ""))) { 50 | return sp.getString(domain, ""); 51 | } 52 | return null; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/cookie/SaCookieManger.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.cookie; 2 | 3 | import android.content.Context; 4 | 5 | import com.example.administrator.sharex5webviewdemo.tools.LogTAG; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import okhttp3.Cookie; 11 | import okhttp3.CookieJar; 12 | import okhttp3.HttpUrl; 13 | 14 | /** 15 | * Created by tzw on 2018/3/12. 16 | * 17 | */ 18 | 19 | public class SaCookieManger implements CookieJar { 20 | 21 | private static final String TAG = LogTAG.cookie; 22 | private static Context mContext; 23 | 24 | public SaCookieManger(Context context) { 25 | mContext = context; 26 | } 27 | 28 | @Override 29 | public void saveFromResponse(HttpUrl url, List cookies) { 30 | SaasCookieManager.loadCookie(cookies,url.host()); 31 | } 32 | 33 | @Override 34 | public List loadForRequest(HttpUrl url) { 35 | return new ArrayList<>(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/cookie/SaasCookieManager.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.cookie; 2 | 3 | import android.os.Build; 4 | import android.util.Log; 5 | 6 | 7 | import com.example.administrator.sharex5webviewdemo.tools.LogTAG; 8 | import com.example.administrator.sharex5webviewdemo.tools.Logger; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | import okhttp3.Cookie; 14 | 15 | /** 16 | * Created by tzw on 2018/3/12. 17 | */ 18 | 19 | public class SaasCookieManager { 20 | /** 21 | * 获取cookie 22 | * @param cookies 23 | * @param url 24 | */ 25 | public static void loadCookie(List cookies, String url){ 26 | List convertCookies = new ArrayList<>(); 27 | 28 | for (int i = 0; i < cookies.size(); i++) { 29 | String temp = cookies.get(i).toString(); 30 | convertCookies.add(temp); 31 | } 32 | com.tencent.smtt.sdk.CookieManager cookieManager= com.tencent.smtt.sdk.CookieManager.getInstance(); 33 | cookieManager.setAcceptCookie(true); 34 | 35 | for (String aCookiesArray : convertCookies) { 36 | cookieManager.setCookie(url, aCookiesArray); 37 | } 38 | if (Build.VERSION.SDK_INT <21){ 39 | com.tencent.smtt.sdk.CookieSyncManager.getInstance().sync(); 40 | }else { 41 | com.tencent.smtt.sdk.CookieManager.getInstance().flush(); 42 | } 43 | } 44 | 45 | 46 | /** 47 | * 48 | * 49 | * 是否是X5 50 | */ 51 | @Deprecated 52 | public static void loadCookie(String cookies, String url, boolean isX5){ 53 | Log.e("OkHttp_Cookies", "loadCookie: "+cookies); 54 | String[] cookiesArray=splitCookies(cookies); 55 | com.tencent.smtt.sdk.CookieManager cookieManager= com.tencent.smtt.sdk.CookieManager.getInstance(); 56 | cookieManager.setAcceptCookie(true); 57 | 58 | for (String aCookiesArray : cookiesArray) { 59 | cookieManager.setCookie(url, aCookiesArray); 60 | } 61 | if (Build.VERSION.SDK_INT <21){ 62 | com.tencent.smtt.sdk.CookieSyncManager.getInstance().sync(); 63 | }else { 64 | com.tencent.smtt.sdk.CookieManager.getInstance().flush(); 65 | } 66 | 67 | } 68 | 69 | public static void removeCookie(){ 70 | // 71 | Log.i("OkHttp_Cookies","removeCookie!"); 72 | com.tencent.smtt.sdk.CookieManager cm= com.tencent.smtt.sdk.CookieManager.getInstance(); 73 | cm.removeSessionCookie(); 74 | cm.removeExpiredCookie(); 75 | cm.removeAllCookie(); 76 | if (Build.VERSION.SDK_INT <21){ 77 | com.tencent.smtt.sdk.CookieSyncManager.getInstance().sync(); 78 | }else { 79 | com.tencent.smtt.sdk.CookieManager.getInstance().flush(); 80 | } 81 | 82 | } 83 | private static String[] splitCookies(String cookies){ 84 | return cookies.split("[;]"); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/cookie/SaveCookiesInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.cookie; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.text.TextUtils; 6 | 7 | 8 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.HomeApplication; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.Iterator; 13 | import java.util.List; 14 | 15 | import okhttp3.Interceptor; 16 | import okhttp3.Request; 17 | import okhttp3.Response; 18 | 19 | /** 20 | * 存储cookie拦截器 21 | */ 22 | public class SaveCookiesInterceptor implements Interceptor { 23 | private static final String COOKIE_PREF = "cookies_prefs"; 24 | @Override 25 | public Response intercept(Chain chain) throws IOException { 26 | Request request = chain.request(); 27 | Response response = chain.proceed(request); 28 | if (!response.headers("set-cookie").isEmpty()) { 29 | 30 | List cookies = response.headers("set-cookie"); 31 | 32 | String cookie = encodeCookie(cookies); 33 | 34 | saveCookie(request.url().toString(), request.url().host(), cookie); 35 | } 36 | return response; 37 | } 38 | /** 39 | * 整合cookie为唯一字符串 40 | * @param cookies 41 | * @return 42 | */ 43 | private String encodeCookie(List cookies) { 44 | 45 | 46 | StringBuilder sb = new StringBuilder(); 47 | 48 | List set = new ArrayList<>(); 49 | for (String cookie : cookies) { 50 | String[] arr = cookie.split(";"); 51 | for (String s : arr) { 52 | if (set.contains(s)) { 53 | continue; 54 | } 55 | set.add(s); 56 | } 57 | } 58 | 59 | Iterator ite = set.iterator(); 60 | while (ite.hasNext()) { 61 | String cookie = ite.next(); 62 | sb.append(cookie).append(";"); 63 | } 64 | int last = sb.lastIndexOf(";"); 65 | if (sb.length() - 1 == last) { 66 | sb.deleteCharAt(last); 67 | } 68 | return sb.toString(); 69 | 70 | } 71 | 72 | /** 73 | * 持久化cookie 74 | */ 75 | private void saveCookie(String url, String domain, String cookies) { 76 | SharedPreferences sp = HomeApplication.getInstance().getSharedPreferences(COOKIE_PREF, 77 | Context.MODE_PRIVATE); 78 | SharedPreferences.Editor editor = sp.edit(); 79 | 80 | if (TextUtils.isEmpty(url)) { 81 | throw new NullPointerException("url is null."); 82 | }else{ 83 | editor.putString(url, cookies); 84 | } 85 | 86 | if (!TextUtils.isEmpty(domain)) { 87 | editor.putString(domain, cookies); 88 | } 89 | 90 | editor.apply(); 91 | } 92 | 93 | 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/model/MVPLoginBean.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.model; 2 | 3 | 4 | 5 | public class MVPLoginBean { 6 | 7 | private String userName; 8 | private String passWord; 9 | 10 | public MVPLoginBean() { 11 | super(); 12 | } 13 | 14 | public MVPLoginBean(String userName, String passWord) { 15 | super(); 16 | this.userName = userName; 17 | this.passWord = passWord; 18 | } 19 | 20 | public String getUserName() { 21 | return userName; 22 | } 23 | 24 | public void setUserName(String userName) { 25 | this.userName = userName; 26 | } 27 | 28 | public String getPassWord() { 29 | return passWord; 30 | } 31 | 32 | public void setPassWord(String passWord) { 33 | this.passWord = passWord; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "MVPLoginBean [userName=" + userName + ", passWord=" + passWord 39 | + "]"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/model/MVPLoginResultBean.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.model; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by tzw on 2018/3/13. 8 | */ 9 | 10 | public class MVPLoginResultBean implements Parcelable { 11 | 12 | private int code; 13 | private String msg; 14 | private UserBean user; 15 | 16 | public int getCode() { 17 | return code; 18 | } 19 | 20 | public void setCode(int code) { 21 | this.code = code; 22 | } 23 | 24 | public String getMsg() { 25 | return msg; 26 | } 27 | 28 | public void setMsg(String msg) { 29 | this.msg = msg; 30 | } 31 | 32 | public UserBean getUser() { 33 | return user; 34 | } 35 | 36 | public void setUser(UserBean user) { 37 | this.user = user; 38 | } 39 | 40 | 41 | 42 | public static class UserBean implements Parcelable { 43 | 44 | 45 | private int id; 46 | private String username; 47 | private String icon; 48 | private int gift_count; 49 | 50 | public int getId() { 51 | return id; 52 | } 53 | 54 | public void setId(int id) { 55 | this.id = id; 56 | } 57 | 58 | public String getUsername() { 59 | return username; 60 | } 61 | 62 | public void setUsername(String username) { 63 | this.username = username; 64 | } 65 | 66 | public String getIcon() { 67 | return icon; 68 | } 69 | 70 | public void setIcon(String icon) { 71 | this.icon = icon; 72 | } 73 | 74 | public int getGift_count() { 75 | return gift_count; 76 | } 77 | 78 | public void setGift_count(int gift_count) { 79 | this.gift_count = gift_count; 80 | } 81 | 82 | @Override 83 | public int describeContents() { 84 | return 0; 85 | } 86 | 87 | @Override 88 | public void writeToParcel(Parcel dest, int flags) { 89 | dest.writeInt(this.id); 90 | dest.writeString(this.username); 91 | dest.writeString(this.icon); 92 | dest.writeInt(this.gift_count); 93 | } 94 | 95 | public UserBean() { 96 | } 97 | 98 | protected UserBean(Parcel in) { 99 | this.id = in.readInt(); 100 | this.username = in.readString(); 101 | this.icon = in.readString(); 102 | this.gift_count = in.readInt(); 103 | } 104 | 105 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 106 | @Override 107 | public UserBean createFromParcel(Parcel source) { 108 | return new UserBean(source); 109 | } 110 | 111 | @Override 112 | public UserBean[] newArray(int size) { 113 | return new UserBean[size]; 114 | } 115 | }; 116 | } 117 | 118 | @Override 119 | public int describeContents() { 120 | return 0; 121 | } 122 | 123 | @Override 124 | public void writeToParcel(Parcel dest, int flags) { 125 | dest.writeInt(this.code); 126 | dest.writeString(this.msg); 127 | dest.writeParcelable(this.user, flags); 128 | } 129 | 130 | public MVPLoginResultBean() { 131 | } 132 | 133 | protected MVPLoginResultBean(Parcel in) { 134 | this.code = in.readInt(); 135 | this.msg = in.readString(); 136 | this.user = in.readParcelable(UserBean.class.getClassLoader()); 137 | } 138 | 139 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 140 | @Override 141 | public MVPLoginResultBean createFromParcel(Parcel source) { 142 | return new MVPLoginResultBean(source); 143 | } 144 | 145 | @Override 146 | public MVPLoginResultBean[] newArray(int size) { 147 | return new MVPLoginResultBean[size]; 148 | } 149 | }; 150 | } 151 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvp_use/ImpLoginPresenter.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvp_use; 2 | 3 | import com.example.administrator.sharex5webviewdemo.model.MVPLoginBean; 4 | import com.example.administrator.sharex5webviewdemo.model.MVPLoginResultBean; 5 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.ImpBasePresenter; 6 | import com.example.administrator.sharex5webviewdemo.tools.HttpUrlConstance; 7 | import com.example.administrator.sharex5webviewdemo.tools.OkHttpRequestUtil; 8 | import com.example.administrator.sharex5webviewdemo.tools.ProjectDataDescribe; 9 | import com.google.gson.Gson; 10 | 11 | import org.json.JSONObject; 12 | 13 | import java.io.IOException; 14 | import java.util.HashMap; 15 | 16 | import okhttp3.Request; 17 | 18 | /** 19 | * Created by tzw on 2018/3/13. 20 | */ 21 | 22 | public class ImpLoginPresenter extends ImpBasePresenter implements MVPLoginPresenter{ 23 | 24 | private MVPLoginView mvpLoginView; 25 | 26 | @Override 27 | public void attachView(MVPLoginView baseView) { 28 | this.mvpLoginView = baseView; 29 | } 30 | 31 | @Override 32 | public void login(MVPLoginBean bean) { 33 | String userName = bean.getUserName(); 34 | String passWord = bean.getPassWord(); 35 | 36 | HashMap map = new HashMap<>(); 37 | map.put("username",userName); 38 | map.put("password",passWord); 39 | 40 | OkHttpRequestUtil.okPostFormRequest(HttpUrlConstance.APP_LOGIN, map, new OkHttpRequestUtil.DataCallBack() { 41 | @Override 42 | public void requestSuccess(String result) throws Exception { 43 | JSONObject j = new JSONObject(result); 44 | MVPLoginResultBean mvpLoginResultBean = new Gson().fromJson(j.toString(), MVPLoginResultBean.class); 45 | int code = mvpLoginResultBean.getCode(); 46 | String msg = mvpLoginResultBean.getMsg(); 47 | 48 | if (code == 0){ 49 | mvpLoginView.loginSuccess(ProjectDataDescribe.NET_OK,"账号密码登录成功",""); 50 | }else if (code == 1){ 51 | mvpLoginView.loginFailed(ProjectDataDescribe.NET_ON_FAILURE,msg); 52 | }else { 53 | 54 | } 55 | 56 | } 57 | 58 | @Override 59 | public void requestFailure(Request request, IOException e) { 60 | mvpLoginView.loginFailed(ProjectDataDescribe.SERVER_ERROR,ProjectDataDescribe.SERVER_ERROR); 61 | } 62 | 63 | @Override 64 | public void requestNoNet(String msg, String data) { 65 | mvpLoginView.loginFailed(ProjectDataDescribe.NET_NO_LINKING,ProjectDataDescribe.NET_NO_LINKING); 66 | } 67 | }); 68 | } 69 | 70 | @Override 71 | public void detachView() { 72 | this.mvpLoginView = null; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvp_use/MVPLoginPresenter.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvp_use; 2 | 3 | import com.example.administrator.sharex5webviewdemo.model.MVPLoginBean; 4 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.BasePresenter; 5 | 6 | /** 7 | * Created by tzw on 2018/3/13. 8 | */ 9 | 10 | public interface MVPLoginPresenter extends BasePresenter{ 11 | void login(MVPLoginBean bean); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvp_use/MVPLoginView.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvp_use; 2 | 3 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.BaseView; 4 | 5 | /** 6 | * Created by tzw on 2018/3/13. 7 | */ 8 | 9 | public interface MVPLoginView extends BaseView{ 10 | 11 | void loginSuccess(String msg, String data,Object object); 12 | 13 | void loginFailed(String msg, String data); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvpbase/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvpbase; 2 | 3 | import android.content.pm.ActivityInfo; 4 | import android.graphics.Color; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | import android.util.SparseArray; 10 | import android.util.TypedValue; 11 | import android.view.View; 12 | import android.view.Window; 13 | import android.view.WindowManager; 14 | 15 | import com.example.administrator.sharex5webviewdemo.R; 16 | import com.example.administrator.sharex5webviewdemo.tools.ActivityUtils; 17 | import com.example.administrator.sharex5webviewdemo.tools.SystemBarTintManager; 18 | 19 | /** 20 | * Created by tzw on 2018/3/13. 21 | * 简单的AppCompatActivity封装 22 | */ 23 | 24 | public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{ 25 | 26 | private SparseArray mViews; 27 | 28 | // 获取布局id(setContentView) 29 | public abstract int getLayoutId(); 30 | // 初始化view 31 | public abstract void initViews(); 32 | // 初始化点击事件 33 | public abstract void initListener(); 34 | // 初始化数据 35 | public abstract void initData(); 36 | // 处理具体的点击事件 37 | public abstract void processClick(View v); 38 | 39 | public void onClick(View v) { 40 | processClick(v); 41 | } 42 | // 设置Activit的方向 true == 横屏 false == 竖屏 43 | public boolean setScreenOrientation(){ 44 | return true; 45 | } 46 | 47 | @Override 48 | public void onCreate(Bundle savedInstanceState) { 49 | super.onCreate(savedInstanceState); 50 | 51 | mViews = new SparseArray<>(); 52 | 53 | if (setScreenOrientation()){ 54 | //强制为竖屏 55 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 56 | }else { 57 | //强制为横屏 58 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 59 | } 60 | 61 | setContentView( getLayoutId() ); 62 | ActivityUtils.getInstance().attach(this); 63 | 64 | initViews(); 65 | initListener(); 66 | initData(); 67 | 68 | } 69 | 70 | 71 | public E $(int viewId) { 72 | E view = (E) mViews.get(viewId); 73 | if (view == null) { 74 | view = (E) findViewById(viewId); 75 | mViews.put(viewId, view); 76 | } 77 | return view; 78 | } 79 | 80 | 81 | public void setOnClick(E view){ 82 | view.setOnClickListener(this); 83 | } 84 | 85 | 86 | /** 子类可以重写改变状态栏颜色 */ 87 | protected int setStatusBarColor() { 88 | return getColorPrimary(); 89 | } 90 | 91 | /** 子类可以重写决定是否使用透明状态栏 */ 92 | protected boolean translucentStatusBar() { 93 | return false; 94 | } 95 | 96 | 97 | /** 设置状态栏颜色 */ 98 | protected void initSystemBarTint() { 99 | Window window = getWindow(); 100 | if (translucentStatusBar()) { 101 | // 设置状态栏全透明 102 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 103 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 104 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 105 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 106 | window.setStatusBarColor(Color.TRANSPARENT); 107 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 108 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 109 | } 110 | return; 111 | } 112 | // 沉浸式状态栏 113 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 114 | //5.0以上使用原生方法 115 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 116 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 117 | window.setStatusBarColor(setStatusBarColor()); 118 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 119 | //4.4-5.0使用三方工具类,有些4.4的手机有问题,这里为演示方便,不使用沉浸式 120 | // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 121 | SystemBarTintManager tintManager = new SystemBarTintManager(this); 122 | tintManager.setStatusBarTintEnabled(true); 123 | tintManager.setStatusBarTintColor(setStatusBarColor()); 124 | } 125 | } 126 | 127 | /** 获取主题色 */ 128 | public int getColorPrimary() { 129 | TypedValue typedValue = new TypedValue(); 130 | getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true); 131 | return typedValue.data; 132 | } 133 | 134 | /** 获取深主题色 */ 135 | public int getDarkColorPrimary() { 136 | TypedValue typedValue = new TypedValue(); 137 | getTheme().resolveAttribute(R.attr.colorPrimaryDark, typedValue, true); 138 | return typedValue.data; 139 | } 140 | 141 | /** 初始化 Toolbar */ 142 | public void initToolBar(Toolbar toolbar, boolean homeAsUpEnabled, String title) { 143 | toolbar.setTitle(title); 144 | setSupportActionBar(toolbar); 145 | getSupportActionBar().setDisplayHomeAsUpEnabled(homeAsUpEnabled); 146 | } 147 | 148 | /** 初始化 Toolbar 字体设置居中需要在toolbar里面包一层*/ 149 | public void initToolBar(Toolbar toolbar, boolean homeAsUpEnabled) { 150 | toolbar.setTitle(""); 151 | setSupportActionBar(toolbar); 152 | getSupportActionBar().setDisplayHomeAsUpEnabled(homeAsUpEnabled); 153 | } 154 | 155 | 156 | public void initToolBar(Toolbar toolbar, boolean homeAsUpEnabled, int resTitle) { 157 | initToolBar(toolbar, homeAsUpEnabled, getString(resTitle)); 158 | } 159 | 160 | 161 | @Override 162 | protected void onDestroy() { 163 | super.onDestroy(); 164 | ActivityUtils.getInstance().detach(this); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvpbase/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvpbase; 2 | 3 | /** 4 | * Created by tzw on 2018/3/13. 5 | * MVP-P层接口的基类 6 | */ 7 | 8 | public interface BasePresenter { 9 | // 绑定 10 | void attachView(T t); 11 | 12 | // 解绑 13 | void detachView(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvpbase/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvpbase; 2 | 3 | /** 4 | * Created by tzw on 2018/3/13. 5 | * MVP-V层基类 6 | */ 7 | 8 | public interface BaseView { 9 | // 回调信息 10 | void showInfo(String msg,String data,Object o) ; 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvpbase/HomeApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvpbase; 2 | import android.app.Application; 3 | import android.content.Intent; 4 | import com.example.administrator.sharex5webviewdemo.tools.X5NetService; 5 | 6 | public class HomeApplication extends Application { 7 | 8 | private static HomeApplication homeApplication; 9 | @Override 10 | public void onCreate() { 11 | super.onCreate(); 12 | homeApplication=this; 13 | preInitX5Core(); 14 | } 15 | 16 | public static HomeApplication getInstance(){ 17 | return homeApplication; 18 | } 19 | 20 | private void preInitX5Core() { 21 | //预加载x5内核 22 | Intent intent = new Intent(this, X5NetService.class); 23 | startService(intent); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/mvp/mvpbase/ImpBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.mvp.mvpbase; 2 | 3 | /** 4 | * Created by tzw on 2018/3/13. 5 | */ 6 | 7 | public class ImpBasePresenter implements BasePresenter{ 8 | 9 | private T mBaseView; 10 | 11 | @Override 12 | public void attachView(T baseView) { 13 | this.mBaseView = baseView; 14 | } 15 | 16 | @Override 17 | public void detachView() { 18 | this.mBaseView = null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/ActivityUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | import android.app.Activity; 4 | 5 | import java.util.concurrent.CopyOnWriteArrayList; 6 | 7 | /** 8 | * Created by tzw on 2018/3/1. 9 | * Activity的管理工具类 10 | */ 11 | 12 | public class ActivityUtils { 13 | 14 | private static volatile ActivityUtils mInstance; 15 | 16 | /** 17 | * 所有打开的Activity 18 | */ 19 | private final CopyOnWriteArrayList mActivities; 20 | 21 | private ActivityUtils() { 22 | mActivities = new CopyOnWriteArrayList<>(); 23 | } 24 | 25 | public static ActivityUtils getInstance() { 26 | if (mInstance == null) { 27 | synchronized (ActivityUtils.class) { 28 | if (mInstance == null) { 29 | mInstance = new ActivityUtils(); 30 | } 31 | } 32 | } 33 | return mInstance; 34 | } 35 | 36 | /** 37 | * 添加统一管理 38 | */ 39 | public void attach(Activity activity) { 40 | mActivities.add(activity); 41 | } 42 | 43 | /** 44 | * 移除解绑 - 防止内存泄漏 45 | * 46 | * @param detachActivity 47 | */ 48 | public synchronized void detach(Activity detachActivity) { 49 | int size = mActivities.size(); 50 | for (int i = 0; i < size; i++) { 51 | if (mActivities.get(i) == detachActivity) { 52 | mActivities.remove(i); 53 | size--; 54 | i--; 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * 根据Activity的类名关闭 Activity 61 | */ 62 | public void finish(Class activityClass) { 63 | for (int i = 0; i < mActivities.size(); i++) { 64 | Activity activity = mActivities.get(i); 65 | if (activity.getClass().getCanonicalName().equals(activityClass.getCanonicalName())) { 66 | activity.finish(); 67 | break; 68 | } 69 | } 70 | } 71 | 72 | /** 73 | * 退出整个应用 74 | */ 75 | public void exit() { 76 | int size = mActivities.size(); 77 | for (int i = 0; i < size; i++) { 78 | Activity activity = mActivities.get(i); 79 | activity.finish(); 80 | } 81 | } 82 | 83 | /** 84 | * 获取当前的Activity(最前面) 85 | */ 86 | public Activity getCurrentActivity() { 87 | return mActivities.get(mActivities.size() - 1); 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/CheckNetUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | /** 8 | * Created by tzw on 2018/2/28. 9 | * 检查是否有网络 10 | * 请求失败的时候,可以先判断是否有网还是服务器异常 11 | */ 12 | 13 | public class CheckNetUtil { 14 | 15 | public static final String TAG = LogTAG.net; 16 | 17 | /** 18 | * 检查是否有网络 19 | */ 20 | public static boolean checkNet(Context context) { 21 | ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 22 | if (connectivity == null) { 23 | Logger.i(TAG,"NetWorkState : " + "Unavailabel"); 24 | return false; 25 | } else { 26 | NetworkInfo[] info = connectivity.getAllNetworkInfo(); 27 | if (info != null) { 28 | for (int i = 0; i < info.length; i++) { 29 | if (info[i].getState() == NetworkInfo.State.CONNECTED) { 30 | Logger.i(TAG,"NetWorkState : " + "Availabel"); 31 | return true; 32 | } 33 | } 34 | } 35 | } 36 | return false; 37 | } 38 | 39 | /** 40 | * 检查是否是WIFI 41 | */ 42 | public static boolean isWifi(Context context) { 43 | NetworkInfo info = getNetworkInfo(context); 44 | if (info != null) { 45 | if (info.getType() == ConnectivityManager.TYPE_WIFI) { 46 | Logger.i(TAG,"NetWorkState : " + "TYPE_WIFI_SUCCESS"); 47 | return true; 48 | 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | /** 55 | * 检查是否是移动网络 56 | */ 57 | public static boolean isMobile(Context context) { 58 | NetworkInfo info = getNetworkInfo(context); 59 | if (info != null) { 60 | if (info.getType() == ConnectivityManager.TYPE_MOBILE) 61 | Logger.i(TAG,"NetWorkState : " + "TYPE_MOBILE_SUCCESS"); 62 | 63 | return true; 64 | } 65 | return false; 66 | } 67 | 68 | private static NetworkInfo getNetworkInfo(Context context) { 69 | 70 | ConnectivityManager cm = (ConnectivityManager) context 71 | .getSystemService(Context.CONNECTIVITY_SERVICE); 72 | return cm.getActiveNetworkInfo(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/HttpUrlConstance.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | /** 4 | * !!!注意!!! 5 | * 6 | * !!!此接口只能作为学习使用!!! 7 | * !!!不能用作任何商业用途 违者必究!!! 8 | */ 9 | public class HttpUrlConstance { 10 | 11 | public static String BAI_DU = "https://www.baidu.com/"; 12 | public static String APP_LOGIN = "http://i.263wan.cn/AppApi/userLogin"; 13 | public static String APP_KONWX5 = "https://www.jianshu.com/p/e4c1a3fc02e8"; 14 | public static String APP_GAMESDK = "https://www.jianshu.com/p/8b9d82560a67"; 15 | public static String APP_GAME_ = "http://i.263wan.cn/Game/game/appid/100016/agent/0/from_device/app"; 16 | public static String APP_MYINFO = "https://www.jianshu.com/u/0111a7da544b"; 17 | public static String APP_INTERVIEW = "https://www.jianshu.com/p/10b29eef7bfb"; 18 | public static String APP_BUTTERKNIFE = "https://www.jianshu.com/p/ba8bf1b9ff2b"; 19 | public static String APP_CHANNELPACKAGE = "https://www.jianshu.com/p/332525b09a88"; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/LogTAG.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | /** 4 | * Created by tzw on 2018/3/13. 5 | * 日志TAG 方便开发人员寻找日志TAG 6 | */ 7 | 8 | public final class LogTAG { 9 | 10 | public static final String login = "login"; 11 | public static final String okhttp = "okhttp"; 12 | public static final String x5webview = "x5webview"; 13 | public static final String net = "net"; 14 | public static final String cookie = "cookie"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/Logger.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by tzw on 2018/3/13. 7 | */ 8 | 9 | public class Logger { 10 | 11 | // 是否开启日志 12 | public static final boolean logTAG = true; 13 | // 默认日志TAG 14 | public static final String TAG = "log"; 15 | // 不写日志TAG 只输出日志信息 16 | public static void i(String desData) { 17 | if (logTAG) { 18 | Log.i(TAG, desData); 19 | } else { 20 | Log.i(TAG, "desData was close "); 21 | } 22 | } 23 | 24 | // 自定义日志TAG ===>> 输出日志信息 25 | public static void i(String debugTag, String debugData) { 26 | if (logTAG) { 27 | Log.i(debugTag, debugData); 28 | } else { 29 | Log.i(debugTag, "debugData was close "); 30 | } 31 | } 32 | 33 | public static void e(String debugData) { 34 | if (logTAG) { 35 | Log.e(TAG, " :" + debugData); 36 | } else { 37 | Log.e(TAG, "debugData was close "); 38 | } 39 | } 40 | 41 | public static void e(String debugTag, String debugData) { 42 | if (logTAG) { 43 | Log.e(debugTag, " :" + debugData); 44 | } else { 45 | Log.e(debugTag, "debugData was close "); 46 | 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/OkHttpRequestUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.util.Log; 6 | 7 | 8 | import com.example.administrator.sharex5webviewdemo.cookie.AddCookiesInterceptor; 9 | import com.example.administrator.sharex5webviewdemo.cookie.SaCookieManger; 10 | import com.example.administrator.sharex5webviewdemo.cookie.SaveCookiesInterceptor; 11 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.HomeApplication; 12 | import com.google.gson.Gson; 13 | 14 | import java.io.IOException; 15 | import java.util.HashMap; 16 | import java.util.List; 17 | import java.util.Map; 18 | import java.util.Set; 19 | import java.util.concurrent.TimeUnit; 20 | 21 | import okhttp3.Call; 22 | import okhttp3.Callback; 23 | import okhttp3.Cookie; 24 | import okhttp3.FormBody; 25 | import okhttp3.Headers; 26 | import okhttp3.MediaType; 27 | import okhttp3.OkHttpClient; 28 | import okhttp3.Request; 29 | import okhttp3.RequestBody; 30 | import okhttp3.Response; 31 | import okhttp3.logging.HttpLoggingInterceptor; 32 | 33 | /** 34 | * Created by tzw on 2018/3/13. 35 | * 简单的Okhttp 封装工具类 36 | */ 37 | 38 | public class OkHttpRequestUtil { 39 | 40 | private volatile static OkHttpRequestUtil netRequest; 41 | private static OkHttpClient okHttpClient; // OKHttp网络请求 42 | private Handler mHandler; 43 | final String TAG = LogTAG.okhttp; 44 | private boolean checkNet; 45 | 46 | private final HashMap> cookieStore = new HashMap<>(); 47 | 48 | private OkHttpRequestUtil() { 49 | 50 | okHttpClient = new OkHttpClient.Builder() 51 | .connectTimeout(10, TimeUnit.SECONDS) 52 | .readTimeout(10, TimeUnit.SECONDS) 53 | .writeTimeout(10, TimeUnit.SECONDS) 54 | .addNetworkInterceptor(new HttpLoggingInterceptor(). 55 | setLevel(HttpLoggingInterceptor.Level.BODY)) 56 | .addInterceptor(new AddCookiesInterceptor()) 57 | .addInterceptor(new SaveCookiesInterceptor()) 58 | .cookieJar(new SaCookieManger(HomeApplication.getInstance())) 59 | .build(); 60 | 61 | mHandler = new Handler(Looper.getMainLooper()); 62 | } 63 | 64 | private static OkHttpRequestUtil getInstance() { 65 | if (netRequest == null) { 66 | netRequest = new OkHttpRequestUtil(); 67 | } 68 | return netRequest; 69 | } 70 | 71 | /** 72 | * 异步get请求(Form),内部实现方法 73 | * @param url url 74 | * @param params key value 75 | */ 76 | public void inner_GetFormAsync(String url, Map params, final DataCallBack callBack) { 77 | 78 | if (params == null) { 79 | params = new HashMap<>(); 80 | } 81 | final String doUrl = urlJoint(url, params); 82 | final Request request = new Request.Builder().url(doUrl).build(); 83 | Call call = okHttpClient.newCall(request); 84 | call.enqueue(new Callback() { 85 | @Override 86 | public void onFailure(Call call, IOException e) { 87 | deliverDataFailure(request, e, callBack); 88 | } 89 | @Override 90 | public void onResponse(Call call, Response response) throws IOException { 91 | if (response != null && response.isSuccessful()) { 92 | String result = response.body().string(); 93 | deliverDataSuccess(result, callBack); 94 | } else { 95 | throw new IOException(response + ""); 96 | } 97 | } 98 | }); 99 | 100 | } 101 | 102 | /** 103 | * get请求 没有请求体 104 | * 105 | * @param url 106 | * @param callBack 107 | */ 108 | private void getMethod(String url, final DataCallBack callBack) { 109 | final Request req = new Request.Builder().url(url).build(); 110 | okHttpClient.newCall(req).enqueue(new Callback() { 111 | @Override 112 | public void onFailure(Call call, IOException e) { 113 | deliverDataFailure(req, e, callBack); 114 | } 115 | @Override 116 | public void onResponse(Call call, Response response) throws IOException { 117 | if (response != null && response.isSuccessful()) { 118 | String result = response.body().string(); 119 | deliverDataSuccess(result, callBack); 120 | } else { 121 | deliverDataSuccess("请求异常", callBack); 122 | 123 | } 124 | } 125 | }); 126 | 127 | } 128 | 129 | /** 130 | * 异步post请求(Form),内部实现方法 131 | * @param url url 132 | * @param params params 133 | * @param callBack callBack 134 | */ 135 | 136 | private void inner_PostFormAsync(String url, Map params, final DataCallBack callBack) { 137 | RequestBody requestBody; 138 | if (params == null) { 139 | params = new HashMap<>(); 140 | } 141 | FormBody.Builder builder = new FormBody.Builder(); 142 | /** 143 | * 在这对添加的参数进行遍历 144 | */ 145 | for (Map.Entry map : params.entrySet()) { 146 | String key = map.getKey(); 147 | String value; 148 | /** 149 | * 判断值是否是空的 150 | */ 151 | if (map.getValue() == null) { 152 | value = ""; 153 | } else { 154 | value = map.getValue(); 155 | } 156 | /** 157 | * 把key和value添加到formbody中 158 | */ 159 | builder.add(key, value); 160 | } 161 | 162 | requestBody = builder.build(); 163 | final Request request = new Request.Builder().url(url).post(requestBody).build(); 164 | 165 | okHttpClient.newCall(request).enqueue(new Callback() { 166 | @Override 167 | public void onFailure(Call call, IOException e) { 168 | deliverDataFailure(request, e, callBack); 169 | } 170 | 171 | @Override 172 | public void onResponse(Call call, Response response) throws IOException { 173 | if (response.isSuccessful()) { // 请求成功 174 | Headers newHead = response.networkResponse().request().headers(); 175 | Log.i(TAG, "new headers :: " + newHead); 176 | //执行请求成功的操作 177 | String result = response.body().string(); 178 | deliverDataSuccess(result, callBack); 179 | } else { 180 | throw new IOException(response + ""); 181 | } 182 | } 183 | }); 184 | } 185 | 186 | 187 | private void inner_PostJsonAsync(String url, Map params, final DataCallBack callBack) { 188 | // 将map转换成json,需要引入Gson包 189 | String mapToJson = new Gson().toJson(params); 190 | 191 | final Request request = buildJsonPostRequest(url, mapToJson); 192 | okHttpClient.newCall(request).enqueue(new Callback() { 193 | @Override 194 | public void onFailure(Call call, IOException e) { 195 | deliverDataFailure(request, e, callBack); 196 | } 197 | 198 | @Override 199 | public void onResponse(Call call, Response response) throws IOException { 200 | if (response.isSuccessful()) { // 请求成功 201 | //执行请求成功的操作 202 | String result = response.body().string(); 203 | deliverDataSuccess(result, callBack); 204 | } else { 205 | throw new IOException(response + ""); 206 | } 207 | } 208 | }); 209 | } 210 | 211 | 212 | private Request buildJsonPostRequest(String url, String json) { 213 | RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json); 214 | return new Request.Builder().url(url).post(requestBody).build(); 215 | } 216 | 217 | 218 | /** 219 | * 分发失败的时候调用 220 | * 客户端没有网络 还是 服务器异常 221 | * @param request request 222 | * @param e e 223 | * @param callBack callBack 224 | */ 225 | private void deliverDataFailure(final Request request, final IOException e, final DataCallBack callBack) { 226 | /** 227 | * 在这里使用异步处理 228 | */ 229 | checkNet = CheckNetUtil.checkNet(HomeApplication.getInstance()); 230 | 231 | mHandler.post(new Runnable() { 232 | @Override 233 | public void run() { 234 | if (callBack != null) { 235 | try { 236 | if (checkNet) { 237 | callBack.requestFailure(request, e); 238 | } else { 239 | callBack.requestNoNet(ProjectDataDescribe.NET_NO_LINKING, 240 | ProjectDataDescribe.NET_NO_LINKING); 241 | } 242 | } catch (Exception e) { 243 | 244 | } 245 | } 246 | } 247 | }); 248 | 249 | } 250 | 251 | /** 252 | * 分发成功的时候调用 253 | * 254 | * @param result result 255 | * @param callBack callBack 256 | */ 257 | private void deliverDataSuccess(final String result, final DataCallBack callBack) { 258 | /** 259 | * 在这里使用异步线程处理 260 | */ 261 | mHandler.post(new Runnable() { 262 | @Override 263 | public void run() { 264 | if (callBack != null) { 265 | try { 266 | callBack.requestSuccess(result); 267 | 268 | } catch (Exception e) { 269 | e.printStackTrace(); 270 | } 271 | } 272 | } 273 | }); 274 | } 275 | 276 | /** 277 | * 数据回调接口 278 | */ 279 | public interface DataCallBack { 280 | 281 | // 请求成功 响应成功 282 | void requestSuccess(String result) throws Exception; 283 | // 请求失败 响应失败 284 | void requestFailure(Request request, IOException e); 285 | // 客户端没有网络连接 286 | void requestNoNet(String msg,String data); 287 | 288 | } 289 | 290 | /** 291 | * 拼接url和请求参数 292 | * 293 | * @param url url 294 | * @param params key value 295 | * @return String url 296 | */ 297 | private static String urlJoint(String url, Map params) { 298 | 299 | StringBuilder endUrl = new StringBuilder(url); 300 | boolean isFirst = true; 301 | Set> entrySet = params.entrySet(); 302 | 303 | for (Map.Entry entry : entrySet) { 304 | if (isFirst && !url.contains("?")) { 305 | isFirst = false; 306 | endUrl.append("?"); 307 | } else { 308 | endUrl.append("&"); 309 | } 310 | endUrl.append(entry.getKey()); 311 | endUrl.append("="); 312 | endUrl.append(entry.getValue()); 313 | } 314 | return endUrl.toString(); 315 | 316 | } 317 | 318 | //-------------对外提供的方法Start-------------------------------- 319 | 320 | /** 321 | * 建立网络框架,获取网络数据,异步get请求(Form) 322 | * 323 | * @param url url 324 | * @param params key value 325 | * @param callBack data 326 | */ 327 | public static void okGetFormRequest(String url, Map params, DataCallBack callBack) { 328 | getInstance().inner_GetFormAsync(url, params, callBack); 329 | } 330 | 331 | /** 332 | * 建立网络框架,获取网络数据,异步post请求(Form) 333 | * @param url url 334 | * @param params key value 335 | * @param callBack data 336 | */ 337 | public static void okPostFormRequest(String url, Map params, DataCallBack callBack) { 338 | getInstance().inner_PostFormAsync(url, params, callBack); 339 | } 340 | 341 | /** 342 | * get 请求 343 | * 没有请求体 344 | */ 345 | public static void okGetRequest(String url, DataCallBack callBack) { 346 | getInstance().getMethod(url, callBack); 347 | } 348 | 349 | } 350 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/ProjectDataDescribe.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | /** 4 | * Created by tzw on 2018/3/13. 5 | */ 6 | 7 | public class ProjectDataDescribe { 8 | // 请求成功,响应成功(!--接口成功--!) 9 | public static final String NET_OK = "netOK"; 10 | 11 | // 请求成功,响应失败(!--接口失败--!) 12 | public static final String NET_ON_FAILURE = "netFaiure"; 13 | 14 | // 没有网络链接(!--客户端没有联网--!) 15 | public static final String NET_NO_LINKING = "请检查网络链接~"; 16 | 17 | // 后台服务器错误(!--服务器宕机--!) 18 | public static final String SERVER_ERROR = "serverError"; 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/SystemBarTintManager.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.app.Activity; 6 | import android.content.Context; 7 | import android.content.res.Configuration; 8 | import android.content.res.Resources; 9 | import android.content.res.TypedArray; 10 | import android.graphics.drawable.Drawable; 11 | import android.os.Build; 12 | import android.util.DisplayMetrics; 13 | import android.util.TypedValue; 14 | import android.view.Gravity; 15 | import android.view.View; 16 | import android.view.ViewConfiguration; 17 | import android.view.ViewGroup; 18 | import android.view.Window; 19 | import android.view.WindowManager; 20 | import android.widget.FrameLayout; 21 | 22 | import java.lang.reflect.Method; 23 | 24 | /** 25 | * Created by tzw on 2018/3/13. 26 | */ 27 | 28 | public class SystemBarTintManager { 29 | 30 | static { 31 | // Android allows a system property to override the presence of the navigation bar. 32 | // Used by the emulator. 33 | // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076 34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 35 | try { 36 | Class c = Class.forName("android.os.SystemProperties"); 37 | Method m = c.getDeclaredMethod("get", String.class); 38 | m.setAccessible(true); 39 | sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys"); 40 | } catch (Throwable e) { 41 | sNavBarOverride = null; 42 | } 43 | } 44 | } 45 | 46 | /** 47 | * The default system bar tint color value. 48 | */ 49 | public static final int DEFAULT_TINT_COLOR = 0x99000000; 50 | 51 | private static String sNavBarOverride; 52 | 53 | private final SystemBarConfig mConfig; 54 | private boolean mStatusBarAvailable; 55 | private boolean mNavBarAvailable; 56 | private boolean mStatusBarTintEnabled; 57 | private boolean mNavBarTintEnabled; 58 | private View mStatusBarTintView; 59 | private View mNavBarTintView; 60 | 61 | /** 62 | * Constructor. Call this in the host activity onCreate method after its 63 | * content view has been set. You should always create new instances when 64 | * the host activity is recreated. 65 | * 66 | * @param activity The host activity. 67 | */ 68 | @TargetApi(19) 69 | public SystemBarTintManager(Activity activity) { 70 | 71 | Window win = activity.getWindow(); 72 | ViewGroup decorViewGroup = (ViewGroup) win.getDecorView(); 73 | 74 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 75 | // check theme attrs 76 | int[] attrs = {android.R.attr.windowTranslucentStatus, android.R.attr.windowTranslucentNavigation}; 77 | TypedArray a = activity.obtainStyledAttributes(attrs); 78 | try { 79 | mStatusBarAvailable = a.getBoolean(0, false); 80 | mNavBarAvailable = a.getBoolean(1, false); 81 | } finally { 82 | a.recycle(); 83 | } 84 | 85 | // check window flags 86 | WindowManager.LayoutParams winParams = win.getAttributes(); 87 | int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 88 | if ((winParams.flags & bits) != 0) { 89 | mStatusBarAvailable = true; 90 | } 91 | bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; 92 | if ((winParams.flags & bits) != 0) { 93 | mNavBarAvailable = true; 94 | } 95 | } 96 | 97 | mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable); 98 | // device might not have virtual navigation keys 99 | if (!mConfig.hasNavigtionBar()) { 100 | mNavBarAvailable = false; 101 | } 102 | 103 | if (mStatusBarAvailable) { 104 | setupStatusBarView(activity, decorViewGroup); 105 | } 106 | if (mNavBarAvailable) { 107 | setupNavBarView(activity, decorViewGroup); 108 | } 109 | 110 | } 111 | 112 | /** 113 | * Enable tinting of the system status bar. 114 | * If the platform is running Jelly Bean or earlier, or translucent system 115 | * UI modes have not been enabled in either the theme or via window flags, 116 | * then this method does nothing. 117 | * 118 | * @param enabled True to enable tinting, false to disable it (default). 119 | */ 120 | public void setStatusBarTintEnabled(boolean enabled) { 121 | mStatusBarTintEnabled = enabled; 122 | if (mStatusBarAvailable) { 123 | mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); 124 | } 125 | } 126 | 127 | /** 128 | * Enable tinting of the system navigation bar. 129 | * If the platform does not have soft navigation keys, is running Jelly Bean 130 | * or earlier, or translucent system UI modes have not been enabled in either 131 | * the theme or via window flags, then this method does nothing. 132 | * 133 | * @param enabled True to enable tinting, false to disable it (default). 134 | */ 135 | public void setNavigationBarTintEnabled(boolean enabled) { 136 | mNavBarTintEnabled = enabled; 137 | if (mNavBarAvailable) { 138 | mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); 139 | } 140 | } 141 | 142 | /** 143 | * Apply the specified color tint to all system UI bars. 144 | * 145 | * @param color The color of the background tint. 146 | */ 147 | public void setTintColor(int color) { 148 | setStatusBarTintColor(color); 149 | setNavigationBarTintColor(color); 150 | } 151 | 152 | /** 153 | * Apply the specified drawable or color resource to all system UI bars. 154 | * 155 | * @param res The identifier of the resource. 156 | */ 157 | public void setTintResource(int res) { 158 | setStatusBarTintResource(res); 159 | setNavigationBarTintResource(res); 160 | } 161 | 162 | /** 163 | * Apply the specified drawable to all system UI bars. 164 | * 165 | * @param drawable The drawable to use as the background, or null to remove it. 166 | */ 167 | public void setTintDrawable(Drawable drawable) { 168 | setStatusBarTintDrawable(drawable); 169 | setNavigationBarTintDrawable(drawable); 170 | } 171 | 172 | /** 173 | * Apply the specified alpha to all system UI bars. 174 | * 175 | * @param alpha The alpha to use 176 | */ 177 | public void setTintAlpha(float alpha) { 178 | setStatusBarAlpha(alpha); 179 | setNavigationBarAlpha(alpha); 180 | } 181 | 182 | /** 183 | * Apply the specified color tint to the system status bar. 184 | * 185 | * @param color The color of the background tint. 186 | */ 187 | public void setStatusBarTintColor(int color) { 188 | if (mStatusBarAvailable) { 189 | mStatusBarTintView.setBackgroundColor(color); 190 | } 191 | } 192 | 193 | /** 194 | * Apply the specified drawable or color resource to the system status bar. 195 | * 196 | * @param res The identifier of the resource. 197 | */ 198 | public void setStatusBarTintResource(int res) { 199 | if (mStatusBarAvailable) { 200 | mStatusBarTintView.setBackgroundResource(res); 201 | } 202 | } 203 | 204 | /** 205 | * Apply the specified drawable to the system status bar. 206 | * 207 | * @param drawable The drawable to use as the background, or null to remove it. 208 | */ 209 | @SuppressWarnings("deprecation") 210 | public void setStatusBarTintDrawable(Drawable drawable) { 211 | if (mStatusBarAvailable) { 212 | mStatusBarTintView.setBackgroundDrawable(drawable); 213 | } 214 | } 215 | 216 | /** 217 | * Apply the specified alpha to the system status bar. 218 | * 219 | * @param alpha The alpha to use 220 | */ 221 | @TargetApi(11) 222 | public void setStatusBarAlpha(float alpha) { 223 | if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 224 | mStatusBarTintView.setAlpha(alpha); 225 | } 226 | } 227 | 228 | /** 229 | * Apply the specified color tint to the system navigation bar. 230 | * 231 | * @param color The color of the background tint. 232 | */ 233 | public void setNavigationBarTintColor(int color) { 234 | if (mNavBarAvailable) { 235 | mNavBarTintView.setBackgroundColor(color); 236 | } 237 | } 238 | 239 | /** 240 | * Apply the specified drawable or color resource to the system navigation bar. 241 | * 242 | * @param res The identifier of the resource. 243 | */ 244 | public void setNavigationBarTintResource(int res) { 245 | if (mNavBarAvailable) { 246 | mNavBarTintView.setBackgroundResource(res); 247 | } 248 | } 249 | 250 | /** 251 | * Apply the specified drawable to the system navigation bar. 252 | * 253 | * @param drawable The drawable to use as the background, or null to remove it. 254 | */ 255 | @SuppressWarnings("deprecation") 256 | public void setNavigationBarTintDrawable(Drawable drawable) { 257 | if (mNavBarAvailable) { 258 | mNavBarTintView.setBackgroundDrawable(drawable); 259 | } 260 | } 261 | 262 | /** 263 | * Apply the specified alpha to the system navigation bar. 264 | * 265 | * @param alpha The alpha to use 266 | */ 267 | @TargetApi(11) 268 | public void setNavigationBarAlpha(float alpha) { 269 | if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 270 | mNavBarTintView.setAlpha(alpha); 271 | } 272 | } 273 | 274 | /** 275 | * Get the system bar configuration. 276 | * 277 | * @return The system bar configuration for the current device configuration. 278 | */ 279 | public SystemBarConfig getConfig() { 280 | return mConfig; 281 | } 282 | 283 | /** 284 | * Is tinting enabled for the system status bar? 285 | * 286 | * @return True if enabled, False otherwise. 287 | */ 288 | public boolean isStatusBarTintEnabled() { 289 | return mStatusBarTintEnabled; 290 | } 291 | 292 | /** 293 | * Is tinting enabled for the system navigation bar? 294 | * 295 | * @return True if enabled, False otherwise. 296 | */ 297 | public boolean isNavBarTintEnabled() { 298 | return mNavBarTintEnabled; 299 | } 300 | 301 | private void setupStatusBarView(Context context, ViewGroup decorViewGroup) { 302 | mStatusBarTintView = new View(context); 303 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight()); 304 | params.gravity = Gravity.TOP; 305 | if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) { 306 | params.rightMargin = mConfig.getNavigationBarWidth(); 307 | } 308 | mStatusBarTintView.setLayoutParams(params); 309 | mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); 310 | mStatusBarTintView.setVisibility(View.GONE); 311 | decorViewGroup.addView(mStatusBarTintView); 312 | } 313 | 314 | private void setupNavBarView(Context context, ViewGroup decorViewGroup) { 315 | mNavBarTintView = new View(context); 316 | FrameLayout.LayoutParams params; 317 | if (mConfig.isNavigationAtBottom()) { 318 | params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight()); 319 | params.gravity = Gravity.BOTTOM; 320 | } else { 321 | params = new FrameLayout.LayoutParams(mConfig.getNavigationBarWidth(), FrameLayout.LayoutParams.MATCH_PARENT); 322 | params.gravity = Gravity.RIGHT; 323 | } 324 | mNavBarTintView.setLayoutParams(params); 325 | mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); 326 | mNavBarTintView.setVisibility(View.GONE); 327 | decorViewGroup.addView(mNavBarTintView); 328 | } 329 | 330 | /** 331 | * Class which describes system bar sizing and other characteristics for the current 332 | * device configuration. 333 | */ 334 | public static class SystemBarConfig { 335 | 336 | private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height"; 337 | private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height"; 338 | private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape"; 339 | private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width"; 340 | private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; 341 | 342 | private final boolean mTranslucentStatusBar; 343 | private final boolean mTranslucentNavBar; 344 | private final int mStatusBarHeight; 345 | private final int mActionBarHeight; 346 | private final boolean mHasNavigationBar; 347 | private final int mNavigationBarHeight; 348 | private final int mNavigationBarWidth; 349 | private final boolean mInPortrait; 350 | private final float mSmallestWidthDp; 351 | 352 | private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) { 353 | Resources res = activity.getResources(); 354 | mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT); 355 | mSmallestWidthDp = getSmallestWidthDp(activity); 356 | mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME); 357 | mActionBarHeight = getActionBarHeight(activity); 358 | mNavigationBarHeight = getNavigationBarHeight(activity); 359 | mNavigationBarWidth = getNavigationBarWidth(activity); 360 | mHasNavigationBar = (mNavigationBarHeight > 0); 361 | mTranslucentStatusBar = translucentStatusBar; 362 | mTranslucentNavBar = traslucentNavBar; 363 | } 364 | 365 | @TargetApi(14) 366 | private int getActionBarHeight(Context context) { 367 | int result = 0; 368 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 369 | TypedValue tv = new TypedValue(); 370 | context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true); 371 | result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); 372 | } 373 | return result; 374 | } 375 | 376 | @TargetApi(14) 377 | private int getNavigationBarHeight(Context context) { 378 | Resources res = context.getResources(); 379 | int result = 0; 380 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 381 | if (hasNavBar(context)) { 382 | String key; 383 | if (mInPortrait) { 384 | key = NAV_BAR_HEIGHT_RES_NAME; 385 | } else { 386 | key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME; 387 | } 388 | return getInternalDimensionSize(res, key); 389 | } 390 | } 391 | return result; 392 | } 393 | 394 | @TargetApi(14) 395 | private int getNavigationBarWidth(Context context) { 396 | Resources res = context.getResources(); 397 | int result = 0; 398 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 399 | if (hasNavBar(context)) { 400 | return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME); 401 | } 402 | } 403 | return result; 404 | } 405 | 406 | @TargetApi(14) 407 | private boolean hasNavBar(Context context) { 408 | Resources res = context.getResources(); 409 | int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android"); 410 | if (resourceId != 0) { 411 | boolean hasNav = res.getBoolean(resourceId); 412 | // check override flag (see static block) 413 | if ("1".equals(sNavBarOverride)) { 414 | hasNav = false; 415 | } else if ("0".equals(sNavBarOverride)) { 416 | hasNav = true; 417 | } 418 | return hasNav; 419 | } else { // fallback 420 | return !ViewConfiguration.get(context).hasPermanentMenuKey(); 421 | } 422 | } 423 | 424 | private int getInternalDimensionSize(Resources res, String key) { 425 | int result = 0; 426 | int resourceId = res.getIdentifier(key, "dimen", "android"); 427 | if (resourceId > 0) { 428 | result = res.getDimensionPixelSize(resourceId); 429 | } 430 | return result; 431 | } 432 | 433 | @SuppressLint("NewApi") 434 | private float getSmallestWidthDp(Activity activity) { 435 | DisplayMetrics metrics = new DisplayMetrics(); 436 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 437 | activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics); 438 | } else { 439 | // TODO this is not correct, but we don't really care pre-kitkat 440 | activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); 441 | } 442 | float widthDp = metrics.widthPixels / metrics.density; 443 | float heightDp = metrics.heightPixels / metrics.density; 444 | return Math.min(widthDp, heightDp); 445 | } 446 | 447 | /** 448 | * Should a navigation bar appear at the bottom of the screen in the current 449 | * device configuration? A navigation bar may appear on the right side of 450 | * the screen in certain configurations. 451 | * 452 | * @return True if navigation should appear at the bottom of the screen, False otherwise. 453 | */ 454 | public boolean isNavigationAtBottom() { 455 | return (mSmallestWidthDp >= 600 || mInPortrait); 456 | } 457 | 458 | /** 459 | * Get the height of the system status bar. 460 | * 461 | * @return The height of the status bar (in pixels). 462 | */ 463 | public int getStatusBarHeight() { 464 | return mStatusBarHeight; 465 | } 466 | 467 | /** 468 | * Get the height of the action bar. 469 | * 470 | * @return The height of the action bar (in pixels). 471 | */ 472 | public int getActionBarHeight() { 473 | return mActionBarHeight; 474 | } 475 | 476 | /** 477 | * Does this device have a system navigation bar? 478 | * 479 | * @return True if this device uses soft key navigation, False otherwise. 480 | */ 481 | public boolean hasNavigtionBar() { 482 | return mHasNavigationBar; 483 | } 484 | 485 | /** 486 | * Get the height of the system navigation bar. 487 | * 488 | * @return The height of the navigation bar (in pixels). If the device does not have 489 | * soft navigation keys, this will always return 0. 490 | */ 491 | public int getNavigationBarHeight() { 492 | return mNavigationBarHeight; 493 | } 494 | 495 | /** 496 | * Get the width of the system navigation bar when it is placed vertically on the screen. 497 | * 498 | * @return The width of the navigation bar (in pixels). If the device does not have 499 | * soft navigation keys, this will always return 0. 500 | */ 501 | public int getNavigationBarWidth() { 502 | return mNavigationBarWidth; 503 | } 504 | 505 | /** 506 | * Get the layout inset for any system UI that appears at the top of the screen. 507 | * 508 | * @param withActionBar True to include the height of the action bar, False otherwise. 509 | * @return The layout inset (in pixels). 510 | */ 511 | public int getPixelInsetTop(boolean withActionBar) { 512 | return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0); 513 | } 514 | 515 | /** 516 | * Get the layout inset for any system UI that appears at the bottom of the screen. 517 | * 518 | * @return The layout inset (in pixels). 519 | */ 520 | public int getPixelInsetBottom() { 521 | if (mTranslucentNavBar && isNavigationAtBottom()) { 522 | return mNavigationBarHeight; 523 | } else { 524 | return 0; 525 | } 526 | } 527 | 528 | /** 529 | * Get the layout inset for any system UI that appears at the right of the screen. 530 | * 531 | * @return The layout inset (in pixels). 532 | */ 533 | public int getPixelInsetRight() { 534 | if (mTranslucentNavBar && !isNavigationAtBottom()) { 535 | return mNavigationBarWidth; 536 | } else { 537 | return 0; 538 | } 539 | } 540 | 541 | } 542 | } 543 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/tools/X5NetService.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.tools; 2 | 3 | import android.app.IntentService; 4 | import android.content.Intent; 5 | import android.support.annotation.Nullable; 6 | 7 | import com.tencent.smtt.sdk.QbSdk; 8 | 9 | /** 10 | * Created by tzw on 2018/3/14. 11 | */ 12 | 13 | public class X5NetService extends IntentService { 14 | 15 | public static final String TAG = LogTAG.x5webview; 16 | public X5NetService(){ 17 | super(TAG); 18 | } 19 | public X5NetService(String name) { 20 | super(TAG); 21 | } 22 | 23 | @Override 24 | public void onHandleIntent(@Nullable Intent intent) { 25 | initX5Web(); 26 | } 27 | public void initX5Web() { 28 | if (!QbSdk.isTbsCoreInited()) { 29 | // 设置X5初始化完成的回调接口 30 | QbSdk.preInit(getApplicationContext(), null); 31 | } 32 | QbSdk.initX5Environment(getApplicationContext(), cb); 33 | } 34 | 35 | QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() { 36 | @Override 37 | public void onViewInitFinished(boolean arg0) { 38 | // TODO Auto-generated method stub 39 | } 40 | @Override 41 | public void onCoreInitFinished() { 42 | // TODO Auto-generated method stub 43 | } 44 | }; 45 | 46 | 47 | } 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.ui; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.example.administrator.sharex5webviewdemo.R; 9 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.BaseActivity; 10 | import com.example.administrator.sharex5webviewdemo.tools.HttpUrlConstance; 11 | 12 | public class MainActivity extends BaseActivity { 13 | 14 | private TextView x5, myInfo, baidu, butterKnife, interview, 15 | moreChannel, synCookie,gameSdk; 16 | @Override 17 | public int getLayoutId() { 18 | return R.layout.activity_main; 19 | } 20 | 21 | @Override 22 | public void initViews() { 23 | x5 = $(R.id.x5); 24 | baidu = $(R.id.baidu); 25 | myInfo = $(R.id.myinfo); 26 | butterKnife = $(R.id.butterknife); 27 | interview = $(R.id.interview); 28 | moreChannel = $(R.id.morechannel); 29 | synCookie = $(R.id.synCookie); 30 | gameSdk = $(R.id.gamesdk); 31 | } 32 | 33 | @Override 34 | public void initListener() { 35 | setOnClick(x5); 36 | setOnClick(baidu); 37 | setOnClick(myInfo); 38 | setOnClick(butterKnife); 39 | setOnClick(interview); 40 | setOnClick(moreChannel); 41 | setOnClick(synCookie); 42 | setOnClick(gameSdk); 43 | } 44 | 45 | @Override 46 | public void initData() { 47 | } 48 | 49 | @Override 50 | public void processClick(View v) { 51 | int id = v.getId(); 52 | switch (id) { 53 | case R.id.x5: 54 | jumpActivity(HttpUrlConstance.APP_KONWX5); 55 | break; 56 | case R.id.baidu: 57 | jumpActivity(HttpUrlConstance.BAI_DU); 58 | break; 59 | case R.id.myinfo: 60 | jumpActivity(HttpUrlConstance.APP_MYINFO); 61 | break; 62 | case R.id.butterknife: 63 | jumpActivity(HttpUrlConstance.APP_BUTTERKNIFE); 64 | break; 65 | case R.id.interview: 66 | jumpActivity(HttpUrlConstance.APP_INTERVIEW); 67 | break; 68 | case R.id.morechannel: 69 | jumpActivity(HttpUrlConstance.APP_CHANNELPACKAGE); 70 | break; 71 | case R.id.gamesdk: 72 | jumpActivity(HttpUrlConstance.APP_GAMESDK); 73 | break; 74 | case R.id.synCookie: 75 | jumpActivity(); 76 | break; 77 | } 78 | } 79 | 80 | private void jumpActivity(){ 81 | startActivity(new Intent(this,UseCookieActivity.class)); 82 | } 83 | 84 | private void jumpActivity(String tagData) { 85 | Intent intent = new Intent(this, X5WebGameActivity.class); 86 | Bundle bundle = new Bundle(); 87 | bundle.putString("key", tagData); 88 | intent.putExtras(bundle); 89 | startActivity(intent); 90 | } 91 | 92 | @Override 93 | protected void onDestroy() { 94 | super.onDestroy(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/ui/UseCookieActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.ui; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.text.TextUtils; 6 | import android.view.View; 7 | import android.widget.EditText; 8 | import android.widget.TextView; 9 | import android.widget.Toast; 10 | 11 | import com.example.administrator.sharex5webviewdemo.R; 12 | import com.example.administrator.sharex5webviewdemo.model.MVPLoginBean; 13 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.BaseActivity; 14 | import com.example.administrator.sharex5webviewdemo.mvp.mvp_use.ImpLoginPresenter; 15 | import com.example.administrator.sharex5webviewdemo.mvp.mvp_use.MVPLoginView; 16 | import com.example.administrator.sharex5webviewdemo.tools.HttpUrlConstance; 17 | import com.example.administrator.sharex5webviewdemo.tools.ProjectDataDescribe; 18 | 19 | /** 20 | * H5与客户端交互: 21 | * 22 | * 同步cookie 23 | */ 24 | public class UseCookieActivity extends BaseActivity implements MVPLoginView { 25 | 26 | private EditText username; 27 | private EditText password; 28 | private TextView login; 29 | private ImpLoginPresenter impLoginPresenter; 30 | protected boolean accountTag, passwordTag; 31 | private final String LOGIN_FORMERROR = "帐号/密码长度格式错误"; 32 | private final String LENGTH_EMPTY = "请检查帐号/密码输入"; 33 | private final int ACCOUNT_MAX_LENGTH = 12; 34 | private final int ACCOUNT_MIN_LENGTH = 4; 35 | private final int PASSWORD_MAX_LENGTH = 12; 36 | private final int PASSWORD_MIN_LENGTH = 4; 37 | 38 | @Override 39 | public int getLayoutId() { 40 | return R.layout.activity_cookie; 41 | } 42 | 43 | @Override 44 | public void initViews() { 45 | 46 | impLoginPresenter = new ImpLoginPresenter(); 47 | impLoginPresenter.attachView(this); 48 | username = $(R.id.username); 49 | password = $(R.id.password); 50 | login = $(R.id.login); 51 | 52 | } 53 | 54 | @Override 55 | public void initListener() { 56 | setOnClick(login); 57 | } 58 | 59 | @Override 60 | public void initData() { 61 | 62 | } 63 | 64 | @Override 65 | public void processClick(View v) { 66 | int id = v.getId(); 67 | switch (id) { 68 | case R.id.login: 69 | login(); 70 | break; 71 | } 72 | } 73 | 74 | private void login() { 75 | 76 | String userName = username.getText().toString().trim(); 77 | String passWord = password.getText().toString().trim(); 78 | 79 | accountTag = (userName.length() > ACCOUNT_MIN_LENGTH) && (userName.length() < ACCOUNT_MAX_LENGTH); 80 | passwordTag = (passWord.length() > PASSWORD_MIN_LENGTH) && (passWord.length() < PASSWORD_MAX_LENGTH); 81 | 82 | if ((TextUtils.isEmpty(userName)) && (TextUtils.isEmpty(passWord))) { 83 | Toast.makeText(this, LENGTH_EMPTY, Toast.LENGTH_SHORT).show(); 84 | return; 85 | } else { 86 | if (accountTag && passwordTag) { 87 | MVPLoginBean bean = new MVPLoginBean(userName, passWord); 88 | impLoginPresenter.login(bean); 89 | } else { 90 | Toast.makeText(this, LOGIN_FORMERROR, Toast.LENGTH_SHORT).show(); 91 | return; 92 | } 93 | } 94 | } 95 | 96 | @Override 97 | public void loginSuccess(String msg, String data, Object object) { 98 | Toast.makeText(this, data, Toast.LENGTH_SHORT).show(); 99 | jumpActivity( HttpUrlConstance.APP_GAME_); 100 | } 101 | 102 | @Override 103 | public void loginFailed(String msg, String data) { 104 | switch (msg) { 105 | case ProjectDataDescribe.NET_NO_LINKING: 106 | case ProjectDataDescribe.NET_ON_FAILURE: 107 | case ProjectDataDescribe.SERVER_ERROR: 108 | Toast.makeText(this, data, Toast.LENGTH_SHORT).show(); 109 | break; 110 | } 111 | } 112 | 113 | private void jumpActivity(String data){ 114 | Intent intent = new Intent(this,X5WebGameActivity.class); 115 | Bundle bundle = new Bundle(); 116 | bundle.putString("key",data); 117 | intent.putExtras(bundle); 118 | startActivity(intent); 119 | } 120 | 121 | 122 | @Override 123 | public void showInfo(String msg, String data, Object o) { 124 | Toast.makeText(this, data, Toast.LENGTH_SHORT).show(); 125 | } 126 | 127 | @Override 128 | protected void onDestroy() { 129 | super.onDestroy(); 130 | impLoginPresenter.detachView(); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/ui/X5WebGameActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.ui; 2 | 3 | import android.content.pm.ActivityInfo; 4 | import android.os.Bundle; 5 | import android.view.KeyEvent; 6 | import android.view.View; 7 | import android.view.WindowManager; 8 | import android.widget.Toast; 9 | 10 | import com.example.administrator.sharex5webviewdemo.R; 11 | import com.example.administrator.sharex5webviewdemo.mvp.mvpbase.BaseActivity; 12 | import com.example.administrator.sharex5webviewdemo.tools.LogTAG; 13 | import com.example.administrator.sharex5webviewdemo.tools.Logger; 14 | import com.example.administrator.sharex5webviewdemo.widget.MyX5WebView; 15 | 16 | 17 | public class X5WebGameActivity extends BaseActivity{ 18 | 19 | private MyX5WebView myX5WebView; 20 | private String webUrl; 21 | private long exitTime = 0; 22 | private Bundle extras; 23 | public final String TAG = LogTAG.x5webview; 24 | public static final String DATA = "确定退出当前页面吗?"; 25 | @Override 26 | public int getLayoutId() { 27 | extras = getIntent().getExtras(); 28 | webUrl = extras.getString("key"); 29 | Logger.i(TAG,"load url : "+ webUrl ); 30 | full(true); 31 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 32 | return R.layout.layout_x5; 33 | } 34 | 35 | @Override 36 | public void initViews() { 37 | myX5WebView = $(R.id.main_web); 38 | } 39 | 40 | @Override 41 | public void initListener() { 42 | 43 | } 44 | 45 | @Override 46 | public void initData() { 47 | myX5WebView.loadUrl(webUrl); 48 | } 49 | 50 | @Override 51 | public void processClick(View v) { 52 | 53 | } 54 | @Override 55 | public boolean onKeyDown(int keyCode, KeyEvent event) { 56 | if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){ 57 | if((System.currentTimeMillis()-exitTime) > 2000){ 58 | Toast.makeText(this,DATA,Toast.LENGTH_SHORT).show(); 59 | exitTime = System.currentTimeMillis(); 60 | } else { 61 | finish(); 62 | } 63 | return true; 64 | } 65 | return super.onKeyDown(keyCode, event); 66 | } 67 | 68 | private void full(boolean enable) { 69 | if (enable) { 70 | WindowManager.LayoutParams lp = getWindow().getAttributes(); 71 | lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; 72 | getWindow().setAttributes(lp); 73 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); 74 | } else { 75 | WindowManager.LayoutParams attr = getWindow().getAttributes(); 76 | attr.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); 77 | getWindow().setAttributes(attr); 78 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/administrator/sharex5webviewdemo/widget/MyX5WebView.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo.widget; 2 | 3 | import android.content.ActivityNotFoundException; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Build; 8 | import android.text.TextUtils; 9 | import android.util.AttributeSet; 10 | import android.util.Log; 11 | import android.view.KeyEvent; 12 | import android.view.MotionEvent; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.ImageView; 16 | import android.widget.ProgressBar; 17 | import android.widget.TextView; 18 | import android.widget.Toast; 19 | 20 | import com.example.administrator.sharex5webviewdemo.R; 21 | import com.example.administrator.sharex5webviewdemo.tools.LogTAG; 22 | import com.tencent.smtt.export.external.interfaces.WebResourceRequest; 23 | import com.tencent.smtt.export.external.interfaces.WebResourceResponse; 24 | import com.tencent.smtt.sdk.CookieManager; 25 | import com.tencent.smtt.sdk.CookieSyncManager; 26 | import com.tencent.smtt.sdk.DownloadListener; 27 | import com.tencent.smtt.sdk.WebChromeClient; 28 | import com.tencent.smtt.sdk.WebSettings; 29 | import com.tencent.smtt.sdk.WebView; 30 | import com.tencent.smtt.sdk.WebViewClient; 31 | 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | public class MyX5WebView extends WebView { 36 | 37 | private static final String TAG = LogTAG.x5webview; 38 | private static final int MAX_LENGTH = 8; 39 | 40 | ProgressBar progressBar; 41 | private TextView tvTitle; 42 | private ImageView imageView; 43 | private List newList; 44 | 45 | 46 | public MyX5WebView(Context context) { 47 | super(context); 48 | initUI(); 49 | } 50 | 51 | public MyX5WebView(Context context, AttributeSet attrs) { 52 | super(context, attrs); 53 | initUI(); 54 | } 55 | 56 | public MyX5WebView(Context context, AttributeSet attrs, int defStyleAttr) { 57 | super(context, attrs, defStyleAttr); 58 | initUI(); 59 | } 60 | 61 | public void setShowProgress(boolean showProgress) { 62 | if (showProgress) { 63 | progressBar.setVisibility(VISIBLE); 64 | } else { 65 | progressBar.setVisibility(GONE); 66 | } 67 | } 68 | 69 | 70 | private void initUI() { 71 | 72 | getX5WebViewExtension().setScrollBarFadingEnabled(false); 73 | setHorizontalScrollBarEnabled(false);//水平不显示小方块 74 | setVerticalScrollBarEnabled(false); //垂直不显示小方块 75 | 76 | // setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);//滚动条在WebView内侧显示 77 | // setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);//滚动条在WebView外侧显示 78 | 79 | 80 | progressBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleHorizontal); 81 | progressBar.setMax(100); 82 | progressBar.setProgressDrawable(this.getResources().getDrawable(R.drawable.color_progressbar)); 83 | 84 | addView(progressBar, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 6)); 85 | imageView = new ImageView(getContext()); 86 | imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 87 | // 加载图 根据自己的需求去集成使用 88 | imageView.setImageResource(R.mipmap.splash); 89 | imageView.setVisibility(VISIBLE); 90 | addView(imageView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 91 | 92 | initWebViewSettings(); 93 | } 94 | 95 | // 基本的WebViewSetting 96 | public void initWebViewSettings() { 97 | setBackgroundColor(getResources().getColor(android.R.color.white)); 98 | setWebViewClient(client); 99 | setWebChromeClient(chromeClient); 100 | setDownloadListener(downloadListener); 101 | setClickable(true); 102 | setOnTouchListener(new OnTouchListener() { 103 | @Override 104 | public boolean onTouch(View v, MotionEvent event) { 105 | return false; 106 | } 107 | }); 108 | WebSettings webSetting = getSettings(); 109 | webSetting.setJavaScriptEnabled(true); 110 | webSetting.setBuiltInZoomControls(true); 111 | webSetting.setJavaScriptCanOpenWindowsAutomatically(true); 112 | webSetting.setDomStorageEnabled(true); 113 | webSetting.setAllowFileAccess(true); 114 | webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS); 115 | webSetting.setSupportZoom(true); 116 | webSetting.setUseWideViewPort(true); 117 | webSetting.setSupportMultipleWindows(true); 118 | webSetting.setAppCacheEnabled(true); 119 | webSetting.setGeolocationEnabled(true); 120 | webSetting.setAppCacheMaxSize(Long.MAX_VALUE); 121 | webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND); 122 | webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH); 123 | //android 默认是可以打开_bank的,是因为它默认设置了WebSettings.setSupportMultipleWindows(false) 124 | //在false状态下,_bank也会在当前页面打开…… 125 | //而x5浏览器,默认开启了WebSettings.setSupportMultipleWindows(true), 126 | // 所以打不开……主动设置成false就可以打开了 127 | //需要支持多窗体还需要重写WebChromeClient.onCreateWindow 128 | webSetting.setSupportMultipleWindows(false); 129 | // webSetting.setCacheMode(WebSettings.LOAD_NORMAL); 130 | // getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension 131 | 132 | } 133 | 134 | @Override 135 | public boolean onKeyDown(int keyCode, KeyEvent event) { 136 | if ((keyCode == KeyEvent.KEYCODE_BACK) && this.canGoBack()) { 137 | this.goBack(); // goBack()表示返回WebView的上一页面 138 | return true; 139 | } 140 | return super.onKeyDown(keyCode, event); 141 | } 142 | 143 | private WebChromeClient chromeClient = new WebChromeClient() { 144 | @Override 145 | public void onReceivedTitle(WebView view, String title) { 146 | if (tvTitle == null || TextUtils.isEmpty(title)) { 147 | return; 148 | } 149 | if (title != null && title.length() > MAX_LENGTH) { 150 | tvTitle.setText(title.subSequence(0, MAX_LENGTH) + "..."); 151 | } else { 152 | tvTitle.setText(title); 153 | } 154 | } 155 | 156 | //监听进度 157 | @Override 158 | public void onProgressChanged(WebView view, int newProgress) { 159 | progressBar.setProgress(newProgress); 160 | if (progressBar != null && newProgress != 100) { 161 | 162 | //Webview加载没有完成 就显示我们自定义的加载图 163 | progressBar.setVisibility(VISIBLE); 164 | 165 | } else if (progressBar != null) { 166 | 167 | //Webview加载完成 就隐藏进度条,显示Webview 168 | progressBar.setVisibility(GONE); 169 | imageView.setVisibility(GONE); 170 | } 171 | } 172 | }; 173 | 174 | private WebViewClient client = new WebViewClient() { 175 | 176 | //当页面加载完成的时候 177 | @Override 178 | public void onPageFinished(WebView webView, String url) { 179 | CookieManager cookieManager = CookieManager.getInstance(); 180 | cookieManager.setAcceptCookie(true); 181 | String endCookie = cookieManager.getCookie(url); 182 | Log.i(TAG, "onPageFinished: endCookie : " + endCookie); 183 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 184 | CookieSyncManager.getInstance().sync();//同步cookie 185 | } else { 186 | CookieManager.getInstance().flush(); 187 | } 188 | super.onPageFinished(webView, url); 189 | } 190 | 191 | @Override 192 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 193 | //返回值是true的时候控制去WebView打开, 194 | // 为false调用系统浏览器或第三方浏览器 195 | if (url.startsWith("http") || url.startsWith("https") || url.startsWith("ftp")) { 196 | return false; 197 | } else { 198 | try { 199 | Intent intent = new Intent(); 200 | intent.setAction(Intent.ACTION_VIEW); 201 | intent.setData(Uri.parse(url)); 202 | view.getContext().startActivity(intent); 203 | } catch (ActivityNotFoundException e) { 204 | Toast.makeText(view.getContext(), "手机还没有安装支持打开此网页的应用!", Toast.LENGTH_SHORT).show(); 205 | } 206 | return true; 207 | } 208 | } 209 | 210 | @Override 211 | public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { 212 | return super.shouldInterceptRequest(view, request); 213 | } 214 | 215 | @Override 216 | public void onLoadResource(WebView webView, String s) { 217 | super.onLoadResource(webView, s); 218 | String reUrl = webView.getUrl() + ""; 219 | // Log.i(TAG, "onLoadResource: onLoadResource : " + reUrl); 220 | List urlList = new ArrayList<>(); 221 | urlList.add(reUrl); 222 | newList = new ArrayList(); 223 | for (String cd : urlList) { 224 | if (!newList.contains(cd)) { 225 | newList.add(cd); 226 | } 227 | } 228 | } 229 | 230 | 231 | }; 232 | 233 | public void syncCookie(String url, String cookie) { 234 | CookieSyncManager.createInstance(getContext()); 235 | if (!TextUtils.isEmpty(url)) { 236 | CookieManager cookieManager = CookieManager.getInstance(); 237 | cookieManager.setAcceptCookie(true); 238 | cookieManager.removeSessionCookie();// 移除 239 | cookieManager.removeAllCookie(); 240 | 241 | //这里的拼接方式是伪代码 242 | String[] split = cookie.split(";"); 243 | for (String string : split) { 244 | //为url设置cookie 245 | // ajax方式下 cookie后面的分号会丢失 246 | cookieManager.setCookie(url, string); 247 | } 248 | String newCookie = cookieManager.getCookie(url); 249 | Log.i(TAG, "syncCookie: newCookie == " + newCookie); 250 | //sdk21之后CookieSyncManager被抛弃了,换成了CookieManager来进行管理。 251 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 252 | CookieSyncManager.getInstance().sync();//同步cookie 253 | } else { 254 | CookieManager.getInstance().flush(); 255 | } 256 | } else { 257 | 258 | } 259 | 260 | } 261 | 262 | //删除Cookie 263 | private void removeCookie() { 264 | 265 | CookieSyncManager.createInstance(getContext()); 266 | CookieManager cookieManager = CookieManager.getInstance(); 267 | cookieManager.removeSessionCookie(); 268 | cookieManager.removeAllCookie(); 269 | if (Build.VERSION.SDK_INT < 21) { 270 | CookieSyncManager.getInstance().sync(); 271 | } else { 272 | CookieManager.getInstance().flush(); 273 | } 274 | 275 | } 276 | 277 | public String getDoMain(String url) { 278 | String domain = ""; 279 | int start = url.indexOf("."); 280 | if (start >= 0) { 281 | int end = url.indexOf("/", start); 282 | if (end < 0) { 283 | domain = url.substring(start); 284 | } else { 285 | domain = url.substring(start, end); 286 | } 287 | } 288 | return domain; 289 | } 290 | 291 | DownloadListener downloadListener = new DownloadListener() { 292 | @Override 293 | public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { 294 | Uri uri = Uri.parse(url); 295 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 296 | getContext().startActivity(intent); 297 | } 298 | }; 299 | } 300 | -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/liblbs.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/jniLibs/armeabi/liblbs.so -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/color_progressbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/gamesdk_pwd_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/drawable/gamesdk_pwd_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/gamesdk_username.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/drawable/gamesdk_username.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 14 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_login_register.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 14 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_login_register_new.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 11 | 12 | 13 | 18 | 21 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_cookie.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 16 | 17 | 26 | 27 | 28 | 29 | 34 | 35 | 43 | 44 | 49 | 58 | 59 | 72 | 76 | 77 | 78 | 79 | 80 | 87 | 88 | 97 | 98 | 112 | 117 | 118 | 119 | 120 | 121 | 133 | 134 | 135 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 24 | 25 | 26 | 30 | 31 | 35 | 36 | 40 | 44 | 45 | 49 | 53 | 57 | 58 | 62 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_x5.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/splash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-xhdpi/splash.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 80 | 81 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ShareX5WebView 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/test/java/com/example/administrator/sharex5webviewdemo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.example.administrator.sharex5webviewdemo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.0' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'http://repo1.maven.org/maven2' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | Android.useDeprecatedNdk=true; -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuowutan/ShareX5WebViewDemo/1efe087272ddcad098fa1200021cff2a49b034a4/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Mar 13 09:02:16 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------