New file |
| | |
| | | *.iml |
| | | .gradle |
| | | /local.properties |
| | | /.idea/caches |
| | | /.idea/libraries |
| | | /.idea/modules.xml |
| | | /.idea/workspace.xml |
| | | /.idea/navEditor.xml |
| | | /.idea/assetWizardSettings.xml |
| | | .DS_Store |
| | | /build |
| | | /captures |
| | | .externalNativeBuild |
New file |
| | |
| | | <component name="ProjectCodeStyleConfiguration"> |
| | | <code_scheme name="Project" version="173"> |
| | | <codeStyleSettings language="XML"> |
| | | <indentOptions> |
| | | <option name="CONTINUATION_INDENT_SIZE" value="4" /> |
| | | </indentOptions> |
| | | <arrangement> |
| | | <rules> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>xmlns:android</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>^$</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>xmlns:.*</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>^$</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | <order>BY_NAME</order> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>.*:id</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>.*:name</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>name</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>^$</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>style</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>^$</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>.*</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>^$</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | <order>BY_NAME</order> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>.*</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | <order>ANDROID_ATTRIBUTE_ORDER</order> |
| | | </rule> |
| | | </section> |
| | | <section> |
| | | <rule> |
| | | <match> |
| | | <AND> |
| | | <NAME>.*</NAME> |
| | | <XML_ATTRIBUTE /> |
| | | <XML_NAMESPACE>.*</XML_NAMESPACE> |
| | | </AND> |
| | | </match> |
| | | <order>BY_NAME</order> |
| | | </rule> |
| | | </section> |
| | | </rules> |
| | | </arrangement> |
| | | </codeStyleSettings> |
| | | </code_scheme> |
| | | </component> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="Encoding" addBOMForNewFiles="with NO BOM" /> |
| | | </project> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="GradleSettings"> |
| | | <option name="linkedExternalProjectsSettings"> |
| | | <GradleProjectSettings> |
| | | <option name="distributionType" value="DEFAULT_WRAPPED" /> |
| | | <option name="externalProjectPath" value="$PROJECT_DIR$" /> |
| | | <option name="modules"> |
| | | <set> |
| | | <option value="$PROJECT_DIR$" /> |
| | | <option value="$PROJECT_DIR$/app" /> |
| | | </set> |
| | | </option> |
| | | <option name="resolveModulePerSourceSet" value="false" /> |
| | | </GradleProjectSettings> |
| | | </option> |
| | | </component> |
| | | </project> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK"> |
| | | <output url="file://$PROJECT_DIR$/build/classes" /> |
| | | </component> |
| | | <component name="ProjectType"> |
| | | <option name="id" value="Android" /> |
| | | </component> |
| | | </project> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="RunConfigurationProducerService"> |
| | | <option name="ignoredProducers"> |
| | | <set> |
| | | <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" /> |
| | | <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" /> |
| | | <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" /> |
| | | </set> |
| | | </option> |
| | | </component> |
| | | </project> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <projectDescription> |
| | | <name>myTestApp</name> |
| | | <comment>Project myTestApp created by Buildship.</comment> |
| | | <projects> |
| | | </projects> |
| | | <buildSpec> |
| | | <buildCommand> |
| | | <name>org.eclipse.buildship.core.gradleprojectbuilder</name> |
| | | <arguments> |
| | | </arguments> |
| | | </buildCommand> |
| | | </buildSpec> |
| | | <natures> |
| | | <nature>org.eclipse.buildship.core.gradleprojectnature</nature> |
| | | </natures> |
| | | </projectDescription> |
New file |
| | |
| | | connection.project.dir= |
| | | eclipse.preferences.version=1 |
New file |
| | |
| | | apply plugin: 'com.android.application' |
| | | |
| | | android { |
| | | compileSdkVersion 28 |
| | | defaultConfig { |
| | | applicationId "com.mytestapp" |
| | | minSdkVersion 14 |
| | | targetSdkVersion 28 |
| | | versionCode 1 |
| | | versionName "1.0" |
| | | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" |
| | | |
| | | ndk{ |
| | | |
| | | } |
| | | } |
| | | |
| | | buildTypes { |
| | | release { |
| | | minifyEnabled false |
| | | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
| | | } |
| | | } |
| | | } |
| | | |
| | | dependencies { |
| | | implementation fileTree(dir: 'libs', include: ['*.jar']) |
| | | implementation 'androidx.appcompat:appcompat:1.0.2' |
| | | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' |
| | | testImplementation 'junit:junit:4.12' |
| | | androidTestImplementation 'androidx.test:runner:1.2.0' |
| | | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' |
| | | } |
New file |
| | |
| | | [{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-debug.apk","fullName":"debug","baseName":"debug"},"path":"app-debug.apk","properties":{}}] |
New file |
| | |
| | | # Add project specific ProGuard rules here. |
| | | # You can control the set of applied configuration files using the |
| | | # proguardFiles setting in build.gradle. |
| | | # |
| | | # For more details, see |
| | | # http://developer.android.com/guide/developing/tools/proguard.html |
| | | |
| | | # If your project uses WebView with JS, uncomment the following |
| | | # and specify the fully qualified class name to the JavaScript interface |
| | | # class: |
| | | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
| | | # public *; |
| | | #} |
| | | |
| | | # Uncomment this to preserve the line number information for |
| | | # debugging stack traces. |
| | | #-keepattributes SourceFile,LineNumberTable |
| | | |
| | | # If you keep the line number information, uncomment this to |
| | | # hide the original source file name. |
| | | #-renamesourcefileattribute SourceFile |
New file |
| | |
| | | [{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.content.Context; |
| | | |
| | | import androidx.test.InstrumentationRegistry; |
| | | import androidx.test.runner.AndroidJUnit4; |
| | | |
| | | import org.junit.Test; |
| | | import org.junit.runner.RunWith; |
| | | |
| | | import static org.junit.Assert.*; |
| | | |
| | | /** |
| | | * Instrumented test, which will execute on an Android device. |
| | | * |
| | | * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> |
| | | */ |
| | | @RunWith(AndroidJUnit4.class) |
| | | public class ExampleInstrumentedTest { |
| | | @Test |
| | | public void useAppContext() { |
| | | // Context of the app under test. |
| | | Context appContext = InstrumentationRegistry.getTargetContext(); |
| | | |
| | | assertEquals("com.mytestapp", appContext.getPackageName()); |
| | | } |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| | | package="com.mytestapp"> |
| | | |
| | | <!--获取Intenet访问权限--> |
| | | <uses-permission android:name="android.permission.INTERNET" /> |
| | | |
| | | <!--监听开机广播--> |
| | | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission> |
| | | |
| | | <application |
| | | android:allowBackup="true" |
| | | android:icon="@mipmap/ic_launcher" |
| | | android:label="@string/app_name" |
| | | android:roundIcon="@mipmap/ic_launcher_round" |
| | | android:supportsRtl="true" |
| | | android:theme="@style/MyTheme"> |
| | | |
| | | <activity android:name=".LoginActivity" |
| | | android:windowSoftInputMode="adjustResize|stateHidden" |
| | | android:launchMode="singleInstance" |
| | | android:theme="@style/MyTheme"> |
| | | <intent-filter> |
| | | <action android:name="android.intent.action.MAIN" /> |
| | | <category android:name="android.intent.category.LAUNCHER" /> |
| | | </intent-filter> |
| | | </activity> |
| | | <activity android:name=".MainActivity" android:theme="@style/MyTheme"> |
| | | </activity> |
| | | <receiver |
| | | android:name=".LaunchSelfReceiver" |
| | | android:enabled="true" |
| | | android:exported="true"> |
| | | <intent-filter android:priority="1000"> |
| | | <action android:name="android.intent.action.BOOT_COMPLETED"></action> |
| | | </intent-filter> |
| | | </receiver> |
| | | </application> |
| | | |
| | | </manifest> |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.app.Activity; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class ActivityCollector { |
| | | public static List<Activity> activities = new ArrayList<>(); |
| | | |
| | | public static void addActivity(Activity activity){ |
| | | activities.add(activity); |
| | | } |
| | | |
| | | public static void removeActivity(Activity activity){ |
| | | activities.remove(activity); |
| | | } |
| | | |
| | | public static void finishAll(){ |
| | | for (Activity activity:activities){ |
| | | if(!activity.isFinishing()){ |
| | | activity.finish(); |
| | | } |
| | | } |
| | | activities.clear(); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.content.Intent; |
| | | import android.os.Build; |
| | | import android.os.Bundle; |
| | | import android.os.CountDownTimer; |
| | | import android.util.Log; |
| | | import android.view.MotionEvent; |
| | | import android.view.View; |
| | | import android.view.WindowManager; |
| | | |
| | | /** |
| | | */import androidx.appcompat.app.AppCompatActivity; |
| | | |
| | | |
| | | /** |
| | | * Author: |
| | | * Date: 2017/8/10 |
| | | * Description: 用户实现手机屏保功能 |
| | | */ |
| | | |
| | | public abstract class BaseActivity extends AppCompatActivity { |
| | | |
| | | public CountDownTimer countDownTimer; |
| | | private long advertisingTime = 5 * 60 * 1000;//定时跳转广告时间 |
| | | |
| | | @Override |
| | | protected void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | //设置屏幕长亮 |
| | | /*getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, |
| | | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);*/ |
| | | setContentView(getLayoutRes()); |
| | | ActivityCollector.addActivity(this); |
| | | |
| | | goneSystemUi(); //屏蔽底部系统虚拟按键 |
| | | |
| | | getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { |
| | | @Override |
| | | public void onSystemUiVisibilityChange(int visibility) { |
| | | Log.e("", "onSystemUiVisibilityChange:OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO " ); |
| | | int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | |
| | | //布局位于状态栏下方 |
| | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | |
| | | //全屏 |
| | | View.SYSTEM_UI_FLAG_FULLSCREEN | |
| | | //隐藏导航栏 |
| | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | |
| | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; |
| | | if (Build.VERSION.SDK_INT >= 19) { |
| | | uiOptions |= 0x00001000; |
| | | } else { |
| | | uiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE; |
| | | } |
| | | getWindow().getDecorView().setSystemUiVisibility(uiOptions); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | protected abstract int getLayoutRes(); |
| | | |
| | | @Override |
| | | public boolean dispatchTouchEvent(MotionEvent ev) { |
| | | switch (ev.getAction()) { |
| | | case MotionEvent.ACTION_DOWN: |
| | | //有按下动作时取消定时 |
| | | if (countDownTimer != null){ |
| | | countDownTimer.cancel(); |
| | | } |
| | | break; |
| | | case MotionEvent.ACTION_UP: |
| | | //抬起时启动定时 |
| | | startAD(); |
| | | break; |
| | | } |
| | | return super.dispatchTouchEvent(ev); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | public void startAD() { |
| | | if (countDownTimer == null) { |
| | | countDownTimer = new CountDownTimer(advertisingTime, 1000l) { |
| | | @Override |
| | | public void onTick(long millisUntilFinished) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void onFinish() { |
| | | |
| | | } |
| | | }; |
| | | countDownTimer.start(); |
| | | } else { |
| | | countDownTimer.start(); |
| | | } |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected void onResume() { |
| | | super.onResume(); |
| | | //显示是启动定时 |
| | | startAD(); |
| | | } |
| | | |
| | | @Override |
| | | protected void onPause() { |
| | | super.onPause(); |
| | | //当activity不在前台是停止定时 |
| | | if (countDownTimer != null){ |
| | | countDownTimer.cancel(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | | super.onDestroy(); |
| | | //销毁时停止定时 |
| | | if (countDownTimer != null){ |
| | | countDownTimer.cancel(); |
| | | } |
| | | |
| | | ActivityCollector.removeActivity(this); |
| | | } |
| | | |
| | | @Override |
| | | public void finish() { |
| | | super.finish(); |
| | | } |
| | | |
| | | public void finishAll(){ |
| | | ActivityCollector.finishAll(); |
| | | } |
| | | |
| | | private void fullscreen(boolean enable) { |
| | | |
| | | if (enable) { //显示状态栏 |
| | | |
| | | WindowManager.LayoutParams lp = getWindow().getAttributes(); |
| | | |
| | | lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; |
| | | |
| | | getWindow().setAttributes(lp); |
| | | |
| | | getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); |
| | | |
| | | } else { //隐藏状态栏 |
| | | |
| | | WindowManager.LayoutParams lp = getWindow().getAttributes(); |
| | | |
| | | lp.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); |
| | | |
| | | getWindow().setAttributes(lp); |
| | | |
| | | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 隐藏虚拟按键 |
| | | */ |
| | | public void goneSystemUi(){ |
| | | //隐藏虚拟按键 |
| | | if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { |
| | | View v = getWindow().getDecorView(); |
| | | v.setSystemUiVisibility(View.GONE); |
| | | } else if (Build.VERSION.SDK_INT >= 19) { |
| | | View decorView = getWindow().getDecorView(); |
| | | int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
| | | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
| | | | View.SYSTEM_UI_FLAG_FULLSCREEN; |
| | | decorView.setSystemUiVisibility(uiOptions); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 显示虚拟按键 |
| | | */ |
| | | public void visibleSystemUi(){ |
| | | //显示虚拟键盘 |
| | | if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { |
| | | //低版本sdk |
| | | View v = getWindow().getDecorView(); |
| | | v.setSystemUiVisibility(View.VISIBLE); |
| | | } else if (Build.VERSION.SDK_INT >= 19) { |
| | | View decorView = getWindow().getDecorView(); |
| | | int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; |
| | | decorView.setSystemUiVisibility(uiOptions); |
| | | } |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.app.AlarmManager; |
| | | import android.app.PendingIntent; |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | import android.content.pm.PackageInfo; |
| | | import android.content.pm.PackageManager; |
| | | import android.os.Build; |
| | | import android.os.Environment; |
| | | import android.os.Looper; |
| | | import android.util.Log; |
| | | import android.widget.Toast; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileOutputStream; |
| | | import java.io.PrintWriter; |
| | | import java.io.StringWriter; |
| | | import java.io.Writer; |
| | | import java.lang.reflect.Field; |
| | | import java.text.DateFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | public class CrashHandler implements Thread.UncaughtExceptionHandler { |
| | | |
| | | public static final String TAG = "CrashHandler"; |
| | | // 系统默认的UncaughtException处理类 |
| | | private Thread.UncaughtExceptionHandler mDefaultHandler; |
| | | // CrashHandler实例 |
| | | private static CrashHandler INSTANCE = new CrashHandler(); |
| | | // 程序的Context对象 |
| | | private Context mContext; |
| | | // 用来存储设备信息和异常信息 |
| | | private Map<String, String> infos = new HashMap<String, String>(); |
| | | |
| | | // 用于格式化日期,作为日志文件名的一部分 |
| | | private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS"); |
| | | |
| | | private CrashHandler() { |
| | | } |
| | | |
| | | /** |
| | | * 获取CrashHandler实例 ,单例模式 |
| | | */ |
| | | public static CrashHandler getInstance() { |
| | | return INSTANCE; |
| | | } |
| | | |
| | | /** |
| | | * 初始化 |
| | | * |
| | | * @param context |
| | | */ |
| | | public void init(Context context) { |
| | | mContext = context; |
| | | // 获取系统默认的UncaughtException处理器 |
| | | mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); |
| | | // 设置该CrashHandler为程序的默认处理器 |
| | | Thread.setDefaultUncaughtExceptionHandler(this); |
| | | } |
| | | |
| | | /** |
| | | * 当UncaughtException发生时会转入该函数来处理 |
| | | */ |
| | | @Override |
| | | public void uncaughtException(Thread thread, Throwable ex) { |
| | | if (!handleException(ex) && mDefaultHandler != null) { |
| | | // 如果用户没有处理则让系统默认的异常处理器来处理 |
| | | mDefaultHandler.uncaughtException(thread, ex); |
| | | } else { |
| | | try { |
| | | Thread.sleep(3000); |
| | | } catch (InterruptedException e) { |
| | | Log.e(TAG, "error : ", e); |
| | | } |
| | | Log.e(TAG, "uncaughtException: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" ); |
| | | |
| | | Intent intent = new Intent(mContext, MainActivity.class); |
| | | PendingIntent restartIntent = PendingIntent.getActivity( |
| | | mContext, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK); |
| | | //退出程序 |
| | | AlarmManager mgr = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); |
| | | mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, |
| | | restartIntent); // 1秒钟后重启应用 |
| | | System.exit(1); |
| | | ActivityCollector.finishAll(); |
| | | |
| | | |
| | | // ARouter.getInstance().build("/module_login/SplashActivity").navigation(); |
| | | |
| | | // Intent intent = new Intent(this.mContext, LoginActivity.class); |
| | | // PendingIntent restartIntent = PendingIntent.getActivity( |
| | | // this.mContext, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK); |
| | | // //退出程序 |
| | | // AlarmManager mgr = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); |
| | | // // 退出程序 |
| | | // android.os.Process.killProcess(android.os.Process.myPid()); |
| | | // ActivityCollector.finishAll(); |
| | | //System.exit(1); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. |
| | | * |
| | | * @param ex |
| | | * @return true:如果处理了该异常信息;否则返回false. |
| | | */ |
| | | private boolean handleException(Throwable ex) { |
| | | if (ex == null) { |
| | | return false; |
| | | } |
| | | // 使用Toast来显示异常信息 |
| | | new Thread() { |
| | | @Override |
| | | public void run() { |
| | | Looper.prepare(); |
| | | Toast.makeText(mContext, "很抱歉,程序出现异常即将退出.", Toast.LENGTH_LONG).show(); |
| | | Looper.loop(); |
| | | } |
| | | }.start(); |
| | | // 收集设备参数信息 |
| | | //collectDeviceInfo(mContext); |
| | | // 保存日志文件 |
| | | //saveCrashInfo2File(ex); |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 收集设备参数信息 |
| | | * |
| | | * @param ctx |
| | | */ |
| | | public void collectDeviceInfo(Context ctx) { |
| | | try { |
| | | PackageManager pm = ctx.getPackageManager(); |
| | | PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); |
| | | if (pi != null) { |
| | | String versionName = pi.versionName == null ? "null" : pi.versionName; |
| | | String versionCode = pi.versionCode + ""; |
| | | infos.put("versionName", versionName); |
| | | infos.put("versionCode", versionCode); |
| | | } |
| | | } catch (PackageManager.NameNotFoundException e) { |
| | | Log.e(TAG, "an error occured when collect package info", e); |
| | | } |
| | | Field[] fields = Build.class.getDeclaredFields(); |
| | | for (Field field : fields) { |
| | | try { |
| | | field.setAccessible(true); |
| | | infos.put(field.getName(), field.get(null).toString()); |
| | | Log.d(TAG, field.getName() + " : " + field.get(null)); |
| | | } catch (Exception e) { |
| | | Log.e(TAG, "an error occured when collect crash info", e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 保存错误信息到文件中 |
| | | * |
| | | * @param ex |
| | | * @return 返回文件名称, 便于将文件传送到服务器 |
| | | */ |
| | | private String saveCrashInfo2File(Throwable ex) { |
| | | |
| | | StringBuffer sb = new StringBuffer(); |
| | | for (Map.Entry<String, String> entry : infos.entrySet()) { |
| | | String key = entry.getKey(); |
| | | String value = entry.getValue(); |
| | | sb.append(key + "=" + value + "\n"); |
| | | } |
| | | |
| | | Writer writer = new StringWriter(); |
| | | PrintWriter printWriter = new PrintWriter(writer); |
| | | ex.printStackTrace(printWriter); |
| | | Throwable cause = ex.getCause(); |
| | | while (cause != null) { |
| | | cause.printStackTrace(printWriter); |
| | | cause = cause.getCause(); |
| | | } |
| | | printWriter.close(); |
| | | String result = writer.toString(); |
| | | sb.append(result); |
| | | try { |
| | | String time = formatter.format(new Date()); |
| | | String fileName = time + ".txt"; |
| | | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
| | | String path = "data/data/"; |
| | | File dir = new File(path); |
| | | if (!dir.exists()) { |
| | | dir.mkdirs(); |
| | | } |
| | | FileOutputStream fos = new FileOutputStream(path + fileName); |
| | | fos.write(sb.toString().getBytes("UTF-8")); |
| | | fos.close(); |
| | | } |
| | | return fileName; |
| | | } catch (Exception e) { |
| | | Log.e(TAG, "an error occured while writing file...", e); |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | |
| | | import android.util.Log; |
| | | |
| | | import java.util.Date; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | public class CrashMonitor { |
| | | |
| | | private final static String TAG = "CrashMonitor"; |
| | | private ScheduledExecutorService executorService = null; |
| | | private long oldpos = 0; |
| | | private int pauseNum = 0; |
| | | private OnCrashedListener onCrashedListener; |
| | | private static CrashMonitor crashMonitor; |
| | | |
| | | private CrashMonitor(){ |
| | | |
| | | } |
| | | |
| | | public static CrashMonitor createCrashMonitor(){ |
| | | if(crashMonitor == null){ |
| | | crashMonitor = new CrashMonitor(); |
| | | } |
| | | crashMonitor.executorService = null; |
| | | crashMonitor.oldpos = new Date().getTime(); |
| | | crashMonitor.pauseNum = 0; |
| | | if(crashMonitor.executorService == null){ |
| | | crashMonitor.monitorPageCrashed(1500); |
| | | } |
| | | return crashMonitor; |
| | | } |
| | | |
| | | public void destory(){ |
| | | this.executorService.shutdown(); |
| | | this.executorService = null; |
| | | onCrashedListener = null; |
| | | } |
| | | |
| | | public interface OnCrashedListener { |
| | | void onCrashed(); |
| | | } |
| | | public void setOnCrashedListener(OnCrashedListener listener) { |
| | | onCrashedListener = listener; |
| | | } |
| | | public boolean isWorking(){ |
| | | boolean res = false; |
| | | if(executorService != null){ |
| | | res = true; |
| | | } |
| | | return res; |
| | | } |
| | | public void updateTimer(long pos){ |
| | | oldpos = pos; |
| | | } |
| | | public void monitorPageCrashed(final int period){ |
| | | executorService = Executors.newScheduledThreadPool(1); |
| | | executorService.scheduleAtFixedRate( |
| | | new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | Log.e(TAG, "run: "+ (new Date().getTime() - oldpos)+"##############" + pauseNum); |
| | | if(oldpos > 0 && (new Date().getTime() - oldpos) > 1 * 60 * 1000){ |
| | | pauseNum ++; |
| | | } |
| | | if(pauseNum >= 3){ |
| | | oldpos = 0; |
| | | executorService.shutdown(); |
| | | //do something |
| | | if(onCrashedListener != null){ |
| | | onCrashedListener.onCrashed(); |
| | | } |
| | | return; |
| | | } |
| | | } |
| | | },0,period, TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.webkit.JavascriptInterface; |
| | | |
| | | public interface HeartJavaScriptFunction { |
| | | @JavascriptInterface |
| | | void onJsFunctionCalled(int tag); |
| | | |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.content.BroadcastReceiver; |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | |
| | | //开机自启动 |
| | | public class LaunchSelfReceiver extends BroadcastReceiver |
| | | { |
| | | public LaunchSelfReceiver() |
| | | { |
| | | } |
| | | |
| | | @Override |
| | | public void onReceive(Context context, Intent intent) |
| | | { |
| | | if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) |
| | | { |
| | | Intent i = new Intent(context, LoginActivity.class); |
| | | i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| | | context.startActivity(i); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import androidx.appcompat.app.AppCompatActivity; |
| | | |
| | | import android.app.AlertDialog; |
| | | import android.app.Dialog; |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | import android.os.Bundle; |
| | | import android.os.Handler; |
| | | import android.os.Message; |
| | | import android.text.InputType; |
| | | import android.util.Log; |
| | | import android.view.MotionEvent; |
| | | import android.view.View; |
| | | import android.view.WindowManager; |
| | | import android.view.inputmethod.EditorInfo; |
| | | import android.view.inputmethod.InputMethodManager; |
| | | import android.widget.Button; |
| | | import android.widget.EditText; |
| | | import android.widget.TextView; |
| | | import android.widget.Toast; |
| | | |
| | | import java.lang.reflect.InvocationTargetException; |
| | | import java.lang.reflect.Method; |
| | | import java.net.HttpURLConnection; |
| | | import java.net.URL; |
| | | import java.net.URLConnection; |
| | | |
| | | public class LoginActivity extends BaseActivity implements View.OnClickListener{ |
| | | private static final String TAG = "LoginActivity"; |
| | | |
| | | private Button loginBtn; |
| | | private Button testBtn; |
| | | |
| | | private EditText et_server_ip; |
| | | private EditText et_server_port; |
| | | |
| | | private boolean isSuccessConn = false; |
| | | |
| | | private Dialog progressDialog; |
| | | |
| | | private Softkeyboardlistener softkeyboardlistener; |
| | | |
| | | @Override |
| | | protected void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); |
| | | MyUtil.hideNavigationBar(getWindow()); |
| | | setContentView(R.layout.activity_login); |
| | | |
| | | MyUtil.hideNavigationBar(getWindow()); |
| | | |
| | | loginBtn = (Button)findViewById(R.id.btn_loginSys); |
| | | testBtn = (Button)findViewById(R.id.btn_testConn); |
| | | |
| | | et_server_ip = (EditText)findViewById(R.id.et_server_ip); |
| | | et_server_port = (EditText)findViewById(R.id.et_server_port); |
| | | |
| | | loginBtn.setOnClickListener(this); |
| | | testBtn.setOnClickListener(this); |
| | | |
| | | final ServerInfo info = ServerInfo.readServerInfo(LoginActivity.this); |
| | | if(info != null){ |
| | | et_server_ip.setText(info.getServer_ip()); |
| | | et_server_port.setText(info.getServer_port()+""); |
| | | // Android 4.0 之后不能在主线程中请求HTTP请求 |
| | | new Thread(new Runnable(){ |
| | | @Override |
| | | public void run() { |
| | | boolean flag = testUrlWithTimeOut(info.createServerUrl(),2000); |
| | | //判断是否已经是设置过了参数 |
| | | if(flag){ |
| | | Intent intent = new Intent(LoginActivity.this,MainActivity.class); |
| | | startActivity(intent); |
| | | } |
| | | //Log.e(TAG, "onCreate:$$$$$$$$$$$$$$$$ "+flag ); |
| | | } |
| | | }).start(); |
| | | |
| | | }else{ |
| | | et_server_ip.setText(""); |
| | | et_server_port.setText(""); |
| | | } |
| | | |
| | | Softkeyboardlistener.setListener(LoginActivity.this, new Softkeyboardlistener.OnSoftKeyBoardChangeListener() { |
| | | @Override |
| | | public void keyBoardShow(int height) { |
| | | //键盘显示 |
| | | Log.e(TAG, "keyBoardHide: 键盘显示" ); |
| | | //hideSoftInputMethod(et_server_ip); |
| | | } |
| | | |
| | | @Override |
| | | public void keyBoardHide(int height) { |
| | | Log.e(TAG, "keyBoardHide: 键盘隐藏" ); |
| | | } |
| | | }); |
| | | |
| | | |
| | | } |
| | | |
| | | @Override |
| | | protected int getLayoutRes() { |
| | | return R.layout.activity_login; |
| | | } |
| | | |
| | | Handler handler = new Handler(){ |
| | | @Override |
| | | public void handleMessage(Message msg){ |
| | | if(msg.what == 84){ |
| | | Toast.makeText(LoginActivity.this,"测试连接成功,可以登陆系统",Toast.LENGTH_SHORT).show(); |
| | | ServerInfo serverInfo = createServerInfo(); |
| | | ServerInfo.WriteServerInfo(LoginActivity.this,serverInfo); |
| | | isSuccessConn = true; |
| | | }else if(msg.what == 85){ |
| | | isSuccessConn = false; |
| | | Toast.makeText(LoginActivity.this,"测试连接失败,请检查服务器信息",Toast.LENGTH_SHORT).show(); |
| | | } |
| | | MyLoadingDialog.stopLoading(); |
| | | } |
| | | }; |
| | | |
| | | |
| | | @Override |
| | | public void onClick(View v) { |
| | | switch (v.getId()){ |
| | | case R.id.btn_loginSys:{ |
| | | if(isSuccessConn){ |
| | | //点击登陆系统 |
| | | Intent intent = new Intent(LoginActivity.this,MainActivity.class); |
| | | startActivity(intent); |
| | | |
| | | //MyUtil.showKeyboard(et_server_ip); |
| | | }else{ |
| | | Toast.makeText(LoginActivity.this,"请先测试连接接成功,方可进入系统!",Toast.LENGTH_SHORT).show(); |
| | | } |
| | | }break; |
| | | case R.id.btn_testConn:{ |
| | | String server_ip = et_server_ip.getText().toString(); |
| | | String server_port = et_server_port.getText().toString(); |
| | | if(server_ip.length() == 0){ |
| | | Toast.makeText(LoginActivity.this,"请输入服务器IP地址!",Toast.LENGTH_SHORT).show(); |
| | | }else if(server_port.length() == 0){ |
| | | Toast.makeText(LoginActivity.this,"请输入服务器端口号!",Toast.LENGTH_SHORT).show(); |
| | | }else{ |
| | | |
| | | MyLoadingDialog.showLoading(LoginActivity.this,"正在测试连接"); |
| | | // progressDialog = new Dialog(LoginActivity.this,R.style.progress_dialog); |
| | | // |
| | | // progressDialog.setContentView(R.layout.dialog); |
| | | // progressDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); |
| | | // TextView msg = (TextView) progressDialog.findViewById(R.id.id_tv_loadingmsg); |
| | | // progressDialog.setCancelable(false); |
| | | // msg.setText("正在测试连接....."); |
| | | // |
| | | // |
| | | // progressDialog.show(); |
| | | //点击测试连接 |
| | | // Android 4.0 之后不能在主线程中请求HTTP请求 |
| | | new Thread(new Runnable(){ |
| | | @Override |
| | | public void run() { |
| | | ServerInfo serverInfo = createServerInfo(); |
| | | boolean flag = testUrlWithTimeOut(serverInfo.createServerUrl(),2000); |
| | | Message msg = Message.obtain(); |
| | | if(flag){ |
| | | msg.what = 84; |
| | | }else{ |
| | | msg.what = 85; |
| | | } |
| | | handler.sendMessage(msg); |
| | | } |
| | | }).start(); |
| | | } |
| | | |
| | | }break; |
| | | } |
| | | } |
| | | |
| | | public ServerInfo createServerInfo(){ |
| | | ServerInfo serverInfo = new ServerInfo(); |
| | | serverInfo.setServer_ip(et_server_ip.getText().toString()); |
| | | serverInfo.setServer_port(Integer.parseInt(et_server_port.getText().toString())); |
| | | return serverInfo; |
| | | } |
| | | |
| | | public static boolean testUrlWithTimeOut(String urlString,int timeOutMillSeconds){ |
| | | boolean flag = false; |
| | | long lo = System.currentTimeMillis(); |
| | | URL url; |
| | | try { |
| | | url = new URL(urlString); |
| | | HttpURLConnection co = (HttpURLConnection)url.openConnection(); |
| | | co.setUseCaches(false); |
| | | co.setConnectTimeout(timeOutMillSeconds); |
| | | int status = co.getResponseCode(); |
| | | if(200 == status){ |
| | | flag = true; |
| | | Log.e(TAG, "testUrlWithTimeOut: 连接可用"+urlString); |
| | | } |
| | | } catch (Exception e1) { |
| | | Log.e(TAG, "testUrlWithTimeOut:连接打不开!" + e1); |
| | | url = null; |
| | | } |
| | | return flag; |
| | | } |
| | | |
| | | @Override |
| | | public boolean dispatchTouchEvent(MotionEvent ev) { |
| | | if (ev.getAction() == MotionEvent.ACTION_DOWN) { |
| | | View v = getCurrentFocus(); |
| | | if (isShouldHideInput(v, ev)) { |
| | | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null) { |
| | | assert v != null; |
| | | imm.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
| | | v.setClickable(true); |
| | | v.setFocusable(true); |
| | | v.setFocusableInTouchMode(true); |
| | | v.requestFocusFromTouch(); |
| | | |
| | | Log.e(TAG, "dispatchTouchEvent: 111111111111111111" ); |
| | | } |
| | | } |
| | | Log.e(TAG, "dispatchTouchEvent: 22222222222222222222222" ); |
| | | return super.dispatchTouchEvent(ev); |
| | | } |
| | | Log.e(TAG, "dispatchTouchEvent: 333333333333333333333" ); |
| | | // 必不可少,否则所有的组件都不会有TouchEvent了 |
| | | return getWindow().superDispatchTouchEvent(ev) || onTouchEvent(ev); |
| | | } |
| | | |
| | | public boolean isShouldHideInput(View v, MotionEvent event) { |
| | | if (v != null && (v instanceof EditText)) { |
| | | int[] leftTop = {0, 0}; |
| | | //获取输入框当前的location位置 |
| | | v.getLocationInWindow(leftTop); |
| | | int left = leftTop[0]; |
| | | int top = leftTop[1]; |
| | | int bottom = top + v.getHeight(); |
| | | int right = left + v.getWidth(); |
| | | return !(event.getX() > left && event.getX() < right |
| | | && event.getY() > top && event.getY() < bottom); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | //监听系统ui变化 |
| | | @Override |
| | | public void onWindowFocusChanged(boolean hasFocus) { |
| | | |
| | | //Log.e(TAG, "onWindowFocusChanged: XXXXXXXXXXXXXXXXXXXXXXXXx" ); |
| | | super.onWindowFocusChanged(hasFocus); |
| | | |
| | | int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | |
| | | //布局位于状态栏下方 |
| | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | |
| | | //全屏 |
| | | View.SYSTEM_UI_FLAG_FULLSCREEN | |
| | | //隐藏导航栏 |
| | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | |
| | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; |
| | | uiOptions |= 0x00001000; |
| | | getWindow().getDecorView().setSystemUiVisibility(uiOptions); |
| | | } |
| | | |
| | | |
| | | public void hideSystemMenu(){ |
| | | int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | |
| | | //布局位于状态栏下方 |
| | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | |
| | | //全屏 |
| | | View.SYSTEM_UI_FLAG_FULLSCREEN | |
| | | //隐藏导航栏 |
| | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | |
| | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; |
| | | uiOptions |= 0x00001000; |
| | | getWindow().getDecorView().setSystemUiVisibility(uiOptions); |
| | | } |
| | | |
| | | /** |
| | | * 禁掉系统软键盘 |
| | | */ |
| | | public void hideSoftInputMethod(EditText mEdit) { |
| | | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); |
| | | int currentVersion = android.os.Build.VERSION.SDK_INT; |
| | | String methodName = null; |
| | | if (currentVersion >= 16) { |
| | | // 4.2 |
| | | methodName = "setShowSoftInputOnFocus"; |
| | | } else if (currentVersion >= 14) { |
| | | // 4.0 |
| | | methodName = "setSoftInputShownOnFocus"; |
| | | } |
| | | if (methodName == null) { |
| | | mEdit.setInputType(InputType.TYPE_NULL); |
| | | } else { |
| | | Class<EditText> cls = EditText.class; |
| | | Method setShowSoftInputOnFocus; |
| | | try { |
| | | setShowSoftInputOnFocus = cls.getMethod(methodName, boolean.class); |
| | | setShowSoftInputOnFocus.setAccessible(true); |
| | | setShowSoftInputOnFocus.invoke(mEdit, false); |
| | | } catch (NoSuchMethodException e) { |
| | | mEdit.setInputType(InputType.TYPE_NULL); |
| | | e.printStackTrace(); |
| | | } catch (IllegalAccessException e) { |
| | | e.printStackTrace(); |
| | | } catch (IllegalArgumentException e) { |
| | | e.printStackTrace(); |
| | | } catch (InvocationTargetException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onStart() { |
| | | super.onStart(); |
| | | Log.e(TAG, "onStart: &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" ); |
| | | |
| | | ServerInfo temp = ServerInfo.readServerInfo(LoginActivity.this); |
| | | if(temp != null){ |
| | | et_server_ip.setText(temp.getServer_ip()); |
| | | et_server_port.setText(temp.getServer_port()+""); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import androidx.appcompat.app.AppCompatActivity; |
| | | |
| | | import android.app.Activity; |
| | | import android.content.Intent; |
| | | import android.os.Bundle; |
| | | import android.util.Log; |
| | | import android.view.KeyEvent; |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | import android.webkit.JavascriptInterface; |
| | | import android.webkit.JsResult; |
| | | import android.webkit.WebChromeClient; |
| | | import android.webkit.WebSettings; |
| | | import android.webkit.WebView; |
| | | import android.webkit.WebViewClient; |
| | | import android.widget.Toast; |
| | | import android.widget.ZoomButtonsController; |
| | | import java.lang.reflect.Field; |
| | | import java.util.Date; |
| | | |
| | | public class MainActivity extends BaseActivity { |
| | | private static final String TAG = "MainActivity"; |
| | | private WebView webView; |
| | | private CrashMonitor crashMonitor = null; |
| | | |
| | | |
| | | @Override |
| | | public void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | setContentView(R.layout.activity_main); |
| | | |
| | | final ServerInfo serverInfo = ServerInfo.readServerInfo(MainActivity.this); |
| | | if(serverInfo == null){ |
| | | |
| | | } |
| | | webView = (WebView) findViewById(R.id.mywebview); |
| | | webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); |
| | | WebSettings webSettings = webView.getSettings(); |
| | | webSettings.setJavaScriptEnabled(true); |
| | | webSettings.setBuiltInZoomControls(true); |
| | | webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); //不适用缓存 |
| | | webView.clearCache(true); |
| | | |
| | | webView.setBackgroundColor(android.R.color.transparent); |
| | | webView.setBackgroundResource(R.drawable.first_bg); |
| | | |
| | | webView.loadUrl(serverInfo.createServerUrl()); |
| | | webSettings.setDisplayZoomControls(false); |
| | | setZoomControlGone(webView); |
| | | webView.setWebViewClient(new MyWebViewClient()); |
| | | |
| | | webView.setWebChromeClient(new WebChromeClient(){ |
| | | @Override |
| | | public boolean onJsAlert(WebView view, String url, String message, JsResult result) { |
| | | Toast.makeText(MainActivity.this,message,Toast.LENGTH_SHORT).show(); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void onProgressChanged(WebView view, int newProgress) { |
| | | super.onProgressChanged(view, newProgress); |
| | | |
| | | if(newProgress == 100 ){ |
| | | //加载完成 |
| | | //Toast.makeText(MainActivity.this,"加载完成",Toast.LENGTH_SHORT).show(); |
| | | }else{ |
| | | //加载中 |
| | | } |
| | | } |
| | | }); |
| | | |
| | | CrashHandler crashHandler = CrashHandler.getInstance(); |
| | | crashHandler.init(MainActivity.this); |
| | | |
| | | |
| | | crashMonitor = CrashMonitor.createCrashMonitor(); |
| | | webView.addJavascriptInterface(new HeartJavaScriptFunction() { |
| | | |
| | | @JavascriptInterface |
| | | public void onJsFunctionCalled(int tag) { |
| | | if(crashMonitor != null){ |
| | | if(2000 == tag){ |
| | | crashMonitor.updateTimer(new Date().getTime()); |
| | | } |
| | | //Log.e(TAG, "onJsFunctionCalled : "+tag ); |
| | | if(!crashMonitor.isWorking()){ |
| | | //Log.e(TAG, "onJsFunctionCalled: isWorking ................" ); |
| | | crashMonitor.monitorPageCrashed(tag); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @JavascriptInterface |
| | | public void saveServerInfo(String server_ip,int server_port){ |
| | | ServerInfo serverInfo1 = new ServerInfo(); |
| | | serverInfo1.setServer_ip(server_ip); |
| | | serverInfo1.setServer_port(server_port); |
| | | ServerInfo.WriteServerInfo(MainActivity.this,serverInfo1); |
| | | } |
| | | |
| | | @JavascriptInterface |
| | | public void reStartSystem(){ |
| | | //Intent intent = new Intent(MainActivity.this,LoginActivity.class); |
| | | //startActivity(intent); |
| | | // 找到这个 webview |
| | | crashMonitor.destory(); |
| | | crashMonitor = null; |
| | | // 加载一个空的url 或者content即可。 |
| | | |
| | | runOnUiThread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | if (webView != null) { |
| | | webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null); |
| | | webView.clearHistory(); |
| | | |
| | | ((ViewGroup) webView.getParent()).removeView(webView); |
| | | webView.destroy(); |
| | | webView = null; |
| | | } |
| | | } |
| | | }); |
| | | MainActivity.this.finish(); |
| | | } |
| | | }, "Android"); |
| | | crashMonitor.setOnCrashedListener(new CrashMonitor.OnCrashedListener() { |
| | | |
| | | @Override |
| | | public void onCrashed() { |
| | | //Log.e(TAG, "onCrashed: 页面卡死进入登陆页面" ); |
| | | Intent intent = new Intent(MainActivity.this,LoginActivity.class); |
| | | startActivity(intent); |
| | | } |
| | | }); |
| | | |
| | | } |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | | if (webView != null) { |
| | | webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null); |
| | | webView.clearHistory(); |
| | | |
| | | ((ViewGroup) webView.getParent()).removeView(webView); |
| | | webView.destroy(); |
| | | webView = null; |
| | | } |
| | | super.onDestroy(); |
| | | } |
| | | |
| | | protected int getLayoutRes() { |
| | | return R.layout.activity_main; |
| | | } |
| | | |
| | | /** |
| | | * 为了能够响应链接继续在本webview控件中显示,要声明此类。 |
| | | * 如果没有这个类,点击了一个链接后,系统会自动选择浏览器浏览 |
| | | */ |
| | | private class MyWebViewClient extends WebViewClient { |
| | | @Override |
| | | public boolean shouldOverrideUrlLoading(WebView view, String url) { |
| | | view.loadUrl(url); |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 设置webview的后退,如果后退没有网页了,则关闭该activity |
| | | */ |
| | | public boolean onKeyDown(int keyCode, KeyEvent event) { |
| | | if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) { |
| | | webView.goBack(); |
| | | return true; |
| | | } |
| | | return super.onKeyDown(keyCode, event); |
| | | } |
| | | |
| | | /** |
| | | * 隐藏放大缩小控件 |
| | | */ |
| | | public void setZoomControlGone(View view) { |
| | | Class classType; |
| | | Field field; |
| | | try { |
| | | classType = WebView.class; |
| | | field = classType.getDeclaredField("mZoomButtonsController"); |
| | | field.setAccessible(true); |
| | | ZoomButtonsController mZoomButtonsController = new ZoomButtonsController( |
| | | view); |
| | | mZoomButtonsController.getZoomControls().setVisibility(View.GONE); |
| | | try { |
| | | field.set(view, mZoomButtonsController); |
| | | } catch (IllegalArgumentException e) { |
| | | e.printStackTrace(); |
| | | } catch (IllegalAccessException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } catch (SecurityException e) { |
| | | e.printStackTrace(); |
| | | } catch (NoSuchFieldException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.annotation.SuppressLint; |
| | | import android.app.Activity; |
| | | import android.app.Dialog; |
| | | import android.content.Context; |
| | | import android.content.DialogInterface; |
| | | import android.os.Build; |
| | | import android.os.Bundle; |
| | | import android.view.LayoutInflater; |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | import android.view.Window; |
| | | import android.view.WindowManager; |
| | | import android.widget.TextView; |
| | | import android.widget.Toast; |
| | | |
| | | import java.lang.ref.WeakReference; |
| | | |
| | | public class MyLoadingDialog extends Dialog implements DialogInterface.OnCancelListener { |
| | | |
| | | private WeakReference<Context> mContext = new WeakReference<>(null); |
| | | private volatile static MyLoadingDialog sDialog; |
| | | |
| | | private MyLoadingDialog(Context context, CharSequence message) { |
| | | super(context, R.style.progress_dialog); |
| | | |
| | | mContext = new WeakReference<>(context); |
| | | |
| | | applyCompat(); |
| | | @SuppressLint("InflateParams") |
| | | View view = LayoutInflater.from(context).inflate(R.layout.dialog, null); |
| | | TextView tvMessage = (TextView) view.findViewById(R.id.id_tv_loadingmsg); |
| | | if (message != null && message.length() > 0) { |
| | | tvMessage.setText(message); |
| | | } |
| | | ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
| | | addContentView(view, lp); |
| | | |
| | | setOnCancelListener(this); |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void onCancel(DialogInterface dialog) { |
| | | // 点手机返回键等触发Dialog消失,应该取消正在进行的网络请求等 |
| | | Context context = mContext.get(); |
| | | if (context != null) { |
| | | Toast.makeText(context, "cancel", Toast.LENGTH_SHORT).show(); |
| | | } |
| | | |
| | | } |
| | | |
| | | public static synchronized void showLoading(Context context) { |
| | | showLoading(context, "loading..."); |
| | | } |
| | | |
| | | public static synchronized void showLoading(Context context, CharSequence message) { |
| | | showLoading(context, message, true); |
| | | } |
| | | |
| | | public static synchronized void showLoading(Context context, CharSequence message, boolean cancelable) { |
| | | if (sDialog != null && sDialog.isShowing()) { |
| | | sDialog.dismiss(); |
| | | } |
| | | |
| | | if (context == null || !(context instanceof Activity)) { |
| | | return; |
| | | } |
| | | sDialog = new MyLoadingDialog(context, message); |
| | | sDialog.setCancelable(cancelable); |
| | | |
| | | if (sDialog != null && !sDialog.isShowing() && !((Activity) context).isFinishing()) { |
| | | sDialog.show(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onStart() { |
| | | super.onStart(); |
| | | int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
| | | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
| | | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
| | | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
| | | | View.SYSTEM_UI_FLAG_IMMERSIVE |
| | | | View.SYSTEM_UI_FLAG_FULLSCREEN; |
| | | this.getWindow().getDecorView().setSystemUiVisibility(uiOptions); |
| | | } |
| | | |
| | | public static synchronized void stopLoading() { |
| | | if (sDialog != null && sDialog.isShowing()) { |
| | | sDialog.dismiss(); |
| | | } |
| | | sDialog = null; |
| | | } |
| | | |
| | | |
| | | private void fullScreenImmersive(View view) { |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
| | | int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
| | | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
| | | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
| | | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
| | | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
| | | | View.SYSTEM_UI_FLAG_FULLSCREEN; |
| | | view.setSystemUiVisibility(uiOptions); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void show() { |
| | | Window window = getWindow(); |
| | | MyUtil.focusNotAle(window); |
| | | |
| | | super.show(); |
| | | MyUtil.hideNavigationBar(window); |
| | | MyUtil.clearFocusNotAle(window); |
| | | } |
| | | |
| | | private void applyCompat() { |
| | | if (Build.VERSION.SDK_INT < 19) { |
| | | return; |
| | | } |
| | | // 隐藏状态栏不占位 |
| | | getWindow().setFlags( |
| | | WindowManager.LayoutParams.FLAG_FULLSCREEN, |
| | | WindowManager.LayoutParams.FLAG_FULLSCREEN); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.app.Activity; |
| | | import android.app.Dialog; |
| | | import android.content.Context; |
| | | import android.os.Build; |
| | | import android.view.View; |
| | | import android.view.Window; |
| | | import android.view.WindowManager; |
| | | import android.view.inputmethod.InputMethodManager; |
| | | |
| | | |
| | | public class MyUtil { |
| | | |
| | | public static void showDialog(Dialog dialog, Activity activity) { |
| | | if (activity != null) { |
| | | //Set the dialog to not focusable (makes navigation ignore us adding the window) |
| | | dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); |
| | | dialog.show(); |
| | | //Set the dialog to immersive |
| | | dialog.getWindow().getDecorView().setSystemUiVisibility(activity.getWindow().getDecorView().getSystemUiVisibility()); |
| | | //Clear the not focusable flag from the window |
| | | dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); |
| | | } |
| | | } |
| | | |
| | | |
| | | public static void showKeyboard(View view) { |
| | | InputMethodManager imm = (InputMethodManager) view.getContext() |
| | | .getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null) { |
| | | view.requestFocus(); |
| | | imm.showSoftInput(view, 0); |
| | | } |
| | | } |
| | | |
| | | public static void hideKeyboard(View view){ |
| | | InputMethodManager imm = (InputMethodManager) view.getContext() |
| | | .getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null) { |
| | | imm.hideSoftInputFromWindow(view.getWindowToken(),0); |
| | | } |
| | | } |
| | | public static void toggleSoftInput(View view){ |
| | | InputMethodManager imm = (InputMethodManager) view.getContext() |
| | | .getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null) { |
| | | imm.toggleSoftInput(0,0); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 隐藏虚拟栏 ,显示的时候再隐藏掉 |
| | | * @param window |
| | | */ |
| | | static public void hideNavigationBar(final Window window) { |
| | | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); |
| | | window.getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { |
| | | @Override |
| | | public void onSystemUiVisibilityChange(int visibility) { |
| | | int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | |
| | | //布局位于状态栏下方 |
| | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | |
| | | //全屏 |
| | | View.SYSTEM_UI_FLAG_FULLSCREEN | |
| | | //隐藏导航栏 |
| | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | |
| | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; |
| | | if (Build.VERSION.SDK_INT >= 19) { |
| | | uiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; |
| | | } else { |
| | | uiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE; |
| | | } |
| | | window.getDecorView().setSystemUiVisibility(uiOptions); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * dialog 需要全屏的时候用,和clearFocusNotAle() 成对出现 |
| | | * 在show 前调用 focusNotAle show后调用clearFocusNotAle |
| | | * @param window |
| | | */ |
| | | static public void focusNotAle(Window window) { |
| | | window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, |
| | | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); |
| | | } |
| | | |
| | | /** |
| | | * dialog 需要全屏的时候用,focusNotAle() 成对出现 |
| | | * 在show 前调用 focusNotAle show后调用clearFocusNotAle |
| | | * @param window |
| | | */ |
| | | static public void clearFocusNotAle(Window window) { |
| | | window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.content.Context; |
| | | import android.content.SharedPreferences; |
| | | |
| | | public class ServerInfo { |
| | | private String server_ip; //服务器ip地址 |
| | | private int server_port; //服务器端口号 |
| | | private String server_name; //服务器项目名称 |
| | | |
| | | |
| | | //获取服务器信息 |
| | | public static ServerInfo readServerInfo(Context context){ |
| | | ServerInfo serverInfo = null; |
| | | if(context != null){ |
| | | serverInfo = new ServerInfo(); |
| | | SharedPreferences pref = context.getSharedPreferences("data", Context.MODE_PRIVATE); |
| | | serverInfo.server_ip = pref.getString("server_ip",""); |
| | | serverInfo.server_port = pref.getInt("server_port",0); |
| | | serverInfo.server_name = pref.getString("server_name",""); |
| | | } |
| | | return serverInfo; |
| | | } |
| | | |
| | | //保存服务器参数信息 |
| | | public static void WriteServerInfo(Context context,ServerInfo serverInfo){ |
| | | SharedPreferences.Editor editor = context.getSharedPreferences("data",Context.MODE_PRIVATE).edit(); |
| | | editor.putString("server_ip",serverInfo.server_ip); |
| | | editor.putInt("server_port",serverInfo.server_port); |
| | | editor.apply(); |
| | | } |
| | | |
| | | public String createServerUrl(){ |
| | | return "http://"+server_ip+":"+server_port+"/Device_Manage/index.html"; |
| | | //return "http://"+server_ip+":"+server_port+"/"; |
| | | } |
| | | |
| | | public String getServer_ip() { |
| | | return server_ip; |
| | | } |
| | | |
| | | public void setServer_ip(String server_ip) { |
| | | this.server_ip = server_ip; |
| | | } |
| | | |
| | | public int getServer_port() { |
| | | return server_port; |
| | | } |
| | | |
| | | public void setServer_port(int server_port) { |
| | | this.server_port = server_port; |
| | | } |
| | | |
| | | public String getServer_name() { |
| | | return server_name; |
| | | } |
| | | |
| | | public void setServer_name(String server_name) { |
| | | this.server_name = server_name; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "ServerInfo{" + |
| | | "server_ip='" + server_ip + '\'' + |
| | | ", server_port=" + server_port + |
| | | ", server_name='" + server_name + '\'' + |
| | | '}'; |
| | | } |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.app.AlertDialog; |
| | | import android.content.Context; |
| | | import android.os.Bundle; |
| | | import android.util.Log; |
| | | import android.view.View; |
| | | import android.view.WindowManager; |
| | | import android.widget.Button; |
| | | import android.widget.EditText; |
| | | import android.widget.Toast; |
| | | |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | public class ServerInfoDialog extends AlertDialog implements View.OnClickListener{ |
| | | private static String TAG = "ServerInfoDialog"; |
| | | |
| | | private Context context; |
| | | private Button btn_cancel; |
| | | private Button btn_confirm; |
| | | private ServerInfo serverInfo; |
| | | |
| | | private EditText tv_server_ip; |
| | | private EditText tv_server_port; |
| | | |
| | | public ServerInfoDialog(Context context){ |
| | | super(context); |
| | | this.context = context; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | setContentView(R.layout.dialog_layout); |
| | | |
| | | btn_cancel = (Button)findViewById(R.id.btn_cancel); |
| | | btn_confirm = (Button)findViewById(R.id.btn_confirrm); |
| | | |
| | | this.tv_server_ip = (EditText) findViewById(R.id.et_server_ip); |
| | | this.tv_server_port = (EditText)findViewById(R.id.et_server_port); |
| | | this.serverInfo = ServerInfo.readServerInfo(this.context); |
| | | Log.e(TAG, "onCreate: "+this.tv_server_ip ); |
| | | |
| | | if(this.serverInfo != null){ |
| | | tv_server_ip.setText(this.serverInfo.getServer_ip()); |
| | | tv_server_port.setText(this.serverInfo.getServer_port()+""); |
| | | }else{ |
| | | tv_server_ip.setText(""); |
| | | tv_server_port.setText(""); |
| | | } |
| | | this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); |
| | | this.setCancelable(false); |
| | | btn_cancel.setOnClickListener(this); |
| | | btn_confirm.setOnClickListener(this); |
| | | |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void onClick(View view){ |
| | | Log.e(TAG, "onClick: "+"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"+view.getId()); |
| | | switch (view.getId()){ |
| | | case R.id.btn_cancel:{ |
| | | this.dismiss(); |
| | | }break; |
| | | case R.id.btn_confirrm:{ |
| | | String server_ip = tv_server_ip.getText().toString(); |
| | | int server_port = Integer.parseInt(tv_server_port.getText().toString()); |
| | | |
| | | Pattern pattern = Pattern.compile("\\b((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\b"); |
| | | |
| | | Matcher matcher = pattern.matcher(server_ip); //验证IP地址有效性 |
| | | |
| | | if(!matcher.matches()){ |
| | | Toast.makeText(this.context, "IP地址格式错误", Toast.LENGTH_SHORT).show(); |
| | | }else if(server_port<1){ |
| | | Toast.makeText(this.context, "端口号必须大于0", Toast.LENGTH_SHORT).show(); |
| | | }else{ |
| | | this.serverInfo.setServer_ip(server_ip); |
| | | this.serverInfo.setServer_port(server_port); |
| | | ServerInfo.WriteServerInfo(this.context,this.serverInfo); |
| | | } |
| | | |
| | | }break; |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.app.Activity; |
| | | import android.content.Context; |
| | | import android.view.View; |
| | | import android.view.inputmethod.InputMethodManager; |
| | | import android.widget.EditText; |
| | | |
| | | /** |
| | | * 软键盘工具类 |
| | | * ·是否隐藏 |
| | | * ·显示 |
| | | * ·隐藏 |
| | | */ |
| | | public class SoftInputUtil { |
| | | |
| | | /** |
| | | * 判断键盘是否显示(当前editText是否在输入法活动状态,即是否正在接收软键盘输入)。 |
| | | * @param editText 输入框 |
| | | */ |
| | | public static boolean isSoftInputShowing(EditText editText){ |
| | | return isSoftInputShowing(editText.getContext(), editText); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 判断键盘是否显示(当前view是否在输入法活动状态,即是否正在接收软键盘输入)。 |
| | | * @param context 上下文 |
| | | * @param view 当前聚焦的正在接收软件盘输入的View。 |
| | | */ |
| | | public static boolean isSoftInputShowing(Context context, View view) { |
| | | boolean bool = false; |
| | | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null && imm.isActive(view)) { |
| | | bool = true; |
| | | } |
| | | return bool; |
| | | } |
| | | |
| | | /** |
| | | * 判断键盘是否显示(是否有View是在输入法活动状态,即是否正有View正在接收软键盘输入)。 |
| | | * @param context 上下文 |
| | | */ |
| | | public static boolean isSoftInputShowing(Context context) { |
| | | boolean bool = false; |
| | | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null && imm.isActive()) { |
| | | bool = true; |
| | | } |
| | | return bool; |
| | | } |
| | | |
| | | /** |
| | | * 显示键盘 |
| | | * @param view 当前聚焦的正在接收软件盘输入的View,通常为EditText。 |
| | | */ |
| | | public static void showSoftInput(View view) { |
| | | showSoftInput(view.getContext(), view); |
| | | } |
| | | |
| | | /** |
| | | * 显示键盘 |
| | | * @param context 上下文 |
| | | * @param view 当前聚焦的正在接收软件盘输入的View,通常为EditText。 |
| | | */ |
| | | public static void showSoftInput(Context context, View view) { |
| | | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null) { |
| | | //第二个参数为flags, 0 | InputMethodManager.SHOW_FORCED | InputMethodManager.SHOW_IMPLICIT |
| | | imm.showSoftInput(view, InputMethodManager.SHOW_FORCED); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 隐藏软键盘 |
| | | * @param activity |
| | | */ |
| | | public static void hideSoftInput(Activity activity) { |
| | | View view = activity.getWindow().peekDecorView(); |
| | | if (view != null) { |
| | | hideSoftInput(activity, view); |
| | | } |
| | | } |
| | | |
| | | public static void hideSoftInput(View view) { |
| | | if (view != null) { |
| | | hideSoftInput(view.getContext(), view); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 隐藏输入法 |
| | | * @param context 上下文 |
| | | * @param view 可以是任意已添加到window中的View(已添加到布局中的View)。 |
| | | */ |
| | | public static void hideSoftInput(Context context, View view) { |
| | | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (imm != null && imm.isActive()) { |
| | | //第二个参数为flags, 0 | InputMethodManager.HIDE_IMPLICIT_ONLY | InputMethodManager.HIDE_NOT_ALWAYS |
| | | imm.hideSoftInputFromWindow(view.getWindowToken(), 0); |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.graphics.Rect; |
| | | import android.view.View; |
| | | import android.view.ViewTreeObserver; |
| | | |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | public class SoftKeyboardStateHelper implements ViewTreeObserver.OnGlobalLayoutListener { |
| | | |
| | | public interface SoftKeyboardStateListener { |
| | | void onSoftKeyboardOpened(int keyboardHeightInPx); |
| | | |
| | | void onSoftKeyboardClosed(); |
| | | } |
| | | |
| | | private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>(); |
| | | private final View activityRootView; |
| | | private int lastSoftKeyboardHeightInPx; |
| | | private boolean isSoftKeyboardOpened; |
| | | |
| | | public SoftKeyboardStateHelper(View activityRootView) { |
| | | this(activityRootView, false); |
| | | } |
| | | |
| | | public SoftKeyboardStateHelper(View activityRootView, boolean isSoftKeyboardOpened) { |
| | | this.activityRootView = activityRootView; |
| | | this.isSoftKeyboardOpened = isSoftKeyboardOpened; |
| | | activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this); |
| | | } |
| | | |
| | | @Override |
| | | public void onGlobalLayout() { |
| | | final Rect r = new Rect(); |
| | | //r will be populated with the coordinates of your view that area still visible. |
| | | activityRootView.getWindowVisibleDisplayFrame(r); |
| | | |
| | | final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top); |
| | | if (!isSoftKeyboardOpened && heightDiff > 100) {// if more than 100 pixels, its probably a keyboard... |
| | | isSoftKeyboardOpened = true; |
| | | notifyOnSoftKeyboardOpened(heightDiff); |
| | | } else if (isSoftKeyboardOpened && heightDiff < 100) { |
| | | isSoftKeyboardOpened = false; |
| | | notifyOnSoftKeyboardClosed(); |
| | | } |
| | | } |
| | | |
| | | public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) { |
| | | this.isSoftKeyboardOpened = isSoftKeyboardOpened; |
| | | } |
| | | |
| | | public boolean isSoftKeyboardOpened() { |
| | | return isSoftKeyboardOpened; |
| | | } |
| | | |
| | | /** |
| | | * |
| | | * * Default value is zero (0) |
| | | * * @return last saved keyboard height in px |
| | | * |
| | | */ |
| | | public int getLastSoftKeyboardHeightInPx() { |
| | | return lastSoftKeyboardHeightInPx; |
| | | } |
| | | |
| | | public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) { |
| | | listeners.add(listener); |
| | | } |
| | | |
| | | public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) { |
| | | listeners.remove(listener); |
| | | } |
| | | |
| | | private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) { |
| | | this.lastSoftKeyboardHeightInPx = keyboardHeightInPx; |
| | | |
| | | for (SoftKeyboardStateListener listener : listeners) { |
| | | if (listener != null) { |
| | | listener.onSoftKeyboardOpened(keyboardHeightInPx); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void notifyOnSoftKeyboardClosed() { |
| | | for (SoftKeyboardStateListener listener : listeners) { |
| | | if (listener != null) { |
| | | listener.onSoftKeyboardClosed(); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import android.app.Activity; |
| | | import android.graphics.Rect; |
| | | import android.view.View; |
| | | import android.view.ViewTreeObserver; |
| | | |
| | | public class Softkeyboardlistener { |
| | | private View rootView;//activity的根视图 |
| | | int rootViewVisibleHeight;//纪录根视图的显示高度 |
| | | private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener; |
| | | |
| | | public Softkeyboardlistener(Activity activity) { |
| | | //获取activity的根视图 |
| | | rootView = activity.getWindow().getDecorView(); |
| | | |
| | | //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变 |
| | | rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { |
| | | @Override |
| | | public void onGlobalLayout() { |
| | | //获取当前根视图在屏幕上显示的大小 |
| | | Rect r = new Rect(); |
| | | rootView.getWindowVisibleDisplayFrame(r); |
| | | |
| | | int visibleHeight = r.height(); |
| | | System.out.println(""+visibleHeight); |
| | | if (rootViewVisibleHeight == 0) { |
| | | rootViewVisibleHeight = visibleHeight; |
| | | return; |
| | | } |
| | | |
| | | //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变 |
| | | if (rootViewVisibleHeight == visibleHeight) { |
| | | return; |
| | | } |
| | | |
| | | //根视图显示高度变小超过200,可以看作软键盘显示了 |
| | | if (rootViewVisibleHeight - visibleHeight > 200) { |
| | | if (onSoftKeyBoardChangeListener != null) { |
| | | onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight); |
| | | } |
| | | rootViewVisibleHeight = visibleHeight; |
| | | return; |
| | | } |
| | | |
| | | //根视图显示高度变大超过200,可以看作软键盘隐藏了 |
| | | if (visibleHeight - rootViewVisibleHeight > 200) { |
| | | if (onSoftKeyBoardChangeListener != null) { |
| | | onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight); |
| | | } |
| | | rootViewVisibleHeight = visibleHeight; |
| | | return; |
| | | } |
| | | |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { |
| | | this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener; |
| | | } |
| | | |
| | | public interface OnSoftKeyBoardChangeListener { |
| | | void keyBoardShow(int height); |
| | | |
| | | void keyBoardHide(int height); |
| | | } |
| | | |
| | | public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { |
| | | Softkeyboardlistener softKeyBoardListener = new Softkeyboardlistener(activity); |
| | | softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener); |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | xmlns:aapt="http://schemas.android.com/aapt" |
| | | android:width="108dp" |
| | | android:height="108dp" |
| | | android:viewportWidth="108" |
| | | android:viewportHeight="108"> |
| | | <path |
| | | android:fillType="evenOdd" |
| | | android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z" |
| | | android:strokeWidth="1" |
| | | android:strokeColor="#00000000"> |
| | | <aapt:attr name="android:fillColor"> |
| | | <gradient |
| | | android:endX="78.5885" |
| | | android:endY="90.9159" |
| | | android:startX="48.7653" |
| | | android:startY="61.0927" |
| | | android:type="linear"> |
| | | <item |
| | | android:color="#44000000" |
| | | android:offset="0.0" /> |
| | | <item |
| | | android:color="#00000000" |
| | | android:offset="1.0" /> |
| | | </gradient> |
| | | </aapt:attr> |
| | | </path> |
| | | <path |
| | | android:fillColor="#FFFFFF" |
| | | android:fillType="nonZero" |
| | | android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z" |
| | | android:strokeWidth="1" |
| | | android:strokeColor="#00000000" /> |
| | | </vector> |
New file |
| | |
| | | <?xml version ="1.0" encoding ="utf-8"?> |
| | | <selector xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <item |
| | | android:state_window_focused="false" |
| | | android:drawable="@drawable/bg_edittext_normal" |
| | | /> |
| | | <item |
| | | android:state_focused="true" |
| | | android:drawable="@drawable/bg_edittext_focused" /> |
| | | |
| | | </selector> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <shape xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <solid android:color="@android:color/transparent" /> |
| | | <corners android:radius="1dp"/> |
| | | <stroke |
| | | android:width="1dip" |
| | | android:color="#728ea3" /> |
| | | </shape> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <shape xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <solid android:color="@android:color/transparent" /> |
| | | <corners android:radius="1dp"/> |
| | | <stroke |
| | | android:width="1dip" |
| | | android:color="#BDC7D8" /> |
| | | </shape> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="108dp" |
| | | android:height="108dp" |
| | | android:viewportWidth="108" |
| | | android:viewportHeight="108"> |
| | | <path |
| | | android:fillColor="#008577" |
| | | android:pathData="M0,0h108v108h-108z" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M9,0L9,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M19,0L19,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M29,0L29,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M39,0L39,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M49,0L49,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M59,0L59,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M69,0L69,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M79,0L79,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M89,0L89,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M99,0L99,108" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,9L108,9" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,19L108,19" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,29L108,29" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,39L108,39" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,49L108,49" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,59L108,59" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,69L108,69" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,79L108,79" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,89L108,89" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M0,99L108,99" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M19,29L89,29" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M19,39L89,39" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M19,49L89,49" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M19,59L89,59" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M19,69L89,69" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M19,79L89,79" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M29,19L29,89" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M39,19L39,89" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M49,19L49,89" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M59,19L59,89" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M69,19L69,89" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | <path |
| | | android:fillColor="#00000000" |
| | | android:pathData="M79,19L79,89" |
| | | android:strokeWidth="0.8" |
| | | android:strokeColor="#33FFFFFF" /> |
| | | </vector> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <animation-list android:oneshot="false" |
| | | xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_01" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_02" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_03" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_04" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_05" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_06" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_07" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_08" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_09" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_10" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_11" /> |
| | | <item android:duration="83" android:drawable="@drawable/ic_loading_white_12" /> |
| | | </animation-list> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:background="#fff"> |
| | | <RelativeLayout |
| | | android:id="@+id/layout_title" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_centerHorizontal="true" |
| | | android:layout_marginTop="50dp" |
| | | > |
| | | <TextView |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:layout_centerInParent="true" |
| | | android:text="蓄电池监控管理系统" |
| | | android:textSize="60dp" |
| | | android:textColor="#1A81FF" |
| | | /> |
| | | </RelativeLayout> |
| | | <RelativeLayout |
| | | android:id="@+id/layout_content" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="250dp" |
| | | android:layout_below="@+id/layout_title" |
| | | android:background="#FFFFFF" |
| | | android:layout_marginTop="30dp" |
| | | android:focusable="true" |
| | | android:focusableInTouchMode="true" |
| | | > |
| | | |
| | | <RelativeLayout |
| | | android:id="@+id/layout_serverip" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="100dp" |
| | | android:layout_centerHorizontal="true" |
| | | android:layout_marginTop="20dp" |
| | | android:orientation="horizontal"> |
| | | |
| | | <TextView |
| | | android:id="@+id/tv_server_ip" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:text="服务器IP地址:" |
| | | android:textColor="#000" |
| | | android:layout_centerVertical="true" |
| | | android:layout_marginLeft="200dp" |
| | | android:textSize="26dp" |
| | | |
| | | /> |
| | | |
| | | <EditText |
| | | android:id="@+id/et_server_ip" |
| | | android:layout_toRightOf="@+id/tv_server_ip" |
| | | android:layout_centerVertical="true" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="50dp" |
| | | android:layout_marginLeft="10dp" |
| | | android:layout_marginRight="200dp" |
| | | android:textColor="#000" |
| | | android:textSize="25dp" |
| | | android:background="@drawable/bg_edittext" |
| | | android:paddingLeft="10dp" |
| | | android:lines="1" |
| | | |
| | | /> |
| | | </RelativeLayout> |
| | | <RelativeLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="100dp" |
| | | android:orientation="horizontal" |
| | | android:layout_below="@+id/layout_serverip" |
| | | > |
| | | <TextView |
| | | android:id="@+id/tv_server_port" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:text="服务器端口号:" |
| | | android:textColor="#000" |
| | | android:layout_centerVertical="true" |
| | | android:layout_marginLeft="200dp" |
| | | android:textSize="26dp" |
| | | /> |
| | | <EditText |
| | | android:id="@+id/et_server_port" |
| | | android:layout_toRightOf="@+id/tv_server_port" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="50dp" |
| | | android:layout_centerVertical="true" |
| | | android:layout_marginLeft="10dp" |
| | | android:layout_marginRight="200dp" |
| | | android:textColor="#000" |
| | | android:textSize="25dp" |
| | | android:background="@drawable/bg_edittext" |
| | | android:lines="1" |
| | | android:hint="请输入服务器端口号" |
| | | android:paddingLeft="10dp" |
| | | android:imeOptions="flagNoExtractUi" |
| | | /> |
| | | </RelativeLayout> |
| | | |
| | | </RelativeLayout> |
| | | <RelativeLayout |
| | | android:id="@+id/layout_button" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_below="@+id/layout_content" |
| | | android:layout_centerHorizontal="true" |
| | | android:padding="20dp" |
| | | > |
| | | <LinearLayout |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:layout_centerInParent="true" |
| | | android:orientation="horizontal" |
| | | > |
| | | <Button |
| | | android:id="@+id/btn_testConn" |
| | | android:layout_width="150dp" |
| | | android:layout_height="60dp" |
| | | android:text="测试连接" |
| | | android:textSize="20dp" |
| | | android:background="#5491FA" |
| | | android:layout_marginRight="80dp" |
| | | /> |
| | | <Button |
| | | android:id="@+id/btn_loginSys" |
| | | android:layout_width="150dp" |
| | | android:layout_height="60dp" |
| | | android:layout_toRightOf="@+id/btn_testConn" |
| | | android:text="进入系统" |
| | | android:textSize="20dp" |
| | | android:background="#5491FA" |
| | | /> |
| | | </LinearLayout> |
| | | |
| | | </RelativeLayout> |
| | | </RelativeLayout> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | > |
| | | <WebView |
| | | android:id="@+id/mywebview" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | ></WebView> |
| | | |
| | | </LinearLayout> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:background="@drawable/ic_loading_bg" |
| | | android:gravity="center" |
| | | android:orientation="vertical" |
| | | android:padding="16dp" > |
| | | |
| | | <ProgressBar |
| | | android:layout_width="48dp" |
| | | android:layout_height="48dp" |
| | | android:indeterminateDrawable="@drawable/progress_drawable_white" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/id_tv_loadingmsg" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:layout_gravity="center_vertical" |
| | | android:layout_marginTop="8dp" |
| | | android:textColor="#fff" |
| | | android:textSize="16dp" /> |
| | | |
| | | </LinearLayout> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:layout_width="550dp" |
| | | android:layout_height="240dp" |
| | | android:orientation="vertical" |
| | | android:background="#5893DF" |
| | | > |
| | | <TextView |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginTop="15dp" |
| | | android:gravity="center" |
| | | android:text="服务器信息配置" |
| | | android:textSize="18sp" /> |
| | | <View |
| | | android:layout_width="match_parent" |
| | | android:layout_height="2dp" |
| | | android:layout_marginLeft="20dp" |
| | | android:layout_marginRight="20dp" |
| | | android:layout_marginTop="10dp" |
| | | android:background="#F5F5F5" /> |
| | | <RelativeLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginTop="10dp" |
| | | android:layout_marginBottom="10dp" |
| | | > |
| | | <EditText |
| | | android:id="@+id/et_server_ip" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_centerHorizontal="true" |
| | | android:layout_marginLeft="20dp" |
| | | android:layout_marginRight="20dp" |
| | | android:layout_marginTop="10dp" |
| | | android:focusable="true" |
| | | android:focusableInTouchMode="true" |
| | | android:hint="请输入服务器IP" |
| | | android:inputType="textUri" /> |
| | | <EditText |
| | | android:id="@+id/et_server_port" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_below="@+id/et_server_ip" |
| | | android:layout_centerHorizontal="true" |
| | | android:layout_marginLeft="20dp" |
| | | android:layout_marginRight="20dp" |
| | | android:layout_marginTop="10dp" |
| | | android:focusable="true" |
| | | android:focusableInTouchMode="true" |
| | | android:hint="请输入端口号" |
| | | android:inputType="number" /> |
| | | </RelativeLayout> |
| | | |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginTop="5dp" |
| | | android:orientation="horizontal"> |
| | | <Button |
| | | android:id="@+id/btn_cancel" |
| | | android:layout_width="0dp" |
| | | android:layout_height="wrap_content" |
| | | android:layout_weight="1" |
| | | android:background="@null" |
| | | |
| | | android:text="取消" |
| | | android:textColor="#1965db" |
| | | android:textSize="16sp" /> |
| | | <Button |
| | | android:id="@+id/btn_confirrm" |
| | | android:layout_width="0dp" |
| | | android:layout_height="wrap_content" |
| | | android:layout_weight="1" |
| | | android:background="@null" |
| | | android:text="确定" |
| | | android:textColor="#1965db" |
| | | android:textSize="16sp" /> |
| | | </LinearLayout> |
| | | </LinearLayout> |
| | | |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <background android:drawable="@drawable/ic_launcher_background" /> |
| | | <foreground android:drawable="@drawable/ic_launcher_foreground" /> |
| | | </adaptive-icon> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <background android:drawable="@drawable/ic_launcher_background" /> |
| | | <foreground android:drawable="@drawable/ic_launcher_foreground" /> |
| | | </adaptive-icon> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <resources> |
| | | <color name="colorPrimary">#008577</color> |
| | | <color name="colorPrimaryDark">#00574B</color> |
| | | <color name="colorAccent">#D81B60</color> |
| | | </resources> |
New file |
| | |
| | | <resources> |
| | | <string name="app_name">myTestApp</string> |
| | | </resources> |
New file |
| | |
| | | <resources> |
| | | |
| | | <!-- Base application theme. --> |
| | | <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> |
| | | <!-- Customize your theme here. --> |
| | | <item name="colorPrimary">@color/colorPrimary</item> |
| | | <item name="colorPrimaryDark">@color/colorPrimaryDark</item> |
| | | <item name="colorAccent">@color/colorAccent</item> |
| | | </style> |
| | | |
| | | |
| | | <style name="progress_dialog" parent="@android:style/Theme.Dialog"> |
| | | <item name="android:windowFrame">@null</item> |
| | | <item name="android:windowIsFloating">true</item> |
| | | <item name="android:windowIsTranslucent">true</item> |
| | | <item name="android:windowNoTitle">true</item> |
| | | <item name="android:background">@null</item> |
| | | <item name="android:windowBackground">@null</item> |
| | | <item name="android:backgroundDimEnabled">false</item> |
| | | </style> |
| | | |
| | | <style name="MyTheme" parent="Theme.AppCompat.NoActionBar"> |
| | | <item name="android:windowFullscreen">true</item> |
| | | <item name="android:windowNoTitle">true</item> |
| | | </style> |
| | | |
| | | </resources> |
New file |
| | |
| | | package com.mytestapp; |
| | | |
| | | import org.junit.Test; |
| | | |
| | | import static org.junit.Assert.*; |
| | | |
| | | /** |
| | | * Example local unit test, which will execute on the development machine (host). |
| | | * |
| | | * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> |
| | | */ |
| | | public class ExampleUnitTest { |
| | | @Test |
| | | public void addition_isCorrect() { |
| | | assertEquals(4, 2 + 2); |
| | | } |
| | | } |
New file |
| | |
| | | // Top-level build file where you can add configuration options common to all sub-projects/modules. |
| | | |
| | | buildscript { |
| | | repositories { |
| | | google() |
| | | jcenter() |
| | | |
| | | } |
| | | dependencies { |
| | | classpath 'com.android.tools.build:gradle:3.5.3' |
| | | |
| | | // NOTE: Do not place your application dependencies here; they belong |
| | | // in the individual module build.gradle files |
| | | } |
| | | } |
| | | |
| | | allprojects { |
| | | repositories { |
| | | google() |
| | | jcenter() |
| | | |
| | | } |
| | | } |
| | | |
| | | task clean(type: Delete) { |
| | | delete rootProject.buildDir |
| | | } |
New file |
| | |
| | | # Project-wide Gradle settings. |
| | | # IDE (e.g. Android Studio) users: |
| | | # Gradle settings configured through the IDE *will override* |
| | | # any settings specified in this file. |
| | | # For more details on how to configure your build environment visit |
| | | # http://www.gradle.org/docs/current/userguide/build_environment.html |
| | | # Specifies the JVM arguments used for the daemon process. |
| | | # The setting is particularly useful for tweaking memory settings. |
| | | org.gradle.jvmargs=-Xmx1536m |
| | | # When configured, Gradle will run in incubating parallel mode. |
| | | # This option should only be used with decoupled projects. More details, visit |
| | | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects |
| | | # org.gradle.parallel=true |
| | | # AndroidX package structure to make it clearer which packages are bundled with the |
| | | # Android operating system, and which are packaged with your app's APK |
| | | # https://developer.android.com/topic/libraries/support-library/androidx-rn |
| | | android.useAndroidX=true |
| | | # Automatically convert third-party libraries to use AndroidX |
| | | android.enableJetifier=true |
| | | |
New file |
| | |
| | | #Tue Dec 31 08:56:59 CST 2019 |
| | | distributionBase=GRADLE_USER_HOME |
| | | distributionPath=wrapper/dists |
| | | zipStoreBase=GRADLE_USER_HOME |
| | | zipStorePath=wrapper/dists |
| | | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip |
New file |
| | |
| | | #!/usr/bin/env sh |
| | | |
| | | ############################################################################## |
| | | ## |
| | | ## Gradle start up script for UN*X |
| | | ## |
| | | ############################################################################## |
| | | |
| | | # Attempt to set APP_HOME |
| | | # Resolve links: $0 may be a link |
| | | PRG="$0" |
| | | # Need this for relative symlinks. |
| | | while [ -h "$PRG" ] ; do |
| | | ls=`ls -ld "$PRG"` |
| | | link=`expr "$ls" : '.*-> \(.*\)$'` |
| | | if expr "$link" : '/.*' > /dev/null; then |
| | | PRG="$link" |
| | | else |
| | | PRG=`dirname "$PRG"`"/$link" |
| | | fi |
| | | done |
| | | SAVED="`pwd`" |
| | | cd "`dirname \"$PRG\"`/" >/dev/null |
| | | APP_HOME="`pwd -P`" |
| | | cd "$SAVED" >/dev/null |
| | | |
| | | APP_NAME="Gradle" |
| | | APP_BASE_NAME=`basename "$0"` |
| | | |
| | | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
| | | DEFAULT_JVM_OPTS="" |
| | | |
| | | # Use the maximum available, or set MAX_FD != -1 to use that value. |
| | | MAX_FD="maximum" |
| | | |
| | | warn () { |
| | | echo "$*" |
| | | } |
| | | |
| | | die () { |
| | | echo |
| | | echo "$*" |
| | | echo |
| | | exit 1 |
| | | } |
| | | |
| | | # OS specific support (must be 'true' or 'false'). |
| | | cygwin=false |
| | | msys=false |
| | | darwin=false |
| | | nonstop=false |
| | | case "`uname`" in |
| | | CYGWIN* ) |
| | | cygwin=true |
| | | ;; |
| | | Darwin* ) |
| | | darwin=true |
| | | ;; |
| | | MINGW* ) |
| | | msys=true |
| | | ;; |
| | | NONSTOP* ) |
| | | nonstop=true |
| | | ;; |
| | | esac |
| | | |
| | | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
| | | |
| | | # Determine the Java command to use to start the JVM. |
| | | if [ -n "$JAVA_HOME" ] ; then |
| | | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
| | | # IBM's JDK on AIX uses strange locations for the executables |
| | | JAVACMD="$JAVA_HOME/jre/sh/java" |
| | | else |
| | | JAVACMD="$JAVA_HOME/bin/java" |
| | | fi |
| | | if [ ! -x "$JAVACMD" ] ; then |
| | | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
| | | |
| | | Please set the JAVA_HOME variable in your environment to match the |
| | | location of your Java installation." |
| | | fi |
| | | else |
| | | JAVACMD="java" |
| | | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
| | | |
| | | Please set the JAVA_HOME variable in your environment to match the |
| | | location of your Java installation." |
| | | fi |
| | | |
| | | # Increase the maximum file descriptors if we can. |
| | | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then |
| | | MAX_FD_LIMIT=`ulimit -H -n` |
| | | if [ $? -eq 0 ] ; then |
| | | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then |
| | | MAX_FD="$MAX_FD_LIMIT" |
| | | fi |
| | | ulimit -n $MAX_FD |
| | | if [ $? -ne 0 ] ; then |
| | | warn "Could not set maximum file descriptor limit: $MAX_FD" |
| | | fi |
| | | else |
| | | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" |
| | | fi |
| | | fi |
| | | |
| | | # For Darwin, add options to specify how the application appears in the dock |
| | | if $darwin; then |
| | | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" |
| | | fi |
| | | |
| | | # For Cygwin, switch paths to Windows format before running java |
| | | if $cygwin ; then |
| | | APP_HOME=`cygpath --path --mixed "$APP_HOME"` |
| | | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` |
| | | JAVACMD=`cygpath --unix "$JAVACMD"` |
| | | |
| | | # We build the pattern for arguments to be converted via cygpath |
| | | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` |
| | | SEP="" |
| | | for dir in $ROOTDIRSRAW ; do |
| | | ROOTDIRS="$ROOTDIRS$SEP$dir" |
| | | SEP="|" |
| | | done |
| | | OURCYGPATTERN="(^($ROOTDIRS))" |
| | | # Add a user-defined pattern to the cygpath arguments |
| | | if [ "$GRADLE_CYGPATTERN" != "" ] ; then |
| | | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" |
| | | fi |
| | | # Now convert the arguments - kludge to limit ourselves to /bin/sh |
| | | i=0 |
| | | for arg in "$@" ; do |
| | | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` |
| | | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option |
| | | |
| | | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition |
| | | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` |
| | | else |
| | | eval `echo args$i`="\"$arg\"" |
| | | fi |
| | | i=$((i+1)) |
| | | done |
| | | case $i in |
| | | (0) set -- ;; |
| | | (1) set -- "$args0" ;; |
| | | (2) set -- "$args0" "$args1" ;; |
| | | (3) set -- "$args0" "$args1" "$args2" ;; |
| | | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; |
| | | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; |
| | | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; |
| | | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; |
| | | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; |
| | | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; |
| | | esac |
| | | fi |
| | | |
| | | # Escape application args |
| | | save () { |
| | | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done |
| | | echo " " |
| | | } |
| | | APP_ARGS=$(save "$@") |
| | | |
| | | # Collect all arguments for the java command, following the shell quoting and substitution rules |
| | | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" |
| | | |
| | | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong |
| | | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then |
| | | cd "$(dirname "$0")" |
| | | fi |
| | | |
| | | exec "$JAVACMD" "$@" |
New file |
| | |
| | | @if "%DEBUG%" == "" @echo off |
| | | @rem ########################################################################## |
| | | @rem |
| | | @rem Gradle startup script for Windows |
| | | @rem |
| | | @rem ########################################################################## |
| | | |
| | | @rem Set local scope for the variables with windows NT shell |
| | | if "%OS%"=="Windows_NT" setlocal |
| | | |
| | | set DIRNAME=%~dp0 |
| | | if "%DIRNAME%" == "" set DIRNAME=. |
| | | set APP_BASE_NAME=%~n0 |
| | | set APP_HOME=%DIRNAME% |
| | | |
| | | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
| | | set DEFAULT_JVM_OPTS= |
| | | |
| | | @rem Find java.exe |
| | | if defined JAVA_HOME goto findJavaFromJavaHome |
| | | |
| | | set JAVA_EXE=java.exe |
| | | %JAVA_EXE% -version >NUL 2>&1 |
| | | if "%ERRORLEVEL%" == "0" goto init |
| | | |
| | | echo. |
| | | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
| | | echo. |
| | | echo Please set the JAVA_HOME variable in your environment to match the |
| | | echo location of your Java installation. |
| | | |
| | | goto fail |
| | | |
| | | :findJavaFromJavaHome |
| | | set JAVA_HOME=%JAVA_HOME:"=% |
| | | set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
| | | |
| | | if exist "%JAVA_EXE%" goto init |
| | | |
| | | echo. |
| | | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |
| | | echo. |
| | | echo Please set the JAVA_HOME variable in your environment to match the |
| | | echo location of your Java installation. |
| | | |
| | | goto fail |
| | | |
| | | :init |
| | | @rem Get command-line arguments, handling Windows variants |
| | | |
| | | if not "%OS%" == "Windows_NT" goto win9xME_args |
| | | |
| | | :win9xME_args |
| | | @rem Slurp the command line arguments. |
| | | set CMD_LINE_ARGS= |
| | | set _SKIP=2 |
| | | |
| | | :win9xME_args_slurp |
| | | if "x%~1" == "x" goto execute |
| | | |
| | | set CMD_LINE_ARGS=%* |
| | | |
| | | :execute |
| | | @rem Setup the command line |
| | | |
| | | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
| | | |
| | | @rem Execute Gradle |
| | | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% |
| | | |
| | | :end |
| | | @rem End local scope for the variables with windows NT shell |
| | | if "%ERRORLEVEL%"=="0" goto mainEnd |
| | | |
| | | :fail |
| | | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
| | | rem the _cmd.exe /c_ return code! |
| | | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 |
| | | exit /b 1 |
| | | |
| | | :mainEnd |
| | | if "%OS%"=="Windows_NT" endlocal |
| | | |
| | | :omega |