### 2022-05-14 V1.0版本
- *.初始版本
This commit is contained in:
commit
034569ede1
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
### 2022-05-14 V1.0版本
|
||||
|
||||
- *.初始版本
|
||||
15
Client/android/MyEasyWOL/.gitignore
vendored
Normal file
15
Client/android/MyEasyWOL/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
3
Client/android/MyEasyWOL/.idea/.gitignore
vendored
Normal file
3
Client/android/MyEasyWOL/.idea/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
6
Client/android/MyEasyWOL/.idea/compiler.xml
Normal file
6
Client/android/MyEasyWOL/.idea/compiler.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<component name="CopyrightManager">
|
||||
<settings default="xuexiang">
|
||||
<module2copyright>
|
||||
<element module="Project Files" copyright="xuexiang" />
|
||||
</module2copyright>
|
||||
</settings>
|
||||
</component>
|
||||
6
Client/android/MyEasyWOL/.idea/copyright/xuexiang.xml
Normal file
6
Client/android/MyEasyWOL/.idea/copyright/xuexiang.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright (C) &#36;today.year xuexiangjys(xuexiangjys@163.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. " />
|
||||
<option name="myName" value="xuexiang" />
|
||||
</copyright>
|
||||
</component>
|
||||
21
Client/android/MyEasyWOL/.idea/gradle.xml
Normal file
21
Client/android/MyEasyWOL/.idea/gradle.xml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="PLATFORM" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="1.8" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
100
Client/android/MyEasyWOL/.idea/jarRepositories.xml
Normal file
100
Client/android/MyEasyWOL/.idea/jarRepositories.xml
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="MavenLocal" />
|
||||
<option name="name" value="MavenLocal" />
|
||||
<option name="url" value="file:/$USER_HOME$/.m2/repository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="Google" />
|
||||
<option name="name" value="Google" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/google" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven4" />
|
||||
<option name="name" value="maven4" />
|
||||
<option name="url" value="https://dl.bintray.com/umsdk/release" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven5" />
|
||||
<option name="name" value="maven5" />
|
||||
<option name="url" value="https://oss.sonatype.org/content/repositories/public" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="BintrayJCenter" />
|
||||
<option name="name" value="BintrayJCenter" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/jcenter" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven6" />
|
||||
<option name="name" value="maven6" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../Android%20Code/TemplateAppProject-master/LocalRepository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven" />
|
||||
<option name="name" value="maven" />
|
||||
<option name="url" value="http://maven.aliyun.com/nexus/content/repositories/jcenter" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="MavenRepo" />
|
||||
<option name="name" value="MavenRepo" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/central" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven2" />
|
||||
<option name="name" value="maven2" />
|
||||
<option name="url" value="https://jitpack.io" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven3" />
|
||||
<option name="name" value="maven3" />
|
||||
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven6" />
|
||||
<option name="name" value="maven6" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../Android%20Code/TemplateAppProject-master/app/LocalRepository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven6" />
|
||||
<option name="name" value="maven6" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../Android%20Code/QuickPower/LocalRepository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven6" />
|
||||
<option name="name" value="maven6" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../Android%20Code/QuickPower/app/LocalRepository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven5" />
|
||||
<option name="name" value="maven5" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../../My%20Datas/android%20code/quickpower/LocalRepository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven5" />
|
||||
<option name="name" value="maven5" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../../My%20Datas/android%20code/quickpower/app/LocalRepository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven5" />
|
||||
<option name="name" value="maven5" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../../../../My%20Datas/MyEasyWOL/Client/android/MyEasyWOL/LocalRepository" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven5" />
|
||||
<option name="name" value="maven5" />
|
||||
<option name="url" value="file:/$PROJECT_DIR$/../../../../../My%20Datas/MyEasyWOL/Client/android/MyEasyWOL/app/LocalRepository" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
10
Client/android/MyEasyWOL/.idea/markdown-navigator-enh.xml
Normal file
10
Client/android/MyEasyWOL/.idea/markdown-navigator-enh.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownEnhProjectSettings">
|
||||
<AnnotatorSettings targetHasSpaces="true" linkCaseMismatch="true" wikiCaseMismatch="true" wikiLinkHasDashes="true" notUnderWikiHome="true" targetNotWikiPageExt="true" notUnderSourceWikiHome="true" targetNameHasAnchor="true" targetPathHasAnchor="true" wikiLinkHasSlash="true" wikiLinkHasSubdir="true" wikiLinkHasOnlyAnchor="true" linkTargetsWikiHasExt="true" linkTargetsWikiHasBadExt="true" notUnderSameRepo="true" targetNotUnderVcs="false" linkNeedsExt="true" linkHasBadExt="true" linkTargetNeedsExt="true" linkTargetHasBadExt="true" wikiLinkNotInWiki="true" imageTargetNotInRaw="true" repoRelativeAcrossVcsRoots="true" multipleWikiTargetsMatch="true" unresolvedLinkReference="true" linkIsIgnored="true" anchorIsIgnored="true" anchorIsUnresolved="true" anchorLineReferenceIsUnresolved="true" anchorLineReferenceFormat="true" anchorHasDuplicates="true" abbreviationDuplicates="true" abbreviationNotUsed="true" attributeIdDuplicateDefinition="true" attributeIdNotUsed="true" footnoteDuplicateDefinition="true" footnoteUnresolved="true" footnoteDuplicates="true" footnoteNotUsed="true" macroDuplicateDefinition="true" macroUnresolved="true" macroDuplicates="true" macroNotUsed="true" referenceDuplicateDefinition="true" referenceUnresolved="true" referenceDuplicates="true" referenceNotUsed="true" referenceUnresolvedNumericId="true" enumRefDuplicateDefinition="true" enumRefUnresolved="true" enumRefDuplicates="true" enumRefNotUsed="true" enumRefLinkUnresolved="true" enumRefLinkDuplicates="true" simTocUpdateNeeded="true" simTocTitleSpaceNeeded="true" />
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="css" scriptDir="js" plainHtml="false" imageDir="" copyLinkedImages="false" imagePathType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
</project>
|
||||
62
Client/android/MyEasyWOL/.idea/markdown-navigator.xml
Normal file
62
Client/android/MyEasyWOL/.idea/markdown-navigator.xml
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownProjectSettings">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" synchronizePreviewPosition="true" highlightPreviewType="LINE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="true" showSelectionInPreview="true" lastLayoutSetsDefault="false">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.md.nav.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings gitHubSyntaxChange="false" correctedInvalidSettings="false" emojiShortcuts="1" emojiImages="0">
|
||||
<PegdownExtensions>
|
||||
<option name="ATXHEADERSPACE" value="true" />
|
||||
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||
<option name="INTELLIJ_DUMMY_IDENTIFIER" value="true" />
|
||||
<option name="RELAXEDHRULES" value="true" />
|
||||
<option name="STRIKETHROUGH" value="true" />
|
||||
<option name="TABLES" value="true" />
|
||||
<option name="TASKLISTITEMS" value="true" />
|
||||
</PegdownExtensions>
|
||||
<ParserOptions>
|
||||
<option name="COMMONMARK_LISTS" value="true" />
|
||||
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||
<option name="PRODUCTION_SPEC_PARSER" value="true" />
|
||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||
</ParserOptions>
|
||||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" addPageHeader="false" addAnchorLinks="false" anchorLinksWrapText="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" defaultUrlTitle="false" migratedPlantUml="true" migratedAnchorLinks="true" plantUmlConversion="0">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.md.nav.editor.text.html.generator" providerName="Unmodified HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
<bodyTop />
|
||||
<bodyBottom />
|
||||
<fencedCodeConversions>
|
||||
<option name="c4plantuml" value="NONE" />
|
||||
<option name="ditaa" value="NONE" />
|
||||
<option name="erd" value="NONE" />
|
||||
<option name="graphviz" value="NONE" />
|
||||
<option name="latex" value="KATEX" />
|
||||
<option name="math" value="KATEX" />
|
||||
<option name="mermaid" value="NONE" />
|
||||
<option name="nomnoml" value="NONE" />
|
||||
<option name="plantuml" value="NONE" />
|
||||
<option name="puml" value="NONE" />
|
||||
<option name="svgbob" value="NONE" />
|
||||
<option name="umlet" value="NONE" />
|
||||
<option name="vega" value="NONE" />
|
||||
<option name="vegalite" value="NONE" />
|
||||
<option name="wavedrom" value="NONE" />
|
||||
</fencedCodeConversions>
|
||||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.md.nav.editor.text.html.css" providerName="No Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<cssText />
|
||||
<cssUriHistory />
|
||||
</CssSettings>
|
||||
</component>
|
||||
</project>
|
||||
4
Client/android/MyEasyWOL/.idea/misc.xml
Normal file
4
Client/android/MyEasyWOL/.idea/misc.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
10
Client/android/MyEasyWOL/.idea/runConfigurations.xml
Normal file
10
Client/android/MyEasyWOL/.idea/runConfigurations.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
Client/android/MyEasyWOL/.idea/vcs.xml
Normal file
6
Client/android/MyEasyWOL/.idea/vcs.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
191
Client/android/MyEasyWOL/LICENSE
Normal file
191
Client/android/MyEasyWOL/LICENSE
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "{}" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright 2018 xuexiangjys
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
1
Client/android/MyEasyWOL/app/.gitignore
vendored
Normal file
1
Client/android/MyEasyWOL/app/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
140
Client/android/MyEasyWOL/app/build.gradle
Normal file
140
Client/android/MyEasyWOL/app/build.gradle
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'img-optimizer'
|
||||
apply plugin: 'org.greenrobot.greendao'
|
||||
//打包时,记得设置true启用
|
||||
if (isNeedPackage.toBoolean() && isUseBooster.toBoolean()) {
|
||||
apply plugin: 'com.didiglobal.booster'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion build_versions.target_sdk
|
||||
buildToolsVersion build_versions.build_tools
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.itrycn.myeasywol"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion build_versions.target_sdk
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
multiDexEnabled true
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [ moduleName : project.getName() ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
if (isNeedPackage.toBoolean()) {
|
||||
release {
|
||||
storeFile file(app_release.storeFile)
|
||||
storePassword app_release.storePassword
|
||||
keyAlias app_release.keyAlias
|
||||
keyPassword app_release.keyPassword
|
||||
}
|
||||
}
|
||||
|
||||
debug {
|
||||
storeFile file("./debug.jks")
|
||||
storePassword "123456"
|
||||
keyAlias "debug"
|
||||
keyPassword "123456"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
if (isNeedPackage.toBoolean()) {
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
Properties properties = new Properties()
|
||||
properties.load(project.rootProject.file('local.properties').newDataInputStream())
|
||||
def appID = properties.getProperty("APP_ID_UMENG")
|
||||
if (appID != null) {
|
||||
buildConfigField "String", "APP_ID_UMENG", appID
|
||||
} else {
|
||||
buildConfigField "String", "APP_ID_UMENG", '""'
|
||||
}
|
||||
} else {
|
||||
signingConfig signingConfigs.debug
|
||||
buildConfigField "String", "APP_ID_UMENG", '""'
|
||||
}
|
||||
}
|
||||
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
|
||||
signingConfig signingConfigs.debug
|
||||
buildConfigField "String", "APP_ID_UMENG", '""'
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
//greendao设置相关参数
|
||||
greendao {
|
||||
schemaVersion 2
|
||||
daoPackage 'com.itrycn.myeasywol.db.dao'
|
||||
targetGenDir 'src/main/java'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
testImplementation deps.junit
|
||||
androidTestImplementation deps.runner
|
||||
androidTestImplementation deps.espresso.core
|
||||
implementation 'org.greenrobot:greendao:3.3.0'
|
||||
//列表侧滑菜单
|
||||
implementation 'com.yanzhenjie.recyclerview:support:1.3.2'
|
||||
/**
|
||||
* greendao 加密
|
||||
*/
|
||||
implementation 'net.zetetic:android-database-sqlcipher:3.5.7'
|
||||
//分包
|
||||
implementation deps.androidx.multidex
|
||||
|
||||
implementation 'com.alibaba.android:vlayout:1.2.36'
|
||||
//下拉刷新
|
||||
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-header:1.1.5'
|
||||
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-layout:1.1.5'
|
||||
//WebView
|
||||
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.0'
|
||||
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.0'//选填
|
||||
//腾讯的键值对存储mmkv
|
||||
implementation 'com.tencent:mmkv:1.0.22'
|
||||
//屏幕适配AutoSize
|
||||
implementation 'me.jessyan:autosize:1.1.2'
|
||||
|
||||
//预加载占位控件
|
||||
implementation 'me.samlss:broccoli:1.0.0'
|
||||
|
||||
implementation 'com.zzhoujay.richtext:richtext:3.0.8'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
|
||||
//ANR异常捕获
|
||||
implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'
|
||||
|
||||
//美团多渠道打包
|
||||
implementation 'com.meituan.android.walle:library:1.1.6'
|
||||
}
|
||||
//自动添加X-Library依赖
|
||||
apply from: 'x-library.gradle'
|
||||
//walle多渠道打包
|
||||
apply from: 'multiple-channel.gradle'
|
||||
|
||||
|
||||
25
Client/android/MyEasyWOL/app/channel
Normal file
25
Client/android/MyEasyWOL/app/channel
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# 美团
|
||||
meituan
|
||||
# 三星
|
||||
samsungapps
|
||||
# 小米
|
||||
xiaomi
|
||||
# 91助手
|
||||
91com
|
||||
# 魅族
|
||||
meizu
|
||||
# 豌豆荚
|
||||
wandou
|
||||
# Google Play
|
||||
googleplay
|
||||
# 百度
|
||||
baidu
|
||||
# 360
|
||||
360cn
|
||||
# 应用宝
|
||||
myapp
|
||||
# 华为
|
||||
huawei
|
||||
# 蒲公英
|
||||
pgyer
|
||||
github
|
||||
BIN
Client/android/MyEasyWOL/app/debug.jks
Normal file
BIN
Client/android/MyEasyWOL/app/debug.jks
Normal file
Binary file not shown.
10
Client/android/MyEasyWOL/app/multiple-channel.gradle
Normal file
10
Client/android/MyEasyWOL/app/multiple-channel.gradle
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
apply plugin: 'walle'
|
||||
|
||||
walle {
|
||||
// 指定渠道包的输出路径
|
||||
apkOutputFolder = new File("${project.buildDir}/outputs/channels")
|
||||
// 定制渠道包的APK的文件名称
|
||||
apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk'
|
||||
// 渠道配置文件
|
||||
channelFile = new File("${project.getProjectDir()}/channel")
|
||||
}
|
||||
268
Client/android/MyEasyWOL/app/proguard-rules.pro
vendored
Normal file
268
Client/android/MyEasyWOL/app/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
#=========================================基础不变的混淆配置=========================================##
|
||||
#指定代码的压缩级别
|
||||
-optimizationpasses 5
|
||||
#包名不混合大小写
|
||||
-dontusemixedcaseclassnames
|
||||
#不去忽略非公共的库类
|
||||
-dontskipnonpubliclibraryclasses
|
||||
# 指定不去忽略非公共的库的类的成员
|
||||
-dontskipnonpubliclibraryclassmembers
|
||||
#优化 不优化输入的类文件
|
||||
-dontoptimize
|
||||
#预校验
|
||||
-dontpreverify
|
||||
#混淆时是否记录日志
|
||||
-verbose
|
||||
# 混淆时所采用的算法
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
#保护注解
|
||||
-keepattributes *Annotation*
|
||||
#忽略警告
|
||||
-ignorewarnings
|
||||
|
||||
##记录生成的日志数据,gradle build时在本项目根目录输出##
|
||||
#apk 包内所有 class 的内部结构
|
||||
-dump class_files.txt
|
||||
#未混淆的类和成员
|
||||
-printseeds seeds.txt
|
||||
#列出从 apk 中删除的代码
|
||||
-printusage unused.txt
|
||||
#混淆前后的映射
|
||||
-printmapping mapping.txt
|
||||
# 并保留源文件名为"Proguard"字符串,而非原始的类名 并保留行号
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
########记录生成的日志数据,gradle build时 在本项目根目录输出-end#####
|
||||
|
||||
#需要保留的东西
|
||||
# 保持哪些类不被混淆
|
||||
-keep public class * extends android.app.Fragment
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class * extends android.support.v4.**
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
#如果有引用v4包可以添加下面这行
|
||||
-keep public class * extends android.support.v4.app.Fragment
|
||||
|
||||
##########JS接口类不混淆,否则执行不了
|
||||
-dontwarn com.android.JsInterface.**
|
||||
-keep class com.android.JsInterface.** {*; }
|
||||
|
||||
#极光推送和百度lbs android sdk一起使用proguard 混淆的问题#http的类被混淆后,导致apk定位失败,保持apache 的http类不被混淆就好了
|
||||
-dontwarn org.apache.**
|
||||
-keep class org.apache.**{ *; }
|
||||
|
||||
-keep public class * extends android.view.View {
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
public void set*(...);
|
||||
}
|
||||
|
||||
#保持 native 方法不被混淆
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
#保持 Parcelable 不被混淆
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
#保持 Serializable 不被混淆
|
||||
-keepnames class * implements java.io.Serializable
|
||||
|
||||
#保持 Serializable 不被混淆并且enum 类也不被混淆
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
static final long serialVersionUID;
|
||||
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||
!static !transient <fields>;
|
||||
!private <fields>;
|
||||
!private <methods>;
|
||||
private void writeObject(java.io.ObjectOutputStream);
|
||||
private void readObject(java.io.ObjectInputStream);
|
||||
java.lang.Object writeReplace();
|
||||
java.lang.Object readResolve();
|
||||
}
|
||||
|
||||
#保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keepclassmembers class * {
|
||||
public void *ButtonClicked(android.view.View);
|
||||
}
|
||||
|
||||
#不混淆资源类
|
||||
-keep class **.R$* {*;}
|
||||
|
||||
#===================================混淆保护自己项目的部分代码以及引用的第三方jar包library=============================#######
|
||||
#如果引用了v4或者v7包
|
||||
-dontwarn android.support.**
|
||||
|
||||
|
||||
# AndroidX 防止混淆
|
||||
-dontwarn com.google.android.material.**
|
||||
-dontnote com.google.android.material.**
|
||||
-dontwarn androidx.**
|
||||
-keep class com.google.android.material.** {*;}
|
||||
-keep class androidx.** {*;}
|
||||
-keep public class * extends androidx.**
|
||||
-keep interface androidx.** {*;}
|
||||
-keepclassmembers class * {
|
||||
@androidx.annotation.Keep *;
|
||||
}
|
||||
|
||||
# zxing
|
||||
-dontwarn com.google.zxing.**
|
||||
-keep class com.google.zxing.**{*;}
|
||||
|
||||
#SignalR推送
|
||||
-keep class microsoft.aspnet.signalr.** { *; }
|
||||
|
||||
# 极光推送混淆
|
||||
-dontoptimize
|
||||
-dontpreverify
|
||||
-dontwarn cn.jpush.**
|
||||
-keep class cn.jpush.** { *; }
|
||||
-dontwarn cn.jiguang.**
|
||||
-keep class cn.jiguang.** { *; }
|
||||
|
||||
# 数据库框架OrmLite
|
||||
-keepattributes *DatabaseField*
|
||||
-keepattributes *DatabaseTable*
|
||||
-keepattributes *SerializedName*
|
||||
-keep class com.j256.**
|
||||
-keepclassmembers class com.j256.** { *; }
|
||||
-keep enum com.j256.**
|
||||
-keepclassmembers enum com.j256.** { *; }
|
||||
-keep interface com.j256.**
|
||||
-keepclassmembers interface com.j256.** { *; }
|
||||
|
||||
#XHttp2
|
||||
-keep class com.xuexiang.xhttp2.model.** { *; }
|
||||
-keep class com.xuexiang.xhttp2.cache.model.** { *; }
|
||||
-keep class com.xuexiang.xhttp2.cache.stategy.**{*;}
|
||||
-keep class com.xuexiang.xhttp2.annotation.** { *; }
|
||||
|
||||
#okhttp
|
||||
-dontwarn com.squareup.okhttp3.**
|
||||
-keep class com.squareup.okhttp3.** { *;}
|
||||
-dontwarn okio.**
|
||||
-dontwarn javax.annotation.Nullable
|
||||
-dontwarn javax.annotation.ParametersAreNonnullByDefault
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
#如果用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错
|
||||
-keepattributes Signature
|
||||
-keep class com.google.gson.stream.** { *; }
|
||||
-keepattributes EnclosingMethod
|
||||
-keep class org.xz_sale.entity.**{*;}
|
||||
-keep class com.google.gson.** {*;}
|
||||
-keep class com.google.**{*;}
|
||||
-keep class sun.misc.Unsafe { *; }
|
||||
-keep class com.google.gson.stream.** { *; }
|
||||
-keep class com.google.gson.examples.android.model.** { *; }
|
||||
|
||||
# Glide
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep public class * extends com.bumptech.glide.module.AppGlideModule
|
||||
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
||||
|
||||
# Retrofit
|
||||
-dontwarn retrofit2.**
|
||||
-keep class retrofit2.** { *; }
|
||||
-keepattributes Exceptions
|
||||
|
||||
# RxJava RxAndroid
|
||||
-dontwarn sun.misc.**
|
||||
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
|
||||
long producerIndex;
|
||||
long consumerIndex;
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
|
||||
rx.internal.util.atomic.LinkedQueueNode producerNode;
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
|
||||
rx.internal.util.atomic.LinkedQueueNode consumerNode;
|
||||
}
|
||||
|
||||
-dontwarn okio.**
|
||||
-dontwarn javax.annotation.Nullable
|
||||
-dontwarn javax.annotation.ParametersAreNonnullByDefault
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
# fastjson
|
||||
-dontwarn com.alibaba.fastjson.**
|
||||
-keep class com.alibaba.fastjson.** { *; }
|
||||
-keepattributes Signature
|
||||
|
||||
# xpage
|
||||
-keep class com.xuexiang.xpage.annotation.** { *; }
|
||||
|
||||
# xaop
|
||||
-keep @com.xuexiang.xaop.annotation.* class * {*;}
|
||||
-keep @org.aspectj.lang.annotation.* class * {*;}
|
||||
-keep class * {
|
||||
@com.xuexiang.xaop.annotation.* <fields>;
|
||||
@org.aspectj.lang.annotation.* <fields>;
|
||||
}
|
||||
-keepclassmembers class * {
|
||||
@com.xuexiang.xaop.annotation.* <methods>;
|
||||
@org.aspectj.lang.annotation.* <methods>;
|
||||
}
|
||||
|
||||
# xrouter
|
||||
-keep public class com.xuexiang.xrouter.routes.**{*;}
|
||||
-keep class * implements com.xuexiang.xrouter.facade.template.ISyringe{*;}
|
||||
# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
|
||||
-keep interface * implements com.xuexiang.xrouter.facade.template.IProvider
|
||||
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
|
||||
-keep class * implements com.xuexiang.xrouter.facade.template.IProvider
|
||||
|
||||
# xupdate
|
||||
-keep class com.xuexiang.xupdate.entity.** { *; }
|
||||
|
||||
# xvideo
|
||||
-keep class com.xuexiang.xvideo.jniinterface.** { *; }
|
||||
|
||||
# xipc
|
||||
-keep @com.xuexiang.xipc.annotation.* class * {*;}
|
||||
-keep class * {
|
||||
@com.xuexiang.xipc.annotation.* <fields>;
|
||||
}
|
||||
-keepclassmembers class * {
|
||||
@com.xuexiang.xipc.annotation.* <methods>;
|
||||
}
|
||||
|
||||
# umeng统计
|
||||
-keep class com.umeng.** {*;}
|
||||
-keepclassmembers class * {
|
||||
public <init> (org.json.JSONObject);
|
||||
}
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class com.xuexiang.xui.widget.edittext.materialedittext.** { *; }
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.itrycn.myeasywol;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.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.getInstrumentation().getTargetContext();
|
||||
|
||||
assertEquals("com.itrycn.myeasywol", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
127
Client/android/MyEasyWOL/app/src/main/AndroidManifest.xml
Normal file
127
Client/android/MyEasyWOL/app/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.itrycn.myeasywol">
|
||||
|
||||
<!--进程杀死-->
|
||||
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<!-- 动态广播自定义权限 -->
|
||||
<uses-permission android:name="com.itrycn.myeasywol.permissions.RECEIVER" />
|
||||
<permission
|
||||
android:name="com.itrycn.myeasywol.permissions.RECEIVER"
|
||||
android:protectionLevel="signature" />
|
||||
<application
|
||||
android:name="com.itrycn.myeasywol.MyApp"
|
||||
android:allowBackup="false"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden"
|
||||
tools:ignore="LockedOrientationActivity"
|
||||
tools:targetApi="n">
|
||||
|
||||
<activity
|
||||
android:name="com.itrycn.myeasywol.activity.MainActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!--通用浏览器-->
|
||||
<activity
|
||||
android:name="com.itrycn.myeasywol.core.webview.AgentWebActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:hardwareAccelerated="true"
|
||||
android:label="@string/app_browser_name"
|
||||
android:theme="@style/AppTheme">
|
||||
<!-- Scheme -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="com.xuexiang.xui.applink" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:scheme="about" />
|
||||
<data android:scheme="javascript" />
|
||||
<!-- 设置自己的deeplink -->
|
||||
<!-- <data-->
|
||||
<!-- android:host="xxx.com"-->
|
||||
<!-- android:scheme="xui"/>-->
|
||||
</intent-filter>
|
||||
<!-- AppLink -->
|
||||
<intent-filter
|
||||
android:autoVerify="true"
|
||||
tools:targetApi="m">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:scheme="inline" />
|
||||
<data android:mimeType="text/html" />
|
||||
<data android:mimeType="text/plain" />
|
||||
<data android:mimeType="application/xhtml+xml" />
|
||||
<data android:mimeType="application/vnd.wap.xhtml+xml" />
|
||||
<!-- 设置自己的applink -->
|
||||
<!-- <data-->
|
||||
<!-- android:host="xxx.com"-->
|
||||
<!-- android:scheme="http"/>-->
|
||||
<!-- <data-->
|
||||
<!-- android:host="xxx.com"-->
|
||||
<!-- android:scheme="https"/>-->
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!--fragment的页面容器-->
|
||||
<activity
|
||||
android:name="com.itrycn.myeasywol.core.BaseActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
<!-- 版本更新提示-->
|
||||
<activity
|
||||
android:name="com.itrycn.myeasywol.utils.update.UpdateTipDialog"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/DialogTheme" />
|
||||
<!-- Webview拦截提示弹窗-->
|
||||
<activity
|
||||
android:name="com.itrycn.myeasywol.core.webview.WebViewInterceptDialog"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/DialogTheme" />
|
||||
<!-- applink的中转页面 -->
|
||||
<activity
|
||||
android:name="com.itrycn.myeasywol.core.XPageTransferActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
|
||||
<!--屏幕自适应设计图-->
|
||||
<meta-data
|
||||
android:name="design_width_in_dp"
|
||||
android:value="360" />
|
||||
<meta-data
|
||||
android:name="design_height_in_dp"
|
||||
android:value="640" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
21
Client/android/MyEasyWOL/app/src/main/assets/tips.json
Normal file
21
Client/android/MyEasyWOL/app/src/main/assets/tips.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"Code": 0,
|
||||
"Data": [
|
||||
{
|
||||
"title": "微信公众号",
|
||||
"content": "<a href=\"https://t.1yb.co/71xZ\">获取更多资讯内容,欢迎微信搜索公众号:「我的Android开源之旅」</a>"
|
||||
},
|
||||
{
|
||||
"title": "关于作者",
|
||||
"content": "点击关注作者,了解最新动态!<br /><a href=\"https://github.com/xuexiangjys\"><font color=\"#800080\">Github</font></a><br />\n<a href=\"https://www.zhihu.com/people/xuexiangjys/posts\"><font color=\"#0000FF\">知乎</font></a><br />\n<a href=\"https://juejin.im/user/598feef55188257d592e56ed/posts\"><font color=\"#000000\">掘金</font></a><br /><a href=\"https://www.jianshu.com/u/6bf605575337\"><font color=\"#FF0000\">简书</font></a><br />\n<a href=\"https://segmentfault.com/blog/openAndroidX\"><font color=\"#008000\">思否</font></a><br />\n<a href=\"https://space.bilibili.com/483850585/video\"><font color=\"#FFA500\">哔哩哔哩</font></a><br />\n<a href=\"https://www.toutiao.com/c/user/token/MS4wLjABAAAAqD0Pe01AhT2Hgi3w7HzboVuq57gntoAJJURwAkM3Elv0-EA9WSKUSy1DujIYLAEm/\"><font color=\"#FF0000\">今日头条</font></a>"
|
||||
},
|
||||
{
|
||||
"title": "赞助作者",
|
||||
"content": "你的打赏是我维护的动力,<a href=\"https://gitee.com/xuexiangjys/Resource/blob/master/doc/sponsor.md\"><font color=\"#800080\">点击此处支持我吧!</font></a>"
|
||||
},
|
||||
{
|
||||
"title": "QQ交流群",
|
||||
"content": "<a href=\"https://qm.qq.com/cgi-bin/qm/qr?k=i1rhgvRxlJRlJzigL0QemICtkk0H6g3J\">XUI开源交流1号群</a><br /><a href=\"https://qm.qq.com/cgi-bin/qm/qr?k=_0IhSCvLxdsgxAIBtTXr__bwsxZl4Eva\">XUI开源交流2号群</a><br /><a href=\"https://qm.qq.com/cgi-bin/qm/qr?k=GRVNTA4ehFuIUhQwqiZkjqYeQoxRBqCI\">AndroidGitHub开源交流群</a><br /><a href=\"https://qm.qq.com/cgi-bin/qm/qr?k=0OHp7jgMiF9SsfrzmOaxcauxMP9fZjc3\">XUpdate官方交流群</a>"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.multidex.MultiDex;
|
||||
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.utils.sdkinit.ANRWatchDogInit;
|
||||
import com.itrycn.myeasywol.utils.sdkinit.XBasicLibInit;
|
||||
import com.itrycn.myeasywol.utils.sdkinit.XUpdateInit;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2018/11/7 下午1:12
|
||||
*/
|
||||
public class MyApp extends Application {
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
//解决4.x运行崩溃的问题
|
||||
MultiDex.install(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
initLibs();
|
||||
initDB();
|
||||
}
|
||||
/**
|
||||
* 初始化数据库
|
||||
*/
|
||||
private void initDB() {
|
||||
DBHelper.getInstance(getApplicationContext());
|
||||
}
|
||||
/**
|
||||
* 初始化基础库
|
||||
*/
|
||||
private void initLibs() {
|
||||
XBasicLibInit.init(this);
|
||||
|
||||
XUpdateInit.init(this);
|
||||
XUpdateInit.checkUpdate(this,false);
|
||||
//运营统计数据运行时不初始化
|
||||
|
||||
//ANR监控
|
||||
ANRWatchDogInit.init();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return 当前app是否是调试开发模式
|
||||
*/
|
||||
public static boolean isDebug() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.activity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseActivity;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.fragment.AboutFragment;
|
||||
import com.itrycn.myeasywol.fragment.SettingsFragment;
|
||||
import com.itrycn.myeasywol.fragment.news.AddPCFragment;
|
||||
import com.itrycn.myeasywol.fragment.news.AddServerFragment;
|
||||
import com.itrycn.myeasywol.fragment.news.PCFragment;
|
||||
import com.itrycn.myeasywol.fragment.news.ServerViewFragment;
|
||||
import com.itrycn.myeasywol.fragment.news.WakePCFragment;
|
||||
import com.itrycn.myeasywol.fragment.profile.MsgCode;
|
||||
import com.itrycn.myeasywol.fragment.profile.ProfileFragment;
|
||||
import com.itrycn.myeasywol.utils.MyBroadcastReceiver;
|
||||
import com.itrycn.myeasywol.utils.Utils;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.core.CoreSwitchBean;
|
||||
import com.xuexiang.xui.adapter.FragmentAdapter;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.utils.ThemeUtils;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
import com.xuexiang.xutil.common.ClickUtils;
|
||||
import com.xuexiang.xutil.common.CollectionUtils;
|
||||
import com.xuexiang.xutil.display.Colors;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* 程序主页面,只是一个简单的Tab例子
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-07-07 23:53
|
||||
*/
|
||||
public class MainActivity extends BaseActivity implements View.OnClickListener, ViewPager.OnPageChangeListener, BottomNavigationView.OnNavigationItemSelectedListener, ClickUtils.OnClick2ExitListener, Toolbar.OnMenuItemClickListener {
|
||||
/**
|
||||
* 广播
|
||||
*/
|
||||
private MyBroadcastReceiver mBroadcastReceiver;
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
@BindView(R.id.view_pager)
|
||||
ViewPager viewPager;
|
||||
/**
|
||||
* 底部导航栏
|
||||
*/
|
||||
@BindView(R.id.bottom_navigation)
|
||||
BottomNavigationView bottomNavigation;
|
||||
/**
|
||||
* 侧边栏
|
||||
*/
|
||||
@BindView(R.id.nav_view)
|
||||
NavigationView navView;
|
||||
@BindView(R.id.drawer_layout)
|
||||
DrawerLayout drawerLayout;
|
||||
|
||||
private String[] mTitles;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_main;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
initViews();
|
||||
|
||||
initListeners();
|
||||
mBroadcastReceiver = new MyBroadcastReceiver();
|
||||
mBroadcastReceiver.setReceiverListener(new MyBroadcastReceiver.MyReceiverListener() {
|
||||
@Override
|
||||
public void onReceive(Context context, final Intent intent, final int code) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleAudioBroadcastReceiver(intent, code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleAudioBroadcastReceiver(Intent intent, int code) {
|
||||
switch (code) {
|
||||
case MsgCode.ACTION_CODE_EDIT_SERVER:
|
||||
Bundle initBundle = intent.getBundleExtra(MyBroadcastReceiver.ACTION_BUNDLEKEY);
|
||||
CoreSwitchBean page = new CoreSwitchBean(AddServerFragment.class)
|
||||
.setNewActivity(true);
|
||||
page.setBundle(initBundle);
|
||||
openPage(page);
|
||||
break;
|
||||
case MsgCode.ACTION_CODE_EDIT_PC:
|
||||
Bundle initBundle_PC = intent.getBundleExtra(MyBroadcastReceiver.ACTION_BUNDLEKEY);
|
||||
CoreSwitchBean page_PC = new CoreSwitchBean(AddPCFragment.class)
|
||||
.setNewActivity(true);
|
||||
page_PC.setBundle(initBundle_PC);
|
||||
openPage(page_PC);
|
||||
break;
|
||||
case MsgCode.ACTION_CODE_WAKE_PC:
|
||||
Bundle initBundle2 = intent.getBundleExtra(MyBroadcastReceiver.ACTION_BUNDLEKEY);
|
||||
CoreSwitchBean page2 = new CoreSwitchBean(WakePCFragment.class)
|
||||
.setNewActivity(true);
|
||||
page2.setBundle(initBundle2);
|
||||
openPage(page2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
mBroadcastReceiver.registerReceiver(getApplicationContext());
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mBroadcastReceiver != null) {
|
||||
mBroadcastReceiver.unregisterReceiver(getApplicationContext());
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
@Override
|
||||
protected boolean isSupportSlideBack() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
mTitles = ResUtils.getStringArray(R.array.home_titles);
|
||||
toolbar.setTitle(mTitles[0]);
|
||||
toolbar.inflateMenu(R.menu.menu_main);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
|
||||
initHeader();
|
||||
|
||||
//主页内容填充
|
||||
BaseFragment[] fragments = new BaseFragment[]{
|
||||
new PCFragment(),
|
||||
new ServerViewFragment(),
|
||||
new ProfileFragment()
|
||||
};
|
||||
FragmentAdapter<BaseFragment> adapter = new FragmentAdapter<>(getSupportFragmentManager(), fragments);
|
||||
viewPager.setOffscreenPageLimit(mTitles.length - 1);
|
||||
viewPager.setAdapter(adapter);
|
||||
|
||||
//GuideTipsDialog.showTips(this);
|
||||
}
|
||||
private void initHeader() {
|
||||
navView.setItemIconTintList(null);
|
||||
View headerView = navView.getHeaderView(0);
|
||||
LinearLayout navHeader = headerView.findViewById(R.id.nav_header);
|
||||
//RadiusImageView ivAvatar = headerView.findViewById(R.id.iv_avatar);
|
||||
TextView tvAvatar = headerView.findViewById(R.id.tv_avatar);
|
||||
TextView tvSign = headerView.findViewById(R.id.tv_sign);
|
||||
|
||||
if (Utils.isColorDark(ThemeUtils.resolveColor(this, R.attr.colorAccent))) {
|
||||
tvAvatar.setTextColor(Colors.WHITE);
|
||||
tvSign.setTextColor(Colors.WHITE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// ivAvatar.setImageTintList(ResUtils.getColors(R.color.xui_config_color_white));
|
||||
}
|
||||
} else {
|
||||
tvAvatar.setTextColor(ThemeUtils.resolveColor(this, R.attr.xui_config_color_title_text));
|
||||
tvSign.setTextColor(ThemeUtils.resolveColor(this, R.attr.xui_config_color_explain_text));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// ivAvatar.setImageTintList(ResUtils.getColors(R.color.xui_config_color_gray_3));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 2019-10-09 初始化数据
|
||||
//ivAvatar.setImageResource(R.drawable.ic_default_head);
|
||||
tvAvatar.setText(R.string.app_name);
|
||||
tvSign.setText("快速便捷的远程唤醒工具");
|
||||
navHeader.setOnClickListener(this);
|
||||
}
|
||||
|
||||
protected void initListeners() {
|
||||
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
||||
drawerLayout.addDrawerListener(toggle);
|
||||
toggle.syncState();
|
||||
|
||||
//侧边栏点击事件
|
||||
navView.setNavigationItemSelectedListener(menuItem -> {
|
||||
if (menuItem.isCheckable()) {
|
||||
drawerLayout.closeDrawers();
|
||||
return handleNavigationItemSelected(menuItem);
|
||||
} else {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.nav_settings:
|
||||
openNewPage(SettingsFragment.class);
|
||||
break;
|
||||
case R.id.nav_about:
|
||||
openNewPage(AboutFragment.class);
|
||||
break;
|
||||
default:
|
||||
XToastUtils.toast("点击了:" + menuItem.getTitle());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
//主页事件监听
|
||||
viewPager.addOnPageChangeListener(this);
|
||||
bottomNavigation.setOnNavigationItemSelectedListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理侧边栏点击事件
|
||||
*
|
||||
* @param menuItem
|
||||
* @return
|
||||
*/
|
||||
private boolean handleNavigationItemSelected(@NonNull MenuItem menuItem) {
|
||||
int index = CollectionUtils.arrayIndexOf(mTitles, menuItem.getTitle());
|
||||
if (index != -1) {
|
||||
toolbar.setTitle(menuItem.getTitle());
|
||||
viewPager.setCurrentItem(index, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_privacy:
|
||||
if(viewPager.getCurrentItem()!=1)
|
||||
{openNewPage(AddPCFragment.class);}
|
||||
else if(viewPager.getCurrentItem()==1)
|
||||
{openNewPage(AddServerFragment.class);}
|
||||
//Utils.showPrivacyDialog(this, null);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.nav_header:
|
||||
//XToastUtils.toast("点击头部!");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=============ViewPager===================//
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int i, float v, int i1) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
MenuItem item = bottomNavigation.getMenu().getItem(position);
|
||||
toolbar.setTitle(item.getTitle());
|
||||
item.setChecked(true);
|
||||
|
||||
updateSideNavStatus(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int i) {
|
||||
|
||||
}
|
||||
|
||||
//================Navigation================//
|
||||
|
||||
/**
|
||||
* 底部导航栏点击事件
|
||||
*
|
||||
* @param menuItem
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
|
||||
int index = CollectionUtils.arrayIndexOf(mTitles, menuItem.getTitle());
|
||||
if (index != -1) {
|
||||
toolbar.setTitle(menuItem.getTitle());
|
||||
viewPager.setCurrentItem(index, false);
|
||||
|
||||
updateSideNavStatus(menuItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新侧边栏菜单选中状态
|
||||
*
|
||||
* @param menuItem
|
||||
*/
|
||||
private void updateSideNavStatus(MenuItem menuItem) {
|
||||
MenuItem side = navView.getMenu().findItem(menuItem.getItemId());
|
||||
if (side != null) {
|
||||
side.setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单、返回键响应
|
||||
*/
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
ClickUtils.exitBy2Click(2000, this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRetry() {
|
||||
XToastUtils.toast("再按一次退出程序");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExit() {
|
||||
XUtil.exitApp();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.activity;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.utils.SettingUtils;
|
||||
import com.itrycn.myeasywol.utils.TokenUtils;
|
||||
import com.itrycn.myeasywol.utils.Utils;
|
||||
import com.xuexiang.xui.utils.KeyboardUtils;
|
||||
import com.xuexiang.xui.widget.activity.BaseSplashActivity;
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
|
||||
import me.jessyan.autosize.internal.CancelAdapt;
|
||||
|
||||
/**
|
||||
* 启动页【无需适配屏幕大小】
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-06-30 17:32
|
||||
*/
|
||||
public class SplashActivity extends BaseSplashActivity implements CancelAdapt {
|
||||
|
||||
@Override
|
||||
protected long getSplashDurationMillis() {
|
||||
return 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* activity启动后的初始化
|
||||
*/
|
||||
@Override
|
||||
protected void onCreateActivity() {
|
||||
initSplashView(R.drawable.xui_config_bg_splash);
|
||||
startSplash(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动页结束后的动作
|
||||
*/
|
||||
@Override
|
||||
protected void onSplashFinished() {
|
||||
if (SettingUtils.isAgreePrivacy()) {
|
||||
loginOrGoMainPage();
|
||||
} else {
|
||||
Utils.showPrivacyDialog(this, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
SettingUtils.setIsAgreePrivacy(true);
|
||||
loginOrGoMainPage();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void loginOrGoMainPage() {
|
||||
ActivityUtils.startActivity(MainActivity.class);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单、返回键响应
|
||||
*/
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.base.broccoli;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
import com.xuexiang.xui.adapter.recyclerview.XRecyclerAdapter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
/**
|
||||
* 使用Broccoli占位的基础适配器
|
||||
*
|
||||
* @author XUE
|
||||
* @since 2019/4/8 16:33
|
||||
*/
|
||||
public abstract class BroccoliRecyclerAdapter<T> extends BaseRecyclerAdapter<T> {
|
||||
/**
|
||||
* 是否已经加载成功
|
||||
*/
|
||||
private boolean mHasLoad = false;
|
||||
private Map<View, Broccoli> mBroccoliMap = new HashMap<>();
|
||||
|
||||
public BroccoliRecyclerAdapter(Collection<T> collection) {
|
||||
super(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindData(@NonNull RecyclerViewHolder holder, int position, T item) {
|
||||
Broccoli broccoli = mBroccoliMap.get(holder.itemView);
|
||||
if (broccoli == null) {
|
||||
broccoli = new Broccoli();
|
||||
mBroccoliMap.put(holder.itemView, broccoli);
|
||||
}
|
||||
if (mHasLoad) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
|
||||
onBindData(holder, item, position);
|
||||
} else {
|
||||
onBindBroccoli(holder, broccoli);
|
||||
broccoli.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定控件
|
||||
*
|
||||
* @param holder
|
||||
* @param model
|
||||
* @param position
|
||||
*/
|
||||
protected abstract void onBindData(RecyclerViewHolder holder, T model, int position);
|
||||
|
||||
/**
|
||||
* 绑定占位控件
|
||||
*
|
||||
* @param broccoli
|
||||
*/
|
||||
protected abstract void onBindBroccoli(RecyclerViewHolder holder, Broccoli broccoli);
|
||||
|
||||
@Override
|
||||
public XRecyclerAdapter refresh(Collection<T> collection) {
|
||||
mHasLoad = true;
|
||||
return super.refresh(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源释放,防止内存泄漏
|
||||
*/
|
||||
public void recycle() {
|
||||
for (Broccoli broccoli : mBroccoliMap.values()) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
}
|
||||
mBroccoliMap.clear();
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.base.broccoli;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.alibaba.android.vlayout.LayoutHelper;
|
||||
import com.itrycn.myeasywol.adapter.base.delegate.SimpleDelegateAdapter;
|
||||
import com.itrycn.myeasywol.adapter.base.delegate.XDelegateAdapter;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
/**
|
||||
* 使用Broccoli占位的基础适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2021/1/9 4:52 PM
|
||||
*/
|
||||
public abstract class BroccoliSimpleDelegateAdapter<T> extends SimpleDelegateAdapter<T> {
|
||||
|
||||
/**
|
||||
* 是否已经加载成功
|
||||
*/
|
||||
private boolean mHasLoad = false;
|
||||
private Map<View, Broccoli> mBroccoliMap = new HashMap<>();
|
||||
|
||||
public BroccoliSimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper) {
|
||||
super(layoutId, layoutHelper);
|
||||
}
|
||||
|
||||
public BroccoliSimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, Collection<T> list) {
|
||||
super(layoutId, layoutHelper, list);
|
||||
}
|
||||
|
||||
public BroccoliSimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, T[] data) {
|
||||
super(layoutId, layoutHelper, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindData(@NonNull RecyclerViewHolder holder, int position, T item) {
|
||||
Broccoli broccoli = mBroccoliMap.get(holder.itemView);
|
||||
if (broccoli == null) {
|
||||
broccoli = new Broccoli();
|
||||
mBroccoliMap.put(holder.itemView, broccoli);
|
||||
}
|
||||
if (mHasLoad) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
|
||||
onBindData(holder, item, position);
|
||||
} else {
|
||||
onBindBroccoli(holder, broccoli);
|
||||
broccoli.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 绑定控件
|
||||
*
|
||||
* @param holder
|
||||
* @param model
|
||||
* @param position
|
||||
*/
|
||||
protected abstract void onBindData(RecyclerViewHolder holder, T model, int position);
|
||||
|
||||
/**
|
||||
* 绑定占位控件
|
||||
*
|
||||
* @param holder
|
||||
* @param broccoli
|
||||
*/
|
||||
protected abstract void onBindBroccoli(RecyclerViewHolder holder, Broccoli broccoli);
|
||||
|
||||
@Override
|
||||
public XDelegateAdapter refresh(Collection<T> collection) {
|
||||
mHasLoad = true;
|
||||
return super.refresh(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源释放,防止内存泄漏
|
||||
*/
|
||||
public void recycle() {
|
||||
for (Broccoli broccoli : mBroccoliMap.values()) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
}
|
||||
mBroccoliMap.clear();
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.base.delegate;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 通用的DelegateAdapter适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 12:44 AM
|
||||
*/
|
||||
public abstract class BaseDelegateAdapter<T> extends XDelegateAdapter<T, RecyclerViewHolder> {
|
||||
|
||||
public BaseDelegateAdapter() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BaseDelegateAdapter(Collection<T> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
public BaseDelegateAdapter(T[] data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 适配的布局
|
||||
*
|
||||
* @param viewType
|
||||
* @return
|
||||
*/
|
||||
protected abstract int getItemLayoutId(int viewType);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected RecyclerViewHolder getViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new RecyclerViewHolder(inflateView(parent, getItemLayoutId(viewType)));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.base.delegate;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
import com.scwang.smartrefresh.layout.adapter.SmartRecyclerAdapter;
|
||||
import com.scwang.smartrefresh.layout.adapter.SmartViewHolder;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ServerRecyclerAdapter extends SmartRecyclerAdapter<ServerInfo> {
|
||||
public ServerRecyclerAdapter() {
|
||||
super(R.layout.adapter_item_simple_list_1);
|
||||
}
|
||||
|
||||
public ServerRecyclerAdapter(Collection<ServerInfo> data) {
|
||||
super(data, R.layout.adapter_item_simple_list_1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定布局控件
|
||||
*
|
||||
* @param holder
|
||||
* @param model
|
||||
* @param position
|
||||
*/
|
||||
@Override
|
||||
protected void onBindViewHolder(SmartViewHolder holder, ServerInfo model, int position) {
|
||||
holder.text(R.id.tv_title, model.getName());
|
||||
//holder.text(android.R.id.text2,model.getName());
|
||||
//holder.textColorId(android.R.id.text2, R.color.xui_config_color_light_blue_gray);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.base.delegate;
|
||||
|
||||
import com.alibaba.android.vlayout.LayoutHelper;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 简易DelegateAdapter适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 12:55 AM
|
||||
*/
|
||||
public abstract class SimpleDelegateAdapter<T> extends BaseDelegateAdapter<T> {
|
||||
|
||||
private int mLayoutId;
|
||||
|
||||
private LayoutHelper mLayoutHelper;
|
||||
|
||||
public SimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper) {
|
||||
super();
|
||||
mLayoutId = layoutId;
|
||||
mLayoutHelper = layoutHelper;
|
||||
}
|
||||
|
||||
public SimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, Collection<T> list) {
|
||||
super(list);
|
||||
mLayoutId = layoutId;
|
||||
mLayoutHelper = layoutHelper;
|
||||
}
|
||||
|
||||
public SimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, T[] data) {
|
||||
super(data);
|
||||
mLayoutId = layoutId;
|
||||
mLayoutHelper = layoutHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemLayoutId(int viewType) {
|
||||
return mLayoutId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LayoutHelper onCreateLayoutHelper() {
|
||||
return mLayoutHelper;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.base.delegate;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
import com.alibaba.android.vlayout.LayoutHelper;
|
||||
import com.alibaba.android.vlayout.layout.SingleLayoutHelper;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
|
||||
/**
|
||||
* 单独布局的DelegateAdapter
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 1:04 AM
|
||||
*/
|
||||
public abstract class SingleDelegateAdapter extends DelegateAdapter.Adapter<RecyclerViewHolder> {
|
||||
|
||||
private int mLayoutId;
|
||||
|
||||
public SingleDelegateAdapter(int layoutId) {
|
||||
mLayoutId = layoutId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutHelper onCreateLayoutHelper() {
|
||||
return new SingleLayoutHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载布局获取控件
|
||||
*
|
||||
* @param parent 父布局
|
||||
* @param layoutId 布局ID
|
||||
* @return
|
||||
*/
|
||||
protected View inflateView(ViewGroup parent, @LayoutRes int layoutId) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new RecyclerViewHolder(inflateView(parent, mLayoutId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.base.delegate;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基础DelegateAdapter
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 12:17 AM
|
||||
*/
|
||||
public abstract class XDelegateAdapter<T, V extends RecyclerView.ViewHolder> extends DelegateAdapter.Adapter<V> {
|
||||
/**
|
||||
* 数据源
|
||||
*/
|
||||
protected final List<T> mData = new ArrayList<>();
|
||||
/**
|
||||
* 当前点击的条目
|
||||
*/
|
||||
protected int mSelectPosition = -1;
|
||||
|
||||
public XDelegateAdapter() {
|
||||
|
||||
}
|
||||
|
||||
public XDelegateAdapter(Collection<T> list) {
|
||||
if (list != null) {
|
||||
mData.addAll(list);
|
||||
}
|
||||
}
|
||||
|
||||
public XDelegateAdapter(T[] data) {
|
||||
if (data != null && data.length > 0) {
|
||||
mData.addAll(Arrays.asList(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建自定义的ViewHolder
|
||||
*
|
||||
* @param parent
|
||||
* @param viewType
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
protected abstract V getViewHolder(@NonNull ViewGroup parent, int viewType);
|
||||
|
||||
/**
|
||||
* 绑定数据
|
||||
*
|
||||
* @param holder
|
||||
* @param position 索引
|
||||
* @param item 列表项
|
||||
*/
|
||||
protected abstract void bindData(@NonNull V holder, int position, T item);
|
||||
|
||||
/**
|
||||
* 加载布局获取控件
|
||||
*
|
||||
* @param parent 父布局
|
||||
* @param layoutId 布局ID
|
||||
* @return
|
||||
*/
|
||||
protected View inflateView(ViewGroup parent, @LayoutRes int layoutId) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public V onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return getViewHolder(parent, viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull V holder, int position) {
|
||||
bindData(holder, position, mData.get(position));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表项
|
||||
*
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
public T getItem(int position) {
|
||||
return checkPosition(position) ? mData.get(position) : null;
|
||||
}
|
||||
|
||||
private boolean checkPosition(int position) {
|
||||
return position >= 0 && position <= mData.size() - 1;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return getItemCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mData.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 数据源
|
||||
*/
|
||||
public List<T> getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定位置添加一项
|
||||
*
|
||||
* @param pos
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter add(int pos, T item) {
|
||||
mData.add(pos, item);
|
||||
notifyItemInserted(pos);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在列表末端增加一项
|
||||
*
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter add(T item) {
|
||||
mData.add(item);
|
||||
notifyItemInserted(mData.size() - 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除列表中指定索引的数据
|
||||
*
|
||||
* @param pos
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter delete(int pos) {
|
||||
mData.remove(pos);
|
||||
notifyItemRemoved(pos);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表中指定位置的数据
|
||||
*
|
||||
* @param pos
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter refresh(int pos, T item) {
|
||||
mData.set(pos, item);
|
||||
notifyItemChanged(pos);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表数据
|
||||
*
|
||||
* @param collection
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter refresh(Collection<T> collection) {
|
||||
if (collection != null) {
|
||||
mData.clear();
|
||||
mData.addAll(collection);
|
||||
mSelectPosition = -1;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表数据
|
||||
*
|
||||
* @param array
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter refresh(T[] array) {
|
||||
if (array != null && array.length > 0) {
|
||||
mData.clear();
|
||||
mData.addAll(Arrays.asList(array));
|
||||
mSelectPosition = -1;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载更多
|
||||
*
|
||||
* @param collection
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter loadMore(Collection<T> collection) {
|
||||
if (collection != null) {
|
||||
mData.addAll(collection);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载更多
|
||||
*
|
||||
* @param array
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter loadMore(T[] array) {
|
||||
if (array != null && array.length > 0) {
|
||||
mData.addAll(Arrays.asList(array));
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个
|
||||
*
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter load(T item) {
|
||||
if (item != null) {
|
||||
mData.add(item);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 当前列表的选中项
|
||||
*/
|
||||
public int getSelectPosition() {
|
||||
return mSelectPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前列表的选中项
|
||||
*
|
||||
* @param selectPosition
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter setSelectPosition(int selectPosition) {
|
||||
mSelectPosition = selectPosition;
|
||||
notifyDataSetChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前列表选中项
|
||||
*
|
||||
* @return 当前列表选中项
|
||||
*/
|
||||
public T getSelectItem() {
|
||||
return getItem(mSelectPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除数据
|
||||
*/
|
||||
public void clear() {
|
||||
if (!isEmpty()) {
|
||||
mData.clear();
|
||||
mSelectPosition = -1;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.adapter.entity;
|
||||
|
||||
/**
|
||||
* 新闻信息
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/4/7 下午12:07
|
||||
*/
|
||||
public class NewInfo {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String UserName = "xuexiangjys";
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
private String Tag;
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String Title;
|
||||
/**
|
||||
* 摘要
|
||||
*/
|
||||
private String Summary;
|
||||
|
||||
/**
|
||||
* 图片
|
||||
*/
|
||||
private String ImageUrl;
|
||||
/**
|
||||
* 点赞数
|
||||
*/
|
||||
private int Praise;
|
||||
/**
|
||||
* 评论数
|
||||
*/
|
||||
private int Comment;
|
||||
/**
|
||||
* 阅读量
|
||||
*/
|
||||
private int Read;
|
||||
/**
|
||||
* 新闻的详情地址
|
||||
*/
|
||||
private String DetailUrl;
|
||||
|
||||
|
||||
public NewInfo() {
|
||||
|
||||
}
|
||||
|
||||
public NewInfo(String userName, String tag, String title, String summary, String imageUrl, int praise, int comment, int read, String detailUrl) {
|
||||
UserName = userName;
|
||||
Tag = tag;
|
||||
Title = title;
|
||||
Summary = summary;
|
||||
ImageUrl = imageUrl;
|
||||
Praise = praise;
|
||||
Comment = comment;
|
||||
Read = read;
|
||||
DetailUrl = detailUrl;
|
||||
}
|
||||
|
||||
|
||||
public NewInfo(String tag, String title, String summary, String imageUrl, String detailUrl) {
|
||||
Tag = tag;
|
||||
Title = title;
|
||||
Summary = summary;
|
||||
ImageUrl = imageUrl;
|
||||
DetailUrl = detailUrl;
|
||||
}
|
||||
|
||||
|
||||
public NewInfo(String tag, String title) {
|
||||
Tag = tag;
|
||||
Title = title;
|
||||
|
||||
Praise = (int) (Math.random() * 100 + 5);
|
||||
Comment = (int) (Math.random() * 50 + 5);
|
||||
Read = (int) (Math.random() * 500 + 50);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getUserName() {
|
||||
return UserName;
|
||||
}
|
||||
|
||||
public NewInfo setUserName(String userName) {
|
||||
UserName = userName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return Tag;
|
||||
}
|
||||
|
||||
public NewInfo setTag(String tag) {
|
||||
Tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return Title;
|
||||
}
|
||||
|
||||
public NewInfo setTitle(String title) {
|
||||
Title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return Summary;
|
||||
}
|
||||
|
||||
public NewInfo setSummary(String summary) {
|
||||
Summary = summary;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getImageUrl() {
|
||||
return ImageUrl;
|
||||
}
|
||||
|
||||
public NewInfo setImageUrl(String imageUrl) {
|
||||
ImageUrl = imageUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getPraise() {
|
||||
return Praise;
|
||||
}
|
||||
|
||||
public NewInfo setPraise(int praise) {
|
||||
Praise = praise;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getComment() {
|
||||
return Comment;
|
||||
}
|
||||
|
||||
public NewInfo setComment(int comment) {
|
||||
Comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRead() {
|
||||
return Read;
|
||||
}
|
||||
|
||||
public NewInfo setRead(int read) {
|
||||
Read = read;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getDetailUrl() {
|
||||
return DetailUrl;
|
||||
}
|
||||
|
||||
public NewInfo setDetailUrl(String detailUrl) {
|
||||
DetailUrl = detailUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NewInfo{" +
|
||||
"UserName='" + UserName + '\'' +
|
||||
", Tag='" + Tag + '\'' +
|
||||
", Title='" + Title + '\'' +
|
||||
", Summary='" + Summary + '\'' +
|
||||
", ImageUrl='" + ImageUrl + '\'' +
|
||||
", Praise=" + Praise +
|
||||
", Comment=" + Comment +
|
||||
", Read=" + Read +
|
||||
", DetailUrl='" + DetailUrl + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.core.CoreSwitchBean;
|
||||
import com.xuexiang.xrouter.facade.service.SerializationService;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.widget.slideback.SlideBack;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
import io.github.inflationx.viewpump.ViewPumpContextWrapper;
|
||||
|
||||
/**
|
||||
* 基础容器Activity
|
||||
*
|
||||
* @author XUE
|
||||
* @since 2019/3/22 11:21
|
||||
*/
|
||||
public class BaseActivity extends XPageActivity {
|
||||
|
||||
Unbinder mUnbinder;
|
||||
/**
|
||||
* 处理ui任务
|
||||
*/
|
||||
public WeakRefHandler mUIHandler;
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context newBase) {
|
||||
//注入字体
|
||||
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持侧滑返回
|
||||
*/
|
||||
public static final String KEY_SUPPORT_SLIDE_BACK = "key_support_slide_back";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
initStatusBarStyle();
|
||||
super.onCreate(savedInstanceState);
|
||||
mUnbinder = ButterKnife.bind(this);
|
||||
//创建ui handler
|
||||
mUIHandler = new WeakRefHandler(Looper.getMainLooper(), this, new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
registerSlideBack();
|
||||
}
|
||||
/**
|
||||
* 初始化状态栏的样式
|
||||
*/
|
||||
protected void initStatusBarStyle() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开fragment
|
||||
*
|
||||
* @param clazz 页面类
|
||||
* @param addToBackStack 是否添加到栈中
|
||||
* @return 打开的fragment对象
|
||||
*/
|
||||
public <T extends XPageFragment> T openPage(Class<T> clazz, boolean addToBackStack) {
|
||||
CoreSwitchBean page = new CoreSwitchBean(clazz)
|
||||
.setAddToBackStack(addToBackStack);
|
||||
return (T) openPage(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开fragment
|
||||
*
|
||||
* @return 打开的fragment对象
|
||||
*/
|
||||
public <T extends XPageFragment> T openNewPage(Class<T> clazz) {
|
||||
CoreSwitchBean page = new CoreSwitchBean(clazz)
|
||||
.setNewActivity(true);
|
||||
return (T) openPage(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换fragment
|
||||
*
|
||||
* @param clazz 页面类
|
||||
* @return 打开的fragment对象
|
||||
*/
|
||||
public <T extends XPageFragment> T switchPage(Class<T> clazz) {
|
||||
return openPage(clazz, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public String serializeObject(Object object) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRelease() {
|
||||
mUnbinder.unbind();
|
||||
//移除队列任务
|
||||
if (mUIHandler != null) {
|
||||
mUIHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
unregisterSlideBack();
|
||||
super.onRelease();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册侧滑回调
|
||||
*/
|
||||
protected void registerSlideBack() {
|
||||
if (isSupportSlideBack()) {
|
||||
SlideBack.with(this)
|
||||
.haveScroll(true)
|
||||
.edgeMode(ResUtils.isRtl() ? SlideBack.EDGE_RIGHT : SlideBack.EDGE_LEFT)
|
||||
.callBack(this::popPage)
|
||||
.register();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销侧滑回调
|
||||
*/
|
||||
protected void unregisterSlideBack() {
|
||||
if (isSupportSlideBack()) {
|
||||
SlideBack.unregister(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 是否支持侧滑返回
|
||||
*/
|
||||
protected boolean isSupportSlideBack() {
|
||||
CoreSwitchBean page = getIntent().getParcelableExtra(CoreSwitchBean.KEY_SWITCH_BEAN);
|
||||
return page == null || page.getBundle() == null || page.getBundle().getBoolean(KEY_SUPPORT_SLIDE_BACK, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.base.XPageContainerListFragment;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.itrycn.myeasywol.core.SimpleListAdapter.KEY_SUB_TITLE;
|
||||
import static com.itrycn.myeasywol.core.SimpleListAdapter.KEY_TITLE;
|
||||
|
||||
/**
|
||||
* 修改列表样式为主副标题显示
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/11/22 上午11:26
|
||||
*/
|
||||
public abstract class BaseContainerFragment extends XPageContainerListFragment {
|
||||
|
||||
@Override
|
||||
protected void initPage() {
|
||||
initTitle();
|
||||
initViews();
|
||||
initListeners();
|
||||
}
|
||||
|
||||
protected TitleBar initTitle() {
|
||||
return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
popToBack();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
mSimpleData = initSimpleData(mSimpleData);
|
||||
|
||||
List<Map<String, String>> data = new ArrayList<>();
|
||||
for (String content : mSimpleData) {
|
||||
Map<String, String> item = new HashMap<>();
|
||||
int index = content.indexOf("\n");
|
||||
if (index > 0) {
|
||||
item.put(KEY_TITLE, String.valueOf(content.subSequence(0, index)));
|
||||
item.put(KEY_SUB_TITLE, String.valueOf(content.subSequence(index + 1, content.length())));
|
||||
} else {
|
||||
item.put(KEY_TITLE, content);
|
||||
item.put(KEY_SUB_TITLE, "");
|
||||
}
|
||||
data.add(item);
|
||||
}
|
||||
|
||||
getListView().setAdapter(new SimpleListAdapter(getContext(), data));
|
||||
initSimply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
|
||||
onItemClick(view, position);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
private void onItemClick(View view, int position) {
|
||||
onItemClick(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
getListView().setOnItemClickListener(null);
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
//屏幕旋转时刷新一下title
|
||||
super.onConfigurationChanged(newConfig);
|
||||
ViewGroup root = (ViewGroup) getRootView();
|
||||
if (root.getChildAt(0) instanceof TitleBar) {
|
||||
root.removeViewAt(0);
|
||||
initTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,400 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Process;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.itrycn.myeasywol.core.http.loader.ProgressLoader;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xpage.utils.Utils;
|
||||
import com.xuexiang.xrouter.facade.service.SerializationService;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 基础fragment
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/5/25 下午3:44
|
||||
*/
|
||||
public abstract class BaseFragment extends XPageFragment {
|
||||
|
||||
private IProgressLoader mIProgressLoader;
|
||||
/**
|
||||
* 处理ui任务
|
||||
*/
|
||||
public WeakRefHandler mUIHandler;
|
||||
/**
|
||||
* 子线程用于执行耗时任务
|
||||
*/
|
||||
public WeakRefHandler mWorkerHandler;
|
||||
//创建异步HandlerThread
|
||||
private HandlerThread mHandlerThread;
|
||||
@Override
|
||||
protected void initPage() {
|
||||
initTitle();
|
||||
initViews();
|
||||
initListeners();
|
||||
//创建ui handler
|
||||
mUIHandler = new WeakRefHandler(Looper.getMainLooper(), this, new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
handleUIMessage(msg);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
//创建异步HandlerThread
|
||||
mHandlerThread = new HandlerThread("loadFragmentData", Process.THREAD_PRIORITY_BACKGROUND);
|
||||
//必须先开启线程
|
||||
mHandlerThread.start();
|
||||
//子线程Handler
|
||||
mWorkerHandler = new WeakRefHandler(mHandlerThread.getLooper(), this, new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
handleWorkerMessage(msg);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 处理UI线程worker
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
protected abstract void handleUIMessage(Message msg);
|
||||
/**
|
||||
* 处理子线程worker
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
protected abstract void handleWorkerMessage(Message msg);
|
||||
protected TitleBar initTitle() {
|
||||
return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), v -> popToBack());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进度条加载者
|
||||
*
|
||||
* @return 进度条加载者
|
||||
*/
|
||||
public IProgressLoader getProgressLoader() {
|
||||
if (mIProgressLoader == null) {
|
||||
mIProgressLoader = ProgressLoader.create(getContext());
|
||||
}
|
||||
return mIProgressLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进度条加载者
|
||||
*
|
||||
* @param message
|
||||
* @return 进度条加载者
|
||||
*/
|
||||
public IProgressLoader getProgressLoader(String message) {
|
||||
if (mIProgressLoader == null) {
|
||||
mIProgressLoader = ProgressLoader.create(getContext(), message);
|
||||
} else {
|
||||
mIProgressLoader.updateMessage(message);
|
||||
}
|
||||
return mIProgressLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
//屏幕旋转时刷新一下title
|
||||
super.onConfigurationChanged(newConfig);
|
||||
ViewGroup root = (ViewGroup) getRootView();
|
||||
if (root.getChildAt(0) instanceof TitleBar) {
|
||||
root.removeViewAt(0);
|
||||
initTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mIProgressLoader != null) {
|
||||
mIProgressLoader.dismissLoading();
|
||||
}
|
||||
//移除队列任务
|
||||
if (mUIHandler != null) {
|
||||
mUIHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
//移除队列任务
|
||||
if (mWorkerHandler != null) {
|
||||
mWorkerHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
|
||||
//关闭线程
|
||||
if (mHandlerThread != null)
|
||||
mHandlerThread.quit();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
//==============================页面跳转api===================================//
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param pageName 页面名
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(String pageName) {
|
||||
return new PageOption(pageName)
|
||||
.setAnim(CoreAnim.slide)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param containActivityClazz 页面容器
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, @NonNull Class<? extends XPageActivity> containActivityClazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.setContainActivityClazz(containActivityClazz)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setNewActivity(true);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
public Fragment openPage(PageOption option, String key, Object value) {
|
||||
if (value instanceof Integer) {
|
||||
option.putInt(key, (Integer) value);
|
||||
} else if (value instanceof Float) {
|
||||
option.putFloat(key, (Float) value);
|
||||
} else if (value instanceof String) {
|
||||
option.putString(key, (String) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
option.putBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Long) {
|
||||
option.putLong(key, (Long) value);
|
||||
} else if (value instanceof Double) {
|
||||
option.putDouble(key, (Double) value);
|
||||
} else if (value instanceof Parcelable) {
|
||||
option.putParcelable(key, (Parcelable) value);
|
||||
} else if (value instanceof Serializable) {
|
||||
option.putSerializable(key, (Serializable) value);
|
||||
} else {
|
||||
option.putString(key, serializeObject(value));
|
||||
}
|
||||
return option.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.setAddToBackStack(addToBackStack)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, Object value) {
|
||||
return openPage(clazz, true, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setAddToBackStack(addToBackStack);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, Object value, int requestCode) {
|
||||
PageOption option = new PageOption(clazz).setRequestCode(requestCode);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, String value, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象
|
||||
*
|
||||
* @param object 需要序列化的对象
|
||||
* @return 序列化结果
|
||||
*/
|
||||
public String serializeObject(Object object) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化对象
|
||||
*
|
||||
* @param input 反序列化的内容
|
||||
* @param clazz 类型
|
||||
* @return 反序列化结果
|
||||
*/
|
||||
public <T> T deserializeObject(String input, Type clazz) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).parseObject(input, clazz);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void hideCurrentPageSoftInput() {
|
||||
if (getActivity() == null) {
|
||||
return;
|
||||
}
|
||||
// 记住,要在xml的父布局加上android:focusable="true" 和 android:focusableInTouchMode="true"
|
||||
Utils.hideSoftInputClearFocus(getActivity().getCurrentFocus());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Parcelable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.base.XPageSimpleListFragment;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xrouter.facade.service.SerializationService;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2018/12/29 下午12:41
|
||||
*/
|
||||
public abstract class BaseSimpleListFragment extends XPageSimpleListFragment {
|
||||
|
||||
@Override
|
||||
protected void initPage() {
|
||||
initTitle();
|
||||
initViews();
|
||||
initListeners();
|
||||
}
|
||||
|
||||
protected TitleBar initTitle() {
|
||||
return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
popToBack();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
//屏幕旋转时刷新一下title
|
||||
super.onConfigurationChanged(newConfig);
|
||||
ViewGroup root = (ViewGroup) getRootView();
|
||||
if (root.getChildAt(0) instanceof TitleBar) {
|
||||
root.removeViewAt(0);
|
||||
initTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
//==============================页面跳转api===================================//
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param pageName 页面名
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(String pageName) {
|
||||
return new PageOption(pageName)
|
||||
.setAnim(CoreAnim.slide)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param containActivityClazz 页面容器
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, @NonNull Class<? extends XPageActivity> containActivityClazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.setContainActivityClazz(containActivityClazz)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setNewActivity(true);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
public Fragment openPage(PageOption option, String key, Object value) {
|
||||
if (value instanceof Integer) {
|
||||
option.putInt(key, (Integer) value);
|
||||
} else if (value instanceof Float) {
|
||||
option.putFloat(key, (Float) value);
|
||||
} else if (value instanceof String) {
|
||||
option.putString(key, (String) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
option.putBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Long) {
|
||||
option.putLong(key, (Long) value);
|
||||
} else if (value instanceof Double) {
|
||||
option.putDouble(key, (Double) value);
|
||||
} else if (value instanceof Parcelable) {
|
||||
option.putParcelable(key, (Parcelable) value);
|
||||
} else if (value instanceof Serializable) {
|
||||
option.putSerializable(key, (Serializable) value);
|
||||
} else {
|
||||
option.putString(key, serializeObject(value));
|
||||
}
|
||||
return option.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.setAddToBackStack(addToBackStack)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, Object value) {
|
||||
return openPage(clazz, true, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setAddToBackStack(addToBackStack);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, Object value, int requestCode) {
|
||||
PageOption option = new PageOption(clazz).setRequestCode(requestCode);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, String value, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象
|
||||
*
|
||||
* @param object 需要序列化的对象
|
||||
* @return 序列化结果
|
||||
*/
|
||||
public String serializeObject(Object object) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.xuexiang.xui.adapter.listview.BaseListAdapter;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 主副标题显示适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/12/19 上午12:19
|
||||
*/
|
||||
public class SimpleListAdapter extends BaseListAdapter<Map<String, String>, SimpleListAdapter.ViewHolder> {
|
||||
|
||||
public static final String KEY_TITLE = "key_title";
|
||||
public static final String KEY_SUB_TITLE = "key_sub_title";
|
||||
|
||||
public SimpleListAdapter(Context context, List<Map<String, String>> data) {
|
||||
super(context, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewHolder newViewHolder(View convertView) {
|
||||
ViewHolder holder = new ViewHolder();
|
||||
holder.mTvTitle = convertView.findViewById(R.id.tv_title);
|
||||
holder.mTvSubTitle = convertView.findViewById(R.id.tv_sub_title);
|
||||
return holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.adapter_item_simple_list_2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void convert(ViewHolder holder, Map<String, String> item, int position) {
|
||||
holder.mTvTitle.setText(item.get(KEY_TITLE));
|
||||
if (!StringUtils.isEmpty(item.get(KEY_SUB_TITLE))) {
|
||||
holder.mTvSubTitle.setText(item.get(KEY_SUB_TITLE));
|
||||
holder.mTvSubTitle.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.mTvSubTitle.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ViewHolder {
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
public TextView mTvTitle;
|
||||
/**
|
||||
* 副标题
|
||||
*/
|
||||
public TextView mTvSubTitle;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Created by zhangliangming on 2018-08-23.
|
||||
*/
|
||||
public class WeakRefHandler<T> extends Handler {
|
||||
private WeakReference<T> mWeakReference;
|
||||
private Callback mCallback;
|
||||
|
||||
public WeakRefHandler(Looper looper, T t, Callback callback) {
|
||||
super(looper);
|
||||
mCallback = callback;
|
||||
mWeakReference = new WeakReference<>(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (isAlive() && mCallback != null) {
|
||||
mCallback.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否还存活
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isAlive() {
|
||||
T t = mWeakReference.get();
|
||||
return t != null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xrouter.annotation.AutoWired;
|
||||
import com.xuexiang.xrouter.annotation.Router;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
|
||||
/**
|
||||
* https://xuexiangjys.club/xpage/transfer?pageName=xxxxx&....
|
||||
* applink的中转
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-07-06 9:37
|
||||
*/
|
||||
@Router(path = "/xpage/transfer")
|
||||
public class XPageTransferActivity extends BaseActivity {
|
||||
|
||||
@AutoWired(name = "pageName")
|
||||
String pageName;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
XRouter.getInstance().inject(this);
|
||||
|
||||
if (!StringUtils.isEmpty(pageName)) {
|
||||
if (openPage(pageName, getIntent().getExtras()) == null) {
|
||||
XToastUtils.error("页面未找到!");
|
||||
finish();
|
||||
}
|
||||
} else {
|
||||
XToastUtils.error("页面未找到!");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.api;
|
||||
|
||||
import com.itrycn.myeasywol.core.http.entity.TipInfo;
|
||||
import com.xuexiang.xhttp2.model.ApiResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.GET;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2021/1/9 7:01 PM
|
||||
*/
|
||||
public class ApiService {
|
||||
|
||||
/**
|
||||
* 使用的是retrofit的接口定义
|
||||
*/
|
||||
public interface IGetService {
|
||||
|
||||
/**
|
||||
* 获得小贴士
|
||||
*/
|
||||
@GET("/xuexiangjys/Resource/raw/master/jsonapi/tips.json")
|
||||
Observable<ApiResult<List<TipInfo>>> getTips();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.callback;
|
||||
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 不带错误提示的网络请求回调
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:02
|
||||
*/
|
||||
public abstract class NoTipCallBack<T> extends SimpleCallBack<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public NoTipCallBack() {
|
||||
|
||||
}
|
||||
|
||||
public NoTipCallBack(XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public NoTipCallBack(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.callback;
|
||||
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示的网络请求回调
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:02
|
||||
*/
|
||||
public abstract class TipCallBack<T> extends SimpleCallBack<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipCallBack() {
|
||||
|
||||
}
|
||||
|
||||
public TipCallBack(XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public TipCallBack(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.callback;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.callback.ProgressLoadingCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示和加载进度条的网络请求回调
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:16
|
||||
*/
|
||||
public abstract class TipProgressLoadingCallBack<T> extends ProgressLoadingCallBack<T> {
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipProgressLoadingCallBack(BaseFragment fragment) {
|
||||
super(fragment.getProgressLoader());
|
||||
}
|
||||
|
||||
public TipProgressLoadingCallBack(IProgressLoader iProgressLoader) {
|
||||
super(iProgressLoader);
|
||||
}
|
||||
|
||||
public TipProgressLoadingCallBack(@NonNull XHttpRequest req, IProgressLoader iProgressLoader) {
|
||||
this(req.getUrl(), iProgressLoader);
|
||||
}
|
||||
|
||||
public TipProgressLoadingCallBack(String url, IProgressLoader iProgressLoader) {
|
||||
super(iProgressLoader);
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
super.onError(e);
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.itrycn.myeasywol.core.http.entity;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2019-08-28 15:35
|
||||
*/
|
||||
@Keep
|
||||
public class TipInfo {
|
||||
|
||||
/**
|
||||
* title : 小贴士3
|
||||
* content : <p style=";font-family:'Microsoft YaHei';font-size:15px">欢迎关注我的微信公众号:我的Android开源之旅。</p><p><br/></p>
|
||||
*/
|
||||
|
||||
private String title;
|
||||
private String content;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TipInfo{" +
|
||||
"title='" + title + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
|
||||
/**
|
||||
* IProgressLoader的创建工厂实现接口
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:17
|
||||
*/
|
||||
public interface IProgressLoaderFactory {
|
||||
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
IProgressLoader create(Context context);
|
||||
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @param message 默认提示
|
||||
* @return
|
||||
*/
|
||||
IProgressLoader create(Context context, String message);
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.OnProgressCancelListener;
|
||||
import com.xuexiang.xui.widget.dialog.MiniLoadingDialog;
|
||||
|
||||
/**
|
||||
* 默认进度加载
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:07
|
||||
*/
|
||||
public class MiniLoadingDialogLoader implements IProgressLoader {
|
||||
/**
|
||||
* 进度loading弹窗
|
||||
*/
|
||||
private MiniLoadingDialog mDialog;
|
||||
/**
|
||||
* 进度框取消监听
|
||||
*/
|
||||
private OnProgressCancelListener mOnProgressCancelListener;
|
||||
|
||||
public MiniLoadingDialogLoader(Context context) {
|
||||
this(context, "请求中...");
|
||||
}
|
||||
|
||||
public MiniLoadingDialogLoader(Context context, String msg) {
|
||||
mDialog = new MiniLoadingDialog(context, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoading() {
|
||||
return mDialog != null && mDialog.isShowing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMessage(String msg) {
|
||||
if (mDialog != null) {
|
||||
mDialog.updateMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showLoading() {
|
||||
if (mDialog != null && !mDialog.isShowing()) {
|
||||
mDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissLoading() {
|
||||
if (mDialog != null && mDialog.isShowing()) {
|
||||
mDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelable(boolean flag) {
|
||||
mDialog.setCancelable(flag);
|
||||
if (flag) {
|
||||
mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialogInterface) {
|
||||
if (mOnProgressCancelListener != null) {
|
||||
mOnProgressCancelListener.onCancelProgress();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnProgressCancelListener(OnProgressCancelListener listener) {
|
||||
mOnProgressCancelListener = listener;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
|
||||
/**
|
||||
* 迷你加载框创建工厂
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:23
|
||||
*/
|
||||
public class MiniProgressLoaderFactory implements IProgressLoaderFactory {
|
||||
|
||||
@Override
|
||||
public IProgressLoader create(Context context) {
|
||||
return new MiniLoadingDialogLoader(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IProgressLoader create(Context context, String message) {
|
||||
return new MiniLoadingDialogLoader(context, message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-07-02 12:51
|
||||
*/
|
||||
public final class ProgressLoader {
|
||||
|
||||
private ProgressLoader() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
private static IProgressLoaderFactory sIProgressLoaderFactory = new MiniProgressLoaderFactory();
|
||||
|
||||
public static void setIProgressLoaderFactory(IProgressLoaderFactory sIProgressLoaderFactory) {
|
||||
ProgressLoader.sIProgressLoaderFactory = sIProgressLoaderFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static IProgressLoader create(Context context) {
|
||||
return sIProgressLoaderFactory.create(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @param message 默认提示信息
|
||||
* @return
|
||||
*/
|
||||
public static IProgressLoader create(Context context, String message) {
|
||||
return sIProgressLoaderFactory.create(context, message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.subscriber;
|
||||
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.BaseSubscriber;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 不带错误toast提示的网络请求订阅,只存储错误的日志
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:11
|
||||
*/
|
||||
public abstract class NoTipRequestSubscriber<T> extends BaseSubscriber<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public NoTipRequestSubscriber() {
|
||||
|
||||
}
|
||||
|
||||
public NoTipRequestSubscriber(XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public NoTipRequestSubscriber(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.subscriber;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.ProgressLoadingSubscriber;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示和加载进度条的网络请求订阅
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:11
|
||||
*/
|
||||
public abstract class TipProgressLoadingSubscriber<T> extends ProgressLoadingSubscriber<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipProgressLoadingSubscriber() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(BaseFragment fragment) {
|
||||
super(fragment.getProgressLoader());
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(IProgressLoader iProgressLoader) {
|
||||
super(iProgressLoader);
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(@NonNull XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(String url) {
|
||||
super();
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
super.onError(e);
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.http.subscriber;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.BaseSubscriber;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示的网络请求订阅
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:10
|
||||
*/
|
||||
public abstract class TipRequestSubscriber<T> extends BaseSubscriber<T> {
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipRequestSubscriber() {
|
||||
|
||||
}
|
||||
|
||||
public TipRequestSubscriber(@NonNull XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public TipRequestSubscriber(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xrouter.facade.Postcard;
|
||||
import com.xuexiang.xrouter.facade.callback.NavCallback;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.widget.slideback.SlideBack;
|
||||
|
||||
import static com.itrycn.myeasywol.core.webview.AgentWebFragment.KEY_URL;
|
||||
|
||||
/**
|
||||
* 壳浏览器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/5 上午12:15
|
||||
*/
|
||||
public class AgentWebActivity extends AppCompatActivity {
|
||||
|
||||
/**
|
||||
* 请求浏览器
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public static void goWeb(Context context, final String url) {
|
||||
Intent intent = new Intent(context, AgentWebActivity.class);
|
||||
intent.putExtra(KEY_URL, url);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_agent_web);
|
||||
|
||||
SlideBack.with(this)
|
||||
.haveScroll(true)
|
||||
.callBack(this::finish)
|
||||
.register();
|
||||
|
||||
Uri uri = getIntent().getData();
|
||||
if (uri != null) {
|
||||
XRouter.getInstance().build(uri).navigation(this, new NavCallback() {
|
||||
@Override
|
||||
public void onArrival(Postcard postcard) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(Postcard postcard) {
|
||||
loadUrl(uri.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
String url = getIntent().getStringExtra(KEY_URL);
|
||||
loadUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadUrl(String url) {
|
||||
if (url != null) {
|
||||
openFragment(url);
|
||||
} else {
|
||||
XToastUtils.error("数据出错!");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private AgentWebFragment mAgentWebFragment;
|
||||
|
||||
private void openFragment(String url) {
|
||||
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.add(R.id.container_frame_layout, mAgentWebFragment = AgentWebFragment.getInstance(url));
|
||||
ft.commit();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
AgentWebFragment agentWebFragment = mAgentWebFragment;
|
||||
if (agentWebFragment != null) {
|
||||
if (((FragmentKeyDown) agentWebFragment).onFragmentKeyDown(keyCode, event)) {
|
||||
return true;
|
||||
} else {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
SlideBack.unregister(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,658 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceError;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.just.agentweb.action.PermissionInterceptor;
|
||||
import com.just.agentweb.core.AgentWeb;
|
||||
import com.just.agentweb.core.client.MiddlewareWebChromeBase;
|
||||
import com.just.agentweb.core.client.MiddlewareWebClientBase;
|
||||
import com.just.agentweb.core.client.WebListenerManager;
|
||||
import com.just.agentweb.core.web.AbsAgentWebSettings;
|
||||
import com.just.agentweb.core.web.AgentWebConfig;
|
||||
import com.just.agentweb.core.web.IAgentWebSettings;
|
||||
import com.just.agentweb.download.AgentWebDownloader;
|
||||
import com.just.agentweb.download.DefaultDownloadImpl;
|
||||
import com.just.agentweb.download.DownloadListenerAdapter;
|
||||
import com.just.agentweb.download.DownloadingService;
|
||||
import com.just.agentweb.utils.LogUtils;
|
||||
import com.just.agentweb.widget.IWebLayout;
|
||||
import com.itrycn.myeasywol.MyApp;
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 通用WebView页面
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/4 下午11:13
|
||||
*/
|
||||
public class AgentWebFragment extends Fragment implements FragmentKeyDown {
|
||||
public static final String KEY_URL = "com.xuexiang.xuidemo.base.webview.key_url";
|
||||
|
||||
private ImageView mBackImageView;
|
||||
private View mLineView;
|
||||
private ImageView mFinishImageView;
|
||||
private TextView mTitleTextView;
|
||||
private AgentWeb mAgentWeb;
|
||||
private ImageView mMoreImageView;
|
||||
private PopupMenu mPopupMenu;
|
||||
public static final String TAG = AgentWebFragment.class.getSimpleName();
|
||||
private DownloadingService mDownloadingService;
|
||||
|
||||
public static AgentWebFragment getInstance(String url) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_URL, url);
|
||||
return getInstance(bundle);
|
||||
}
|
||||
|
||||
public static AgentWebFragment getInstance(Bundle bundle) {
|
||||
AgentWebFragment fragment = new AgentWebFragment();
|
||||
if (bundle != null) {
|
||||
fragment.setArguments(bundle);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_agentweb, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mAgentWeb = AgentWeb.with(this)
|
||||
//传入AgentWeb的父控件。
|
||||
.setAgentWebParent((LinearLayout) view, -1, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
|
||||
//设置进度条颜色与高度,-1为默认值,高度为2,单位为dp。
|
||||
.useDefaultIndicator(-1, 3)
|
||||
//设置 IAgentWebSettings。
|
||||
.setAgentWebWebSettings(getSettings())
|
||||
//WebViewClient , 与 WebView 使用一致 ,但是请勿获取WebView调用setWebViewClient(xx)方法了,会覆盖AgentWeb DefaultWebClient,同时相应的中间件也会失效。
|
||||
.setWebViewClient(mWebViewClient)
|
||||
//WebChromeClient
|
||||
.setWebChromeClient(mWebChromeClient)
|
||||
//设置WebChromeClient中间件,支持多个WebChromeClient,AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebChrome(getMiddlewareWebChrome())
|
||||
//设置WebViewClient中间件,支持多个WebViewClient, AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebClient(getMiddlewareWebClient())
|
||||
//权限拦截 2.0.0 加入。
|
||||
.setPermissionInterceptor(mPermissionInterceptor)
|
||||
//严格模式 Android 4.2.2 以下会放弃注入对象 ,使用AgentWebView没影响。
|
||||
.setSecurityType(AgentWeb.SecurityType.STRICT_CHECK)
|
||||
//自定义UI AgentWeb3.0.0 加入。
|
||||
.setAgentWebUIController(new UIController(getActivity()))
|
||||
//参数1是错误显示的布局,参数2点击刷新控件ID -1表示点击整个布局都刷新, AgentWeb 3.0.0 加入。
|
||||
.setMainFrameErrorView(R.layout.agentweb_error_page, -1)
|
||||
.setWebLayout(getWebLayout())
|
||||
.interceptUnkownUrl()
|
||||
//创建AgentWeb。
|
||||
.createAgentWeb()
|
||||
.ready()//设置 WebSettings。
|
||||
//WebView载入该url地址的页面并显示。
|
||||
.go(getUrl());
|
||||
|
||||
if (MyApp.isDebug()) {
|
||||
AgentWebConfig.debug();
|
||||
}
|
||||
|
||||
// 得到 AgentWeb 最底层的控件
|
||||
addBackgroundChild(mAgentWeb.getWebCreator().getWebParentLayout());
|
||||
|
||||
initView(view);
|
||||
|
||||
// AgentWeb 没有把WebView的功能全面覆盖 ,所以某些设置 AgentWeb 没有提供,请从WebView方面入手设置。
|
||||
mAgentWeb.getWebCreator().getWebView().setOverScrollMode(WebView.OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
protected IWebLayout getWebLayout() {
|
||||
return new WebLayout(getActivity());
|
||||
}
|
||||
|
||||
protected void initView(View view) {
|
||||
mBackImageView = view.findViewById(R.id.iv_back);
|
||||
mLineView = view.findViewById(R.id.view_line);
|
||||
mFinishImageView = view.findViewById(R.id.iv_finish);
|
||||
mTitleTextView = view.findViewById(R.id.toolbar_title);
|
||||
mBackImageView.setOnClickListener(mOnClickListener);
|
||||
mFinishImageView.setOnClickListener(mOnClickListener);
|
||||
mMoreImageView = view.findViewById(R.id.iv_more);
|
||||
mMoreImageView.setOnClickListener(mOnClickListener);
|
||||
pageNavigator(View.GONE);
|
||||
}
|
||||
|
||||
protected void addBackgroundChild(FrameLayout frameLayout) {
|
||||
TextView textView = new TextView(frameLayout.getContext());
|
||||
textView.setText("技术由 AgentWeb 提供");
|
||||
textView.setTextSize(16);
|
||||
textView.setTextColor(Color.parseColor("#727779"));
|
||||
frameLayout.setBackgroundColor(Color.parseColor("#272b2d"));
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2);
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
final float scale = frameLayout.getContext().getResources().getDisplayMetrics().density;
|
||||
params.topMargin = (int) (15 * scale + 0.5f);
|
||||
frameLayout.addView(textView, 0, params);
|
||||
}
|
||||
|
||||
|
||||
private void pageNavigator(int tag) {
|
||||
mBackImageView.setVisibility(tag);
|
||||
mLineView.setVisibility(tag);
|
||||
}
|
||||
|
||||
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.iv_back:
|
||||
// true表示AgentWeb处理了该事件
|
||||
if (!mAgentWeb.back()) {
|
||||
AgentWebFragment.this.getActivity().finish();
|
||||
}
|
||||
break;
|
||||
case R.id.iv_finish:
|
||||
AgentWebFragment.this.getActivity().finish();
|
||||
break;
|
||||
case R.id.iv_more:
|
||||
showPoPup(v);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//========================================//
|
||||
|
||||
/**
|
||||
* 权限申请拦截器
|
||||
*/
|
||||
protected PermissionInterceptor mPermissionInterceptor = new PermissionInterceptor() {
|
||||
/**
|
||||
* PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
|
||||
* @param url
|
||||
* @param permissions
|
||||
* @param action
|
||||
* @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
|
||||
*/
|
||||
@Override
|
||||
public boolean intercept(String url, String[] permissions, String action) {
|
||||
Log.i(TAG, "mUrl:" + url + " permission:" + JsonUtil.toJson(permissions) + " action:" + action);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//=====================下载============================//
|
||||
|
||||
/**
|
||||
* 更新于 AgentWeb 4.0.0,下载监听
|
||||
*/
|
||||
protected DownloadListenerAdapter mDownloadListenerAdapter = new DownloadListenerAdapter() {
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param userAgent UserAgent
|
||||
* @param contentDisposition ContentDisposition
|
||||
* @param mimetype 资源的媒体类型
|
||||
* @param contentLength 文件长度
|
||||
* @param extra 下载配置 , 用户可以通过 Extra 修改下载icon , 关闭进度条 , 是否强制下载。
|
||||
* @return true 表示用户处理了该下载事件 , false 交给 AgentWeb 下载
|
||||
*/
|
||||
@Override
|
||||
public boolean onStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength, AgentWebDownloader.Extra extra) {
|
||||
LogUtils.i(TAG, "onStart:" + url);
|
||||
// 是否开启断点续传
|
||||
extra.setOpenBreakPointDownload(true)
|
||||
//下载通知的icon
|
||||
.setIcon(R.drawable.ic_file_download_black_24dp)
|
||||
// 连接的超时时间
|
||||
.setConnectTimeOut(6000)
|
||||
// 以8KB位单位,默认60s ,如果60s内无法从网络流中读满8KB数据,则抛出异常
|
||||
.setBlockMaxTime(10 * 60 * 1000)
|
||||
// 下载的超时时间
|
||||
.setDownloadTimeOut(Long.MAX_VALUE)
|
||||
// 串行下载更节省资源哦
|
||||
.setParallelDownload(false)
|
||||
// false 关闭进度通知
|
||||
.setEnableIndicator(true)
|
||||
// 自定义请求头
|
||||
.addHeader("Cookie", "xx")
|
||||
// 下载完成自动打开
|
||||
.setAutoOpen(true)
|
||||
// 强制下载,不管网络网络类型
|
||||
.setForceDownload(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 不需要暂停或者停止下载该方法可以不必实现
|
||||
* @param url
|
||||
* @param downloadingService 用户可以通过 DownloadingService#shutdownNow 终止下载
|
||||
*/
|
||||
@Override
|
||||
public void onBindService(String url, DownloadingService downloadingService) {
|
||||
super.onBindService(url, downloadingService);
|
||||
mDownloadingService = downloadingService;
|
||||
LogUtils.i(TAG, "onBindService:" + url + " DownloadingService:" + downloadingService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调onUnbindService方法,让用户释放掉 DownloadingService。
|
||||
* @param url
|
||||
* @param downloadingService
|
||||
*/
|
||||
@Override
|
||||
public void onUnbindService(String url, DownloadingService downloadingService) {
|
||||
super.onUnbindService(url, downloadingService);
|
||||
mDownloadingService = null;
|
||||
LogUtils.i(TAG, "onUnbindService:" + url);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param loaded 已经下载的长度
|
||||
* @param length 文件的总大小
|
||||
* @param usedTime 耗时 ,单位ms
|
||||
* 注意该方法回调在子线程 ,线程名 AsyncTask #XX 或者 AgentWeb # XX
|
||||
*/
|
||||
@Override
|
||||
public void onProgress(String url, long loaded, long length, long usedTime) {
|
||||
int mProgress = (int) ((loaded) / Float.valueOf(length) * 100);
|
||||
LogUtils.i(TAG, "onProgress:" + mProgress);
|
||||
super.onProgress(url, loaded, length, usedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path 文件的绝对路径
|
||||
* @param url 下载地址
|
||||
* @param throwable 如果异常,返回给用户异常
|
||||
* @return true 表示用户处理了下载完成后续的事件 ,false 默认交给AgentWeb 处理
|
||||
*/
|
||||
@Override
|
||||
public boolean onResult(String path, String url, Throwable throwable) {
|
||||
//下载成功
|
||||
if (null == throwable) {
|
||||
//do you work
|
||||
} else {//下载失败
|
||||
|
||||
}
|
||||
// true 不会发出下载完成的通知 , 或者打开文件
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return IAgentWebSettings
|
||||
*/
|
||||
public IAgentWebSettings getSettings() {
|
||||
return new AbsAgentWebSettings() {
|
||||
private AgentWeb mAgentWeb;
|
||||
|
||||
@Override
|
||||
protected void bindAgentWebSupport(AgentWeb agentWeb) {
|
||||
this.mAgentWeb = agentWeb;
|
||||
}
|
||||
|
||||
/**
|
||||
* AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
|
||||
* 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
|
||||
* 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
|
||||
* 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
|
||||
* @param webView
|
||||
* @param downloadListener
|
||||
* @return WebListenerManager
|
||||
*/
|
||||
@Override
|
||||
public WebListenerManager setDownloader(WebView webView, android.webkit.DownloadListener downloadListener) {
|
||||
return super.setDownloader(webView,
|
||||
DefaultDownloadImpl
|
||||
.create(getActivity(),
|
||||
webView,
|
||||
mDownloadListenerAdapter,
|
||||
mDownloadListenerAdapter,
|
||||
this.mAgentWeb.getPermissionInterceptor()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//===================WebChromeClient 和 WebViewClient===========================//
|
||||
/**
|
||||
* 页面空白,请检查scheme是否加上, scheme://host:port/path?query&query 。
|
||||
*
|
||||
* @return mUrl
|
||||
*/
|
||||
public String getUrl() {
|
||||
String target = "";
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
target = bundle.getString(KEY_URL);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(target)) {
|
||||
target = "https://github.com/xuexiangjys";
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
protected WebChromeClient mWebChromeClient = new WebChromeClient() {
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
Log.i(TAG, "onProgressChanged:" + newProgress + " view:" + view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedTitle(WebView view, String title) {
|
||||
super.onReceivedTitle(view, title);
|
||||
if (mTitleTextView != null && !TextUtils.isEmpty(title)) {
|
||||
if (title.length() > 10) {
|
||||
title = title.substring(0, 10).concat("...");
|
||||
}
|
||||
mTitleTextView.setText(title);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected WebViewClient mWebViewClient = new WebViewClient() {
|
||||
|
||||
private HashMap<String, Long> timer = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
super.onReceivedError(view, request, error);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return shouldOverrideUrlLoading(view, request.getUrl() + "");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
}
|
||||
|
||||
//
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(final WebView view, String url) {
|
||||
//intent:// scheme的处理 如果返回false , 则交给 DefaultWebClient 处理 , 默认会打开该Activity , 如果Activity不存在则跳到应用市场上去. true 表示拦截
|
||||
//例如优酷视频播放 ,intent://play?...package=com.youku.phone;end;
|
||||
//优酷想唤起自己应用播放该视频 , 下面拦截地址返回 true 则会在应用内 H5 播放 ,禁止优酷唤起播放该视频, 如果返回 false , DefaultWebClient 会根据intent 协议处理 该地址 , 首先匹配该应用存不存在 ,如果存在 , 唤起该应用播放 , 如果不存在 , 则跳到应用市场下载该应用 .
|
||||
if (url.startsWith("intent://") && url.contains("com.youku.phone")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
Log.i(TAG, "mUrl:" + url + " onPageStarted target:" + getUrl());
|
||||
timer.put(url, System.currentTimeMillis());
|
||||
if (url.equals(getUrl())) {
|
||||
pageNavigator(View.GONE);
|
||||
} else {
|
||||
pageNavigator(View.VISIBLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
|
||||
if (timer.get(url) != null) {
|
||||
long overTime = System.currentTimeMillis();
|
||||
Long startTime = timer.get(url);
|
||||
Log.i(TAG, " page mUrl:" + url + " used time:" + (overTime - startTime));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
|
||||
super.onReceivedHttpError(view, request, errorResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
|
||||
//========================菜单功能================================//
|
||||
|
||||
/**
|
||||
* 打开浏览器
|
||||
*
|
||||
* @param targetUrl 外部浏览器打开的地址
|
||||
*/
|
||||
private void openBrowser(String targetUrl) {
|
||||
if (TextUtils.isEmpty(targetUrl) || targetUrl.startsWith("file://")) {
|
||||
XToastUtils.toast(targetUrl + " 该链接无法使用浏览器打开。");
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
Uri uri = Uri.parse(targetUrl);
|
||||
intent.setData(uri);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 显示更多菜单
|
||||
*
|
||||
* @param view 菜单依附在该View下面
|
||||
*/
|
||||
private void showPoPup(View view) {
|
||||
if (mPopupMenu == null) {
|
||||
mPopupMenu = new PopupMenu(getContext(), view);
|
||||
mPopupMenu.inflate(R.menu.menu_toolbar_web);
|
||||
mPopupMenu.setOnMenuItemClickListener(mOnMenuItemClickListener);
|
||||
}
|
||||
mPopupMenu.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单事件
|
||||
*/
|
||||
private PopupMenu.OnMenuItemClickListener mOnMenuItemClickListener = new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.refresh:
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getUrlLoader().reload(); // 刷新
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.copy:
|
||||
if (mAgentWeb != null) {
|
||||
toCopy(getContext(), mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.default_browser:
|
||||
if (mAgentWeb != null) {
|
||||
openBrowser(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.share:
|
||||
if (mAgentWeb != null) {
|
||||
shareWebUrl(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 分享网页链接
|
||||
*
|
||||
* @param url 网页链接
|
||||
*/
|
||||
private void shareWebUrl(String url) {
|
||||
Intent shareIntent = new Intent();
|
||||
shareIntent.setAction(Intent.ACTION_SEND);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
shareIntent.setType("text/plain");
|
||||
//设置分享列表的标题,并且每次都显示分享列表
|
||||
startActivity(Intent.createChooser(shareIntent, "分享到"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 复制字符串
|
||||
*
|
||||
* @param context
|
||||
* @param text
|
||||
*/
|
||||
private void toCopy(Context context, String text) {
|
||||
ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
manager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||
}
|
||||
|
||||
//===================生命周期管理===========================//
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mAgentWeb.getWebLifeCycle().onResume();//恢复
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mAgentWeb.getWebLifeCycle().onPause(); //暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFragmentKeyDown(int keyCode, KeyEvent event) {
|
||||
return mAgentWeb.handleKeyEvent(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
mAgentWeb.getWebLifeCycle().onDestroy();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
//===================中间键===========================//
|
||||
|
||||
|
||||
/**
|
||||
* MiddlewareWebClientBase 是 AgentWeb 3.0.0 提供一个强大的功能,
|
||||
* 如果用户需要使用 AgentWeb 提供的功能, 不想重写 WebClientView方
|
||||
* 法覆盖AgentWeb提供的功能,那么 MiddlewareWebClientBase 是一个
|
||||
* 不错的选择 。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected MiddlewareWebClientBase getMiddlewareWebClient() {
|
||||
return new MiddlewareWebViewClient() {
|
||||
/**
|
||||
*
|
||||
* @param view
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (url.startsWith("agentweb")) {
|
||||
Log.i(TAG, "agentweb scheme ~");
|
||||
return true;
|
||||
}
|
||||
// 执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (super.shouldOverrideUrlLoading(view, url)) {
|
||||
return true;
|
||||
}
|
||||
// do you work
|
||||
return false;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return super.shouldOverrideUrlLoading(view, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected MiddlewareWebChromeBase getMiddlewareWebChrome() {
|
||||
return new MiddlewareChromeClient() {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.just.agentweb.core.AgentWeb;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
|
||||
/**
|
||||
* 基础web
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/5/28 10:22
|
||||
*/
|
||||
public abstract class BaseWebViewFragment extends BaseFragment {
|
||||
|
||||
protected AgentWeb mAgentWeb;
|
||||
|
||||
//===================生命周期管理===========================//
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mAgentWeb != null) {
|
||||
//恢复
|
||||
mAgentWeb.getWebLifeCycle().onResume();
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mAgentWeb != null) {
|
||||
//暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
|
||||
mAgentWeb.getWebLifeCycle().onPause();
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return mAgentWeb != null && mAgentWeb.handleKeyEvent(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.destroy();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/4 下午11:32
|
||||
*/
|
||||
public interface FragmentKeyDown {
|
||||
|
||||
/**
|
||||
* fragment按键监听
|
||||
* @param keyCode
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
boolean onFragmentKeyDown(int keyCode, KeyEvent event);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.webkit.WebView;
|
||||
|
||||
/**
|
||||
* 修复 Android 5.0 & 5.1 打开 WebView 闪退问题:
|
||||
* 参阅 https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LollipopFixedWebView extends WebView {
|
||||
public LollipopFixedWebView(Context context) {
|
||||
super(getFixedContext(context));
|
||||
}
|
||||
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs) {
|
||||
super(getFixedContext(context), attrs);
|
||||
}
|
||||
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
|
||||
}
|
||||
|
||||
public static Context getFixedContext(Context context) {
|
||||
if (isLollipopWebViewBug()) {
|
||||
// Avoid crashing on Android 5 and 6 (API level 21 to 23)
|
||||
return context.createConfigurationContext(new Configuration());
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
public static boolean isLollipopWebViewBug() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.M;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.util.Log;
|
||||
import android.webkit.JsResult;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.just.agentweb.core.client.MiddlewareWebChromeBase;
|
||||
|
||||
/**
|
||||
* WebChrome(WebChromeClient主要辅助WebView处理JavaScript的对话框、网站图片、网站title、加载进度等)中间件
|
||||
* 【浏览器】
|
||||
* @author xuexiang
|
||||
* @since 2019/1/4 下午11:31
|
||||
*/
|
||||
public class MiddlewareChromeClient extends MiddlewareWebChromeBase {
|
||||
|
||||
public MiddlewareChromeClient() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
|
||||
Log.i("Info", "onJsAlert:" + url);
|
||||
return super.onJsAlert(view, url, message, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
Log.i("Info", "onProgressChanged:");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.just.agentweb.core.client.MiddlewareWebClientBase;
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
|
||||
import static com.itrycn.myeasywol.core.webview.WebViewInterceptDialog.APP_LINK_HOST;
|
||||
|
||||
/**
|
||||
* 【网络请求、加载】
|
||||
* WebClient(WebViewClient 这个类主要帮助WebView处理各种通知、url加载,请求时间的)中间件
|
||||
* <p>
|
||||
* <p>
|
||||
* 方法的执行顺序,例如下面用了7个中间件一个 WebViewClient
|
||||
* <p>
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 1
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 2
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 3
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 4
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 5
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 6
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 7
|
||||
* DefaultWebClient // 8
|
||||
* .setWebViewClient(mWebViewClient) // 9
|
||||
* <p>
|
||||
* <p>
|
||||
* 典型的洋葱模型
|
||||
* 对象内部的方法执行顺序: 1->2->3->4->5->6->7->8->9->8->7->6->5->4->3->2->1
|
||||
* <p>
|
||||
* <p>
|
||||
* 中断中间件的执行, 删除super.methodName(...) 这行即可
|
||||
* <p>
|
||||
* 这里主要是做去广告的工作
|
||||
*/
|
||||
public class MiddlewareWebViewClient extends MiddlewareWebClientBase {
|
||||
|
||||
public MiddlewareWebViewClient() {
|
||||
}
|
||||
|
||||
private static int count = 1;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
Log.i("Info", "MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + request.getUrl().toString() + " c:" + (count++));
|
||||
if (shouldOverrideUrlLoadingByApp(view, request.getUrl().toString())) {
|
||||
return true;
|
||||
}
|
||||
return super.shouldOverrideUrlLoading(view, request);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
Log.i("Info", "MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + url + " c:" + (count++));
|
||||
if (shouldOverrideUrlLoadingByApp(view, url)) {
|
||||
return true;
|
||||
}
|
||||
return super.shouldOverrideUrlLoading(view, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
||||
url = url.toLowerCase();
|
||||
if (!hasAdUrl(url)) {
|
||||
//正常加载
|
||||
return super.shouldInterceptRequest(view, url);
|
||||
} else {
|
||||
//含有广告资源屏蔽请求
|
||||
return new WebResourceResponse(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
String url = request.getUrl().toString().toLowerCase();
|
||||
if (!hasAdUrl(url)) {
|
||||
//正常加载
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
} else {
|
||||
//含有广告资源屏蔽请求
|
||||
return new WebResourceResponse(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在广告的链接
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
private static boolean hasAdUrl(String url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据url的scheme处理跳转第三方app的业务,true代表拦截,false代表不拦截
|
||||
*/
|
||||
private boolean shouldOverrideUrlLoadingByApp(WebView webView, final String url) {
|
||||
if (url.startsWith("http") || url.startsWith("https") || url.startsWith("ftp")) {
|
||||
//不拦截http, https, ftp的请求
|
||||
Uri uri = Uri.parse(url);
|
||||
if (uri != null && !(APP_LINK_HOST.equals(uri.getHost())
|
||||
//防止xui官网被拦截
|
||||
&& url.contains("xpage"))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WebViewInterceptDialog.show(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.just.agentweb.core.web.AgentWebUIControllerImplBase;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* 如果你需要修改某一个AgentWeb 内部的某一个弹窗 ,请看下面的例子
|
||||
* 注意写法一定要参照 DefaultUIController 的写法 ,因为UI自由定制,但是回调的方式是固定的,并且一定要回调。
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-10-30 23:18
|
||||
*/
|
||||
public class UIController extends AgentWebUIControllerImplBase {
|
||||
|
||||
private WeakReference<Activity> mActivity;
|
||||
|
||||
public UIController(Activity activity) {
|
||||
mActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowMessage(String message, String from) {
|
||||
super.onShowMessage(message, from);
|
||||
Log.i(TAG, "message:" + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectItemsPrompt(WebView view, String url, String[] items, Handler.Callback callback) {
|
||||
// 使用默认的UI
|
||||
super.onSelectItemsPrompt(view, url, items, callback);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.just.agentweb.widget.IWebLayout;
|
||||
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||
import com.itrycn.myeasywol.R;
|
||||
|
||||
/**
|
||||
* 定义支持下来回弹的WebView
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/5 上午2:01
|
||||
*/
|
||||
public class WebLayout implements IWebLayout {
|
||||
|
||||
private final SmartRefreshLayout mSmartRefreshLayout;
|
||||
private WebView mWebView;
|
||||
|
||||
public WebLayout(Activity activity) {
|
||||
mSmartRefreshLayout = (SmartRefreshLayout) LayoutInflater.from(activity).inflate(R.layout.fragment_pulldown_web, null);
|
||||
mWebView = mSmartRefreshLayout.findViewById(R.id.webView);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewGroup getLayout() {
|
||||
return mSmartRefreshLayout;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebView getWebView() {
|
||||
return mWebView;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.widget.dialog.DialogLoader;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* WebView拦截提示
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-10-21 9:51
|
||||
*/
|
||||
public class WebViewInterceptDialog extends AppCompatActivity implements DialogInterface.OnDismissListener {
|
||||
|
||||
private static final String KEY_INTERCEPT_URL = "key_intercept_url";
|
||||
|
||||
// TODO: 2019-10-30 这里修改你的applink
|
||||
public static final String APP_LINK_HOST = "xuexiangjys.club";
|
||||
public static final String APP_LINK_ACTION = "com.xuexiang.xui.applink";
|
||||
|
||||
|
||||
/**
|
||||
* 显示WebView拦截提示
|
||||
*
|
||||
* @param url 需要拦截处理的url
|
||||
*/
|
||||
public static void show(String url) {
|
||||
ActivityUtils.startActivity(WebViewInterceptDialog.class, KEY_INTERCEPT_URL, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String url = getIntent().getStringExtra(KEY_INTERCEPT_URL);
|
||||
|
||||
DialogLoader.getInstance().showConfirmDialog(
|
||||
this,
|
||||
getOpenTitle(url),
|
||||
ResUtils.getString(R.string.lab_yes),
|
||||
(dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
if (isAppLink(url)) {
|
||||
openAppLink(this, url);
|
||||
} else {
|
||||
openApp(url);
|
||||
}
|
||||
},
|
||||
ResUtils.getString(R.string.lab_no),
|
||||
(dialog, which) -> dialog.dismiss()
|
||||
).setOnDismissListener(this);
|
||||
|
||||
}
|
||||
|
||||
private String getOpenTitle(String url) {
|
||||
String scheme = getScheme(url);
|
||||
if ("mqqopensdkapi".equals(scheme)) {
|
||||
return "是否允许页面打开\"QQ\"?";
|
||||
} else {
|
||||
return ResUtils.getString(R.string.lab_open_third_app);
|
||||
}
|
||||
}
|
||||
|
||||
private String getScheme(String url) {
|
||||
try {
|
||||
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
|
||||
return intent.getScheme();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private boolean isAppLink(String url) {
|
||||
Uri uri = Uri.parse(url);
|
||||
return uri != null
|
||||
&& APP_LINK_HOST.equals(uri.getHost())
|
||||
&& (url.startsWith("http") || url.startsWith("https"));
|
||||
}
|
||||
|
||||
|
||||
private void openApp(String url) {
|
||||
Intent intent;
|
||||
try {
|
||||
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
XUtil.getContext().startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
XToastUtils.error("您所打开的第三方App未安装!");
|
||||
}
|
||||
}
|
||||
|
||||
private void openAppLink(Context context, String url) {
|
||||
try {
|
||||
Intent intent = new Intent(APP_LINK_ACTION);
|
||||
intent.setData(Uri.parse(url));
|
||||
context.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
XToastUtils.error("您所打开的第三方App未安装!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,690 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.core.webview;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceError;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.just.agentweb.action.PermissionInterceptor;
|
||||
import com.just.agentweb.core.AgentWeb;
|
||||
import com.just.agentweb.core.client.DefaultWebClient;
|
||||
import com.just.agentweb.core.client.MiddlewareWebChromeBase;
|
||||
import com.just.agentweb.core.client.MiddlewareWebClientBase;
|
||||
import com.just.agentweb.core.client.WebListenerManager;
|
||||
import com.just.agentweb.core.web.AbsAgentWebSettings;
|
||||
import com.just.agentweb.core.web.AgentWebConfig;
|
||||
import com.just.agentweb.core.web.IAgentWebSettings;
|
||||
import com.just.agentweb.download.AgentWebDownloader;
|
||||
import com.just.agentweb.download.DefaultDownloadImpl;
|
||||
import com.just.agentweb.download.DownloadListenerAdapter;
|
||||
import com.just.agentweb.download.DownloadingService;
|
||||
import com.just.agentweb.widget.IWebLayout;
|
||||
import com.itrycn.myeasywol.MyApp;
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
import static com.itrycn.myeasywol.core.webview.AgentWebFragment.KEY_URL;
|
||||
|
||||
/**
|
||||
* 使用XPageFragment
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-05-26 18:15
|
||||
*/
|
||||
@Page(params = {KEY_URL})
|
||||
public class XPageWebViewFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.iv_back)
|
||||
AppCompatImageView mIvBack;
|
||||
@BindView(R.id.view_line)
|
||||
View mLineView;
|
||||
@BindView(R.id.toolbar_title)
|
||||
TextView mTvTitle;
|
||||
|
||||
protected AgentWeb mAgentWeb;
|
||||
private PopupMenu mPopupMenu;
|
||||
|
||||
private DownloadingService mDownloadingService;
|
||||
|
||||
/**
|
||||
* 打开网页
|
||||
*
|
||||
* @param xPageActivity
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static Fragment openUrl(XPageActivity xPageActivity, String url) {
|
||||
return PageOption.to(XPageWebViewFragment.class)
|
||||
.putString(KEY_URL, url)
|
||||
.open(xPageActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开网页
|
||||
*
|
||||
* @param fragment
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static Fragment openUrl(XPageFragment fragment, String url) {
|
||||
return PageOption.to(XPageWebViewFragment.class)
|
||||
.setNewActivity(true)
|
||||
.putString(KEY_URL, url)
|
||||
.open(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_agentweb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mAgentWeb = AgentWeb.with(this)
|
||||
//传入AgentWeb的父控件。
|
||||
.setAgentWebParent((LinearLayout) getRootView(), -1, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
|
||||
//设置进度条颜色与高度,-1为默认值,高度为2,单位为dp。
|
||||
.useDefaultIndicator(-1, 3)
|
||||
//设置 IAgentWebSettings。
|
||||
.setAgentWebWebSettings(getSettings())
|
||||
//WebViewClient , 与 WebView 使用一致 ,但是请勿获取WebView调用setWebViewClient(xx)方法了,会覆盖AgentWeb DefaultWebClient,同时相应的中间件也会失效。
|
||||
.setWebViewClient(mWebViewClient)
|
||||
//WebChromeClient
|
||||
.setWebChromeClient(mWebChromeClient)
|
||||
//设置WebChromeClient中间件,支持多个WebChromeClient,AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebChrome(getMiddlewareWebChrome())
|
||||
//设置WebViewClient中间件,支持多个WebViewClient, AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebClient(getMiddlewareWebClient())
|
||||
//权限拦截 2.0.0 加入。
|
||||
.setPermissionInterceptor(mPermissionInterceptor)
|
||||
//严格模式 Android 4.2.2 以下会放弃注入对象 ,使用AgentWebView没影响。
|
||||
.setSecurityType(AgentWeb.SecurityType.STRICT_CHECK)
|
||||
//自定义UI AgentWeb3.0.0 加入。
|
||||
.setAgentWebUIController(new UIController(getActivity()))
|
||||
//参数1是错误显示的布局,参数2点击刷新控件ID -1表示点击整个布局都刷新, AgentWeb 3.0.0 加入。
|
||||
.setMainFrameErrorView(R.layout.agentweb_error_page, -1)
|
||||
.setWebLayout(getWebLayout())
|
||||
//打开其他页面时,弹窗质询用户前往其他应用 AgentWeb 3.0.0 加入。
|
||||
.setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.DISALLOW)
|
||||
//拦截找不到相关页面的Url AgentWeb 3.0.0 加入。
|
||||
.interceptUnkownUrl()
|
||||
//创建AgentWeb。
|
||||
.createAgentWeb()
|
||||
.ready()//设置 WebSettings。
|
||||
//WebView载入该url地址的页面并显示。
|
||||
.go(getUrl());
|
||||
|
||||
if (MyApp.isDebug()) {
|
||||
AgentWebConfig.debug();
|
||||
}
|
||||
|
||||
pageNavigator(View.GONE);
|
||||
// 得到 AgentWeb 最底层的控件
|
||||
addBackgroundChild(mAgentWeb.getWebCreator().getWebParentLayout());
|
||||
|
||||
// AgentWeb 没有把WebView的功能全面覆盖 ,所以某些设置 AgentWeb 没有提供,请从WebView方面入手设置。
|
||||
mAgentWeb.getWebCreator().getWebView().setOverScrollMode(WebView.OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
protected IWebLayout getWebLayout() {
|
||||
return new WebLayout(getActivity());
|
||||
}
|
||||
|
||||
protected void addBackgroundChild(FrameLayout frameLayout) {
|
||||
TextView textView = new TextView(frameLayout.getContext());
|
||||
textView.setText("技术由 AgentWeb 提供");
|
||||
textView.setTextSize(16);
|
||||
textView.setTextColor(Color.parseColor("#727779"));
|
||||
frameLayout.setBackgroundColor(Color.parseColor("#272b2d"));
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2);
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
final float scale = frameLayout.getContext().getResources().getDisplayMetrics().density;
|
||||
params.topMargin = (int) (15 * scale + 0.5f);
|
||||
frameLayout.addView(textView, 0, params);
|
||||
}
|
||||
|
||||
|
||||
private void pageNavigator(int tag) {
|
||||
//返回的导航按钮
|
||||
mIvBack.setVisibility(tag);
|
||||
mLineView.setVisibility(tag);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@OnClick({R.id.iv_back, R.id.iv_finish, R.id.iv_more})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.iv_back:
|
||||
// true表示AgentWeb处理了该事件
|
||||
if (!mAgentWeb.back()) {
|
||||
popToBack();
|
||||
}
|
||||
break;
|
||||
case R.id.iv_finish:
|
||||
popToBack();
|
||||
break;
|
||||
case R.id.iv_more:
|
||||
showPoPup(view);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================下载============================//
|
||||
|
||||
/**
|
||||
* 更新于 AgentWeb 4.0.0,下载监听
|
||||
*/
|
||||
protected DownloadListenerAdapter mDownloadListenerAdapter = new DownloadListenerAdapter() {
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param userAgent UserAgent
|
||||
* @param contentDisposition ContentDisposition
|
||||
* @param mimeType 资源的媒体类型
|
||||
* @param contentLength 文件长度
|
||||
* @param extra 下载配置 , 用户可以通过 Extra 修改下载icon , 关闭进度条 , 是否强制下载。
|
||||
* @return true 表示用户处理了该下载事件 , false 交给 AgentWeb 下载
|
||||
*/
|
||||
@Override
|
||||
public boolean onStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength, AgentWebDownloader.Extra extra) {
|
||||
Logger.i("onStart:" + url);
|
||||
// 是否开启断点续传
|
||||
extra.setOpenBreakPointDownload(true)
|
||||
//下载通知的icon
|
||||
.setIcon(R.drawable.ic_file_download_black_24dp)
|
||||
// 连接的超时时间
|
||||
.setConnectTimeOut(6000)
|
||||
// 以8KB位单位,默认60s ,如果60s内无法从网络流中读满8KB数据,则抛出异常
|
||||
.setBlockMaxTime(10 * 60 * 1000)
|
||||
// 下载的超时时间
|
||||
.setDownloadTimeOut(Long.MAX_VALUE)
|
||||
// 串行下载更节省资源哦
|
||||
.setParallelDownload(false)
|
||||
// false 关闭进度通知
|
||||
.setEnableIndicator(true)
|
||||
// 自定义请求头
|
||||
.addHeader("Cookie", "xx")
|
||||
// 下载完成自动打开
|
||||
.setAutoOpen(true)
|
||||
// 强制下载,不管网络网络类型
|
||||
.setForceDownload(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 不需要暂停或者停止下载该方法可以不必实现
|
||||
* @param url
|
||||
* @param downloadingService 用户可以通过 DownloadingService#shutdownNow 终止下载
|
||||
*/
|
||||
@Override
|
||||
public void onBindService(String url, DownloadingService downloadingService) {
|
||||
super.onBindService(url, downloadingService);
|
||||
mDownloadingService = downloadingService;
|
||||
Logger.i("onBindService:" + url + " DownloadingService:" + downloadingService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调onUnbindService方法,让用户释放掉 DownloadingService。
|
||||
* @param url
|
||||
* @param downloadingService
|
||||
*/
|
||||
@Override
|
||||
public void onUnbindService(String url, DownloadingService downloadingService) {
|
||||
super.onUnbindService(url, downloadingService);
|
||||
mDownloadingService = null;
|
||||
Logger.i("onUnbindService:" + url);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param loaded 已经下载的长度
|
||||
* @param length 文件的总大小
|
||||
* @param usedTime 耗时 ,单位ms
|
||||
* 注意该方法回调在子线程 ,线程名 AsyncTask #XX 或者 AgentWeb # XX
|
||||
*/
|
||||
@Override
|
||||
public void onProgress(String url, long loaded, long length, long usedTime) {
|
||||
int mProgress = (int) ((loaded) / (float) length * 100);
|
||||
Logger.i("onProgress:" + mProgress);
|
||||
super.onProgress(url, loaded, length, usedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path 文件的绝对路径
|
||||
* @param url 下载地址
|
||||
* @param throwable 如果异常,返回给用户异常
|
||||
* @return true 表示用户处理了下载完成后续的事件 ,false 默认交给AgentWeb 处理
|
||||
*/
|
||||
@Override
|
||||
public boolean onResult(String path, String url, Throwable throwable) {
|
||||
//下载成功
|
||||
if (null == throwable) {
|
||||
//do you work
|
||||
} else {//下载失败
|
||||
|
||||
}
|
||||
// true 不会发出下载完成的通知 , 或者打开文件
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 下载服务设置
|
||||
*
|
||||
* @return IAgentWebSettings
|
||||
*/
|
||||
public IAgentWebSettings getSettings() {
|
||||
return new AbsAgentWebSettings() {
|
||||
private AgentWeb mAgentWeb;
|
||||
|
||||
@Override
|
||||
protected void bindAgentWebSupport(AgentWeb agentWeb) {
|
||||
this.mAgentWeb = agentWeb;
|
||||
}
|
||||
|
||||
/**
|
||||
* AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
|
||||
* 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
|
||||
* 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
|
||||
* 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
|
||||
* @param webView
|
||||
* @param downloadListener
|
||||
* @return WebListenerManager
|
||||
*/
|
||||
@Override
|
||||
public WebListenerManager setDownloader(WebView webView, android.webkit.DownloadListener downloadListener) {
|
||||
return super.setDownloader(webView,
|
||||
DefaultDownloadImpl
|
||||
.create(getActivity(),
|
||||
webView,
|
||||
mDownloadListenerAdapter,
|
||||
mDownloadListenerAdapter,
|
||||
mAgentWeb.getPermissionInterceptor()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//===================WebChromeClient 和 WebViewClient===========================//
|
||||
|
||||
/**
|
||||
* 页面空白,请检查scheme是否加上, scheme://host:port/path?query&query 。
|
||||
*
|
||||
* @return mUrl
|
||||
*/
|
||||
public String getUrl() {
|
||||
String target = "";
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
target = bundle.getString(KEY_URL);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(target)) {
|
||||
target = "https://github.com/xuexiangjys";
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 和浏览器相关,包括和JS的交互
|
||||
*/
|
||||
protected WebChromeClient mWebChromeClient = new WebChromeClient() {
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
//网页加载进度
|
||||
}
|
||||
@Override
|
||||
public void onReceivedTitle(WebView view, String title) {
|
||||
super.onReceivedTitle(view, title);
|
||||
if (mTvTitle != null && !TextUtils.isEmpty(title)) {
|
||||
if (title.length() > 10) {
|
||||
title = title.substring(0, 10).concat("...");
|
||||
}
|
||||
mTvTitle.setText(title);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 和网页url加载相关,统计加载时间
|
||||
*/
|
||||
protected WebViewClient mWebViewClient = new WebViewClient() {
|
||||
private HashMap<String, Long> mTimer = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
super.onReceivedError(view, request, error);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return shouldOverrideUrlLoading(view, request.getUrl() + "");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
}
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(final WebView view, String url) {
|
||||
//intent:// scheme的处理 如果返回false , 则交给 DefaultWebClient 处理 , 默认会打开该Activity , 如果Activity不存在则跳到应用市场上去. true 表示拦截
|
||||
//例如优酷视频播放 ,intent://play?...package=com.youku.phone;end;
|
||||
//优酷想唤起自己应用播放该视频 , 下面拦截地址返回 true 则会在应用内 H5 播放 ,禁止优酷唤起播放该视频, 如果返回 false , DefaultWebClient 会根据intent 协议处理 该地址 , 首先匹配该应用存不存在 ,如果存在 , 唤起该应用播放 , 如果不存在 , 则跳到应用市场下载该应用 .
|
||||
if (url.startsWith("intent://") && url.contains("com.youku.phone")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
mTimer.put(url, System.currentTimeMillis());
|
||||
if (url.equals(getUrl())) {
|
||||
pageNavigator(View.GONE);
|
||||
} else {
|
||||
pageNavigator(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
if (mTimer.get(url) != null) {
|
||||
long overTime = System.currentTimeMillis();
|
||||
Long startTime = mTimer.get(url);
|
||||
//统计页面的使用时长
|
||||
Logger.i(" page mUrl:" + url + " used time:" + (overTime - startTime));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
|
||||
super.onReceivedHttpError(view, request, errorResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
}
|
||||
};
|
||||
|
||||
//=====================菜单========================//
|
||||
|
||||
/**
|
||||
* 显示更多菜单
|
||||
*
|
||||
* @param view 菜单依附在该View下面
|
||||
*/
|
||||
private void showPoPup(View view) {
|
||||
if (mPopupMenu == null) {
|
||||
mPopupMenu = new PopupMenu(getContext(), view);
|
||||
mPopupMenu.inflate(R.menu.menu_toolbar_web);
|
||||
mPopupMenu.setOnMenuItemClickListener(mOnMenuItemClickListener);
|
||||
}
|
||||
mPopupMenu.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单事件
|
||||
*/
|
||||
private PopupMenu.OnMenuItemClickListener mOnMenuItemClickListener = new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.refresh:
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getUrlLoader().reload(); // 刷新
|
||||
}
|
||||
return true;
|
||||
case R.id.copy:
|
||||
if (mAgentWeb != null) {
|
||||
toCopy(getContext(), mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.default_browser:
|
||||
if (mAgentWeb != null) {
|
||||
openBrowser(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.share:
|
||||
if (mAgentWeb != null) {
|
||||
shareWebUrl(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开浏览器
|
||||
*
|
||||
* @param targetUrl 外部浏览器打开的地址
|
||||
*/
|
||||
private void openBrowser(String targetUrl) {
|
||||
if (TextUtils.isEmpty(targetUrl) || targetUrl.startsWith("file://")) {
|
||||
XToastUtils.toast(targetUrl + " 该链接无法使用浏览器打开。");
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
Uri uri = Uri.parse(targetUrl);
|
||||
intent.setData(uri);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享网页链接
|
||||
*
|
||||
* @param url 网页链接
|
||||
*/
|
||||
private void shareWebUrl(String url) {
|
||||
Intent shareIntent = new Intent();
|
||||
shareIntent.setAction(Intent.ACTION_SEND);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
shareIntent.setType("text/plain");
|
||||
//设置分享列表的标题,并且每次都显示分享列表
|
||||
startActivity(Intent.createChooser(shareIntent, "分享到"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制字符串
|
||||
*
|
||||
* @param context
|
||||
* @param text
|
||||
*/
|
||||
private void toCopy(Context context, String text) {
|
||||
ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
manager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||
}
|
||||
|
||||
//===================生命周期管理===========================//
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getWebLifeCycle().onResume();//恢复
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getWebLifeCycle().onPause(); //暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return mAgentWeb != null && mAgentWeb.handleKeyEvent(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.destroy();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
|
||||
//===================中间键===========================//
|
||||
|
||||
|
||||
/**
|
||||
* MiddlewareWebClientBase 是 AgentWeb 3.0.0 提供一个强大的功能,
|
||||
* 如果用户需要使用 AgentWeb 提供的功能, 不想重写 WebClientView方
|
||||
* 法覆盖AgentWeb提供的功能,那么 MiddlewareWebClientBase 是一个
|
||||
* 不错的选择 。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected MiddlewareWebClientBase getMiddlewareWebClient() {
|
||||
return new MiddlewareWebViewClient() {
|
||||
/**
|
||||
*
|
||||
* @param view
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (url.startsWith("agentweb")) {
|
||||
return true;
|
||||
}
|
||||
// 执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (super.shouldOverrideUrlLoading(view, url)) {
|
||||
return true;
|
||||
}
|
||||
// do you work
|
||||
return false;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return super.shouldOverrideUrlLoading(view, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected MiddlewareWebChromeBase getMiddlewareWebChrome() {
|
||||
return new MiddlewareChromeClient() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限申请拦截器
|
||||
*/
|
||||
protected PermissionInterceptor mPermissionInterceptor = new PermissionInterceptor() {
|
||||
/**
|
||||
* PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
|
||||
* @param url
|
||||
* @param permissions
|
||||
* @param action
|
||||
* @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
|
||||
*/
|
||||
@Override
|
||||
public boolean intercept(String url, String[] permissions, String action) {
|
||||
Logger.i("mUrl:" + url + " permission:" + JsonUtil.toJson(permissions) + " action:" + action);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.db;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.itrycn.myeasywol.db.dao.DaoMaster;
|
||||
import com.itrycn.myeasywol.db.dao.DaoSession;
|
||||
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
import org.greenrobot.greendao.identityscope.IdentityScopeType;
|
||||
|
||||
public class DBHelper {
|
||||
private final String DB_NAME = "happyplayer.db";
|
||||
private static DBHelper _DBHelper;
|
||||
private static UpdateOpenHelper mDevOpenHelper;
|
||||
private static DaoMaster mDaoMaster;
|
||||
private static DaoSession mDaoSession;
|
||||
private static String mPassword;
|
||||
|
||||
private DBHelper(Context context) {
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
mPassword = "itrycn2021";
|
||||
// 初始化数据库信息
|
||||
mDevOpenHelper = new UpdateOpenHelper(context, DB_NAME, null);
|
||||
getDaoMaster();
|
||||
getDaoSession();
|
||||
}
|
||||
|
||||
public static DBHelper getInstance(Context context) {
|
||||
if (null == _DBHelper) {
|
||||
synchronized (DBHelper.class) {
|
||||
if (null == _DBHelper) {
|
||||
_DBHelper = new DBHelper(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _DBHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可写数据库
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Database getWritableDatabase() {
|
||||
return mDevOpenHelper.getEncryptedWritableDb(mPassword);
|
||||
// return mDevOpenHelper.getWritableDb();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取DaoMaster
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private DaoMaster getDaoMaster() {
|
||||
if (null == mDaoMaster) {
|
||||
synchronized (DBHelper.class) {
|
||||
if (null == mDaoMaster) {
|
||||
mDaoMaster = new DaoMaster(getWritableDatabase());
|
||||
}
|
||||
}
|
||||
}
|
||||
return mDaoMaster;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取DaoSession
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DaoSession getDaoSession() {
|
||||
if (null == mDaoSession) {
|
||||
synchronized (DBHelper.class) {
|
||||
mDaoSession = getDaoMaster().newSession(IdentityScopeType.None);
|
||||
}
|
||||
}
|
||||
|
||||
return mDaoSession;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.db;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.xuexiang.xui.adapter.simple.AdapterItem;
|
||||
|
||||
public class MyAdapterItem extends AdapterItem {
|
||||
|
||||
public MyAdapterItem(CharSequence title) {
|
||||
super(title);
|
||||
}
|
||||
public MyAdapterItem(CharSequence title, Drawable icon) {
|
||||
super(title,icon);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.db;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.itrycn.myeasywol.db.dao.DaoMaster;
|
||||
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*/
|
||||
public class UpdateOpenHelper extends DaoMaster.OpenHelper {
|
||||
|
||||
public UpdateOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
|
||||
super(context, name, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库升级
|
||||
*
|
||||
* @param db
|
||||
* @param oldVersion
|
||||
* @param newVersion
|
||||
*/
|
||||
@Override
|
||||
public void onUpgrade(Database db, int oldVersion, int newVersion) {
|
||||
if (oldVersion < newVersion) {
|
||||
//操作数据库的更新 有几个表升级都可以传入到下面
|
||||
//MigrationHelper.getInstance().migrate(db, AudioInfoDao.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package com.itrycn.myeasywol.db.dao;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||
import android.util.Log;
|
||||
|
||||
import org.greenrobot.greendao.AbstractDaoMaster;
|
||||
import org.greenrobot.greendao.database.StandardDatabase;
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
import org.greenrobot.greendao.database.DatabaseOpenHelper;
|
||||
import org.greenrobot.greendao.identityscope.IdentityScopeType;
|
||||
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
|
||||
/**
|
||||
* Master of DAO (schema version 2): knows all DAOs.
|
||||
*/
|
||||
public class DaoMaster extends AbstractDaoMaster {
|
||||
public static final int SCHEMA_VERSION = 2;
|
||||
|
||||
/** Creates underlying database table using DAOs. */
|
||||
public static void createAllTables(Database db, boolean ifNotExists) {
|
||||
PCInfoDao.createTable(db, ifNotExists);
|
||||
ServerInfoDao.createTable(db, ifNotExists);
|
||||
}
|
||||
|
||||
/** Drops underlying database table using DAOs. */
|
||||
public static void dropAllTables(Database db, boolean ifExists) {
|
||||
PCInfoDao.dropTable(db, ifExists);
|
||||
ServerInfoDao.dropTable(db, ifExists);
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: Drops all table on Upgrade! Use only during development.
|
||||
* Convenience method using a {@link DevOpenHelper}.
|
||||
*/
|
||||
public static DaoSession newDevSession(Context context, String name) {
|
||||
Database db = new DevOpenHelper(context, name).getWritableDb();
|
||||
DaoMaster daoMaster = new DaoMaster(db);
|
||||
return daoMaster.newSession();
|
||||
}
|
||||
|
||||
public DaoMaster(SQLiteDatabase db) {
|
||||
this(new StandardDatabase(db));
|
||||
}
|
||||
|
||||
public DaoMaster(Database db) {
|
||||
super(db, SCHEMA_VERSION);
|
||||
registerDaoClass(PCInfoDao.class);
|
||||
registerDaoClass(ServerInfoDao.class);
|
||||
}
|
||||
|
||||
public DaoSession newSession() {
|
||||
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
|
||||
}
|
||||
|
||||
public DaoSession newSession(IdentityScopeType type) {
|
||||
return new DaoSession(db, type, daoConfigMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
|
||||
*/
|
||||
public static abstract class OpenHelper extends DatabaseOpenHelper {
|
||||
public OpenHelper(Context context, String name) {
|
||||
super(context, name, SCHEMA_VERSION);
|
||||
}
|
||||
|
||||
public OpenHelper(Context context, String name, CursorFactory factory) {
|
||||
super(context, name, factory, SCHEMA_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Database db) {
|
||||
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
|
||||
createAllTables(db, false);
|
||||
}
|
||||
}
|
||||
|
||||
/** WARNING: Drops all table on Upgrade! Use only during development. */
|
||||
public static class DevOpenHelper extends OpenHelper {
|
||||
public DevOpenHelper(Context context, String name) {
|
||||
super(context, name);
|
||||
}
|
||||
|
||||
public DevOpenHelper(Context context, String name, CursorFactory factory) {
|
||||
super(context, name, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(Database db, int oldVersion, int newVersion) {
|
||||
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
|
||||
dropAllTables(db, true);
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package com.itrycn.myeasywol.db.dao;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.greenrobot.greendao.AbstractDao;
|
||||
import org.greenrobot.greendao.AbstractDaoSession;
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
import org.greenrobot.greendao.identityscope.IdentityScopeType;
|
||||
import org.greenrobot.greendao.internal.DaoConfig;
|
||||
|
||||
import com.itrycn.myeasywol.db.entity.PCInfo;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
|
||||
import com.itrycn.myeasywol.db.dao.PCInfoDao;
|
||||
import com.itrycn.myeasywol.db.dao.ServerInfoDao;
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.greenrobot.greendao.AbstractDaoSession
|
||||
*/
|
||||
public class DaoSession extends AbstractDaoSession {
|
||||
|
||||
private final DaoConfig pCInfoDaoConfig;
|
||||
private final DaoConfig serverInfoDaoConfig;
|
||||
|
||||
private final PCInfoDao pCInfoDao;
|
||||
private final ServerInfoDao serverInfoDao;
|
||||
|
||||
public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
|
||||
daoConfigMap) {
|
||||
super(db);
|
||||
|
||||
pCInfoDaoConfig = daoConfigMap.get(PCInfoDao.class).clone();
|
||||
pCInfoDaoConfig.initIdentityScope(type);
|
||||
|
||||
serverInfoDaoConfig = daoConfigMap.get(ServerInfoDao.class).clone();
|
||||
serverInfoDaoConfig.initIdentityScope(type);
|
||||
|
||||
pCInfoDao = new PCInfoDao(pCInfoDaoConfig, this);
|
||||
serverInfoDao = new ServerInfoDao(serverInfoDaoConfig, this);
|
||||
|
||||
registerDao(PCInfo.class, pCInfoDao);
|
||||
registerDao(ServerInfo.class, serverInfoDao);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
pCInfoDaoConfig.clearIdentityScope();
|
||||
serverInfoDaoConfig.clearIdentityScope();
|
||||
}
|
||||
|
||||
public PCInfoDao getPCInfoDao() {
|
||||
return pCInfoDao;
|
||||
}
|
||||
|
||||
public ServerInfoDao getServerInfoDao() {
|
||||
return serverInfoDao;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
package com.itrycn.myeasywol.db.dao;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
|
||||
import org.greenrobot.greendao.AbstractDao;
|
||||
import org.greenrobot.greendao.Property;
|
||||
import org.greenrobot.greendao.internal.DaoConfig;
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
import org.greenrobot.greendao.database.DatabaseStatement;
|
||||
|
||||
import com.itrycn.myeasywol.db.entity.PCInfo;
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
|
||||
/**
|
||||
* DAO for table "PCINFO".
|
||||
*/
|
||||
public class PCInfoDao extends AbstractDao<PCInfo, Long> {
|
||||
|
||||
public static final String TABLENAME = "PCINFO";
|
||||
|
||||
/**
|
||||
* Properties of entity PCInfo.<br/>
|
||||
* Can be used for QueryBuilder and for referencing column names.
|
||||
*/
|
||||
public static class Properties {
|
||||
public final static Property Id = new Property(0, Long.class, "id", true, "_id");
|
||||
public final static Property Name = new Property(1, String.class, "name", false, "NAME");
|
||||
public final static Property Ip = new Property(2, String.class, "ip", false, "IP");
|
||||
public final static Property Port = new Property(3, int.class, "port", false, "PORT");
|
||||
public final static Property Mac = new Property(4, String.class, "mac", false, "MAC");
|
||||
public final static Property ServerID = new Property(5, Long.class, "serverID", false, "SERVER_ID");
|
||||
}
|
||||
|
||||
|
||||
public PCInfoDao(DaoConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
public PCInfoDao(DaoConfig config, DaoSession daoSession) {
|
||||
super(config, daoSession);
|
||||
}
|
||||
|
||||
/** Creates the underlying database table. */
|
||||
public static void createTable(Database db, boolean ifNotExists) {
|
||||
String constraint = ifNotExists? "IF NOT EXISTS ": "";
|
||||
db.execSQL("CREATE TABLE " + constraint + "\"PCINFO\" (" + //
|
||||
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
|
||||
"\"NAME\" TEXT," + // 1: name
|
||||
"\"IP\" TEXT," + // 2: ip
|
||||
"\"PORT\" INTEGER NOT NULL ," + // 3: port
|
||||
"\"MAC\" TEXT," + // 4: mac
|
||||
"\"SERVER_ID\" INTEGER);"); // 5: serverID
|
||||
}
|
||||
|
||||
/** Drops the underlying database table. */
|
||||
public static void dropTable(Database db, boolean ifExists) {
|
||||
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"PCINFO\"";
|
||||
db.execSQL(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void bindValues(DatabaseStatement stmt, PCInfo entity) {
|
||||
stmt.clearBindings();
|
||||
|
||||
Long id = entity.getId();
|
||||
if (id != null) {
|
||||
stmt.bindLong(1, id);
|
||||
}
|
||||
|
||||
String name = entity.getName();
|
||||
if (name != null) {
|
||||
stmt.bindString(2, name);
|
||||
}
|
||||
|
||||
String ip = entity.getIp();
|
||||
if (ip != null) {
|
||||
stmt.bindString(3, ip);
|
||||
}
|
||||
stmt.bindLong(4, entity.getPort());
|
||||
|
||||
String mac = entity.getMac();
|
||||
if (mac != null) {
|
||||
stmt.bindString(5, mac);
|
||||
}
|
||||
|
||||
Long serverID = entity.getServerID();
|
||||
if (serverID != null) {
|
||||
stmt.bindLong(6, serverID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void bindValues(SQLiteStatement stmt, PCInfo entity) {
|
||||
stmt.clearBindings();
|
||||
|
||||
Long id = entity.getId();
|
||||
if (id != null) {
|
||||
stmt.bindLong(1, id);
|
||||
}
|
||||
|
||||
String name = entity.getName();
|
||||
if (name != null) {
|
||||
stmt.bindString(2, name);
|
||||
}
|
||||
|
||||
String ip = entity.getIp();
|
||||
if (ip != null) {
|
||||
stmt.bindString(3, ip);
|
||||
}
|
||||
stmt.bindLong(4, entity.getPort());
|
||||
|
||||
String mac = entity.getMac();
|
||||
if (mac != null) {
|
||||
stmt.bindString(5, mac);
|
||||
}
|
||||
|
||||
Long serverID = entity.getServerID();
|
||||
if (serverID != null) {
|
||||
stmt.bindLong(6, serverID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long readKey(Cursor cursor, int offset) {
|
||||
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PCInfo readEntity(Cursor cursor, int offset) {
|
||||
PCInfo entity = new PCInfo( //
|
||||
cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
|
||||
cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // name
|
||||
cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // ip
|
||||
cursor.getInt(offset + 3), // port
|
||||
cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // mac
|
||||
cursor.isNull(offset + 5) ? null : cursor.getLong(offset + 5) // serverID
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readEntity(Cursor cursor, PCInfo entity, int offset) {
|
||||
entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
|
||||
entity.setName(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
|
||||
entity.setIp(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
|
||||
entity.setPort(cursor.getInt(offset + 3));
|
||||
entity.setMac(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
|
||||
entity.setServerID(cursor.isNull(offset + 5) ? null : cursor.getLong(offset + 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Long updateKeyAfterInsert(PCInfo entity, long rowId) {
|
||||
entity.setId(rowId);
|
||||
return rowId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getKey(PCInfo entity) {
|
||||
if(entity != null) {
|
||||
return entity.getId();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(PCInfo entity) {
|
||||
return entity.getId() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean isEntityUpdateable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
package com.itrycn.myeasywol.db.dao;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
|
||||
import org.greenrobot.greendao.AbstractDao;
|
||||
import org.greenrobot.greendao.Property;
|
||||
import org.greenrobot.greendao.internal.DaoConfig;
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
import org.greenrobot.greendao.database.DatabaseStatement;
|
||||
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
|
||||
/**
|
||||
* DAO for table "SERVER_INFO".
|
||||
*/
|
||||
public class ServerInfoDao extends AbstractDao<ServerInfo, Long> {
|
||||
|
||||
public static final String TABLENAME = "SERVER_INFO";
|
||||
|
||||
/**
|
||||
* Properties of entity ServerInfo.<br/>
|
||||
* Can be used for QueryBuilder and for referencing column names.
|
||||
*/
|
||||
public static class Properties {
|
||||
public final static Property Id = new Property(0, Long.class, "id", true, "_id");
|
||||
public final static Property Name = new Property(1, String.class, "name", false, "NAME");
|
||||
public final static Property Url = new Property(2, String.class, "Url", false, "URL");
|
||||
public final static Property SuccessMark = new Property(3, String.class, "SuccessMark", false, "SUCCESS_MARK");
|
||||
}
|
||||
|
||||
|
||||
public ServerInfoDao(DaoConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
public ServerInfoDao(DaoConfig config, DaoSession daoSession) {
|
||||
super(config, daoSession);
|
||||
}
|
||||
|
||||
/** Creates the underlying database table. */
|
||||
public static void createTable(Database db, boolean ifNotExists) {
|
||||
String constraint = ifNotExists? "IF NOT EXISTS ": "";
|
||||
db.execSQL("CREATE TABLE " + constraint + "\"SERVER_INFO\" (" + //
|
||||
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
|
||||
"\"NAME\" TEXT," + // 1: name
|
||||
"\"URL\" TEXT," + // 2: Url
|
||||
"\"SUCCESS_MARK\" TEXT);"); // 3: SuccessMark
|
||||
}
|
||||
|
||||
/** Drops the underlying database table. */
|
||||
public static void dropTable(Database db, boolean ifExists) {
|
||||
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"SERVER_INFO\"";
|
||||
db.execSQL(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void bindValues(DatabaseStatement stmt, ServerInfo entity) {
|
||||
stmt.clearBindings();
|
||||
|
||||
Long id = entity.getId();
|
||||
if (id != null) {
|
||||
stmt.bindLong(1, id);
|
||||
}
|
||||
|
||||
String name = entity.getName();
|
||||
if (name != null) {
|
||||
stmt.bindString(2, name);
|
||||
}
|
||||
|
||||
String Url = entity.getUrl();
|
||||
if (Url != null) {
|
||||
stmt.bindString(3, Url);
|
||||
}
|
||||
|
||||
String SuccessMark = entity.getSuccessMark();
|
||||
if (SuccessMark != null) {
|
||||
stmt.bindString(4, SuccessMark);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void bindValues(SQLiteStatement stmt, ServerInfo entity) {
|
||||
stmt.clearBindings();
|
||||
|
||||
Long id = entity.getId();
|
||||
if (id != null) {
|
||||
stmt.bindLong(1, id);
|
||||
}
|
||||
|
||||
String name = entity.getName();
|
||||
if (name != null) {
|
||||
stmt.bindString(2, name);
|
||||
}
|
||||
|
||||
String Url = entity.getUrl();
|
||||
if (Url != null) {
|
||||
stmt.bindString(3, Url);
|
||||
}
|
||||
|
||||
String SuccessMark = entity.getSuccessMark();
|
||||
if (SuccessMark != null) {
|
||||
stmt.bindString(4, SuccessMark);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long readKey(Cursor cursor, int offset) {
|
||||
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerInfo readEntity(Cursor cursor, int offset) {
|
||||
ServerInfo entity = new ServerInfo( //
|
||||
cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
|
||||
cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // name
|
||||
cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // Url
|
||||
cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3) // SuccessMark
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readEntity(Cursor cursor, ServerInfo entity, int offset) {
|
||||
entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
|
||||
entity.setName(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
|
||||
entity.setUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
|
||||
entity.setSuccessMark(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Long updateKeyAfterInsert(ServerInfo entity, long rowId) {
|
||||
entity.setId(rowId);
|
||||
return rowId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getKey(ServerInfo entity) {
|
||||
if(entity != null) {
|
||||
return entity.getId();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(ServerInfo entity) {
|
||||
return entity.getId() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean isEntityUpdateable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.db.entity;
|
||||
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
||||
import org.greenrobot.greendao.annotation.Id;
|
||||
import org.greenrobot.greendao.annotation.Generated;
|
||||
@Entity
|
||||
public class PCInfo {
|
||||
@Id(autoincrement = true)
|
||||
private Long id;
|
||||
private String name;
|
||||
private String ip;
|
||||
private int port;
|
||||
private String mac;
|
||||
private Long serverID;
|
||||
@Generated(hash = 867088671)
|
||||
public PCInfo(Long id, String name, String ip, int port, String mac,
|
||||
Long serverID) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
this.mac = mac;
|
||||
this.serverID = serverID;
|
||||
}
|
||||
@Generated(hash = 932968637)
|
||||
public PCInfo() {
|
||||
}
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public String getIp() {
|
||||
return this.ip;
|
||||
}
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
public String getMac() {
|
||||
return this.mac;
|
||||
}
|
||||
public void setMac(String mac) {
|
||||
this.mac = mac;
|
||||
}
|
||||
public Long getServerID() {
|
||||
return this.serverID;
|
||||
}
|
||||
public void setServerID(Long serverID) {
|
||||
this.serverID = serverID;
|
||||
}
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.db.entity;
|
||||
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
||||
import org.greenrobot.greendao.annotation.Id;
|
||||
import org.greenrobot.greendao.annotation.Generated;
|
||||
|
||||
@Entity
|
||||
public class ServerInfo {
|
||||
@Id(autoincrement = true)
|
||||
private Long id;
|
||||
private String name;
|
||||
private String Url;
|
||||
private String SuccessMark;
|
||||
@Generated(hash = 620916738)
|
||||
public ServerInfo(Long id, String name, String Url, String SuccessMark) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.Url = Url;
|
||||
this.SuccessMark = SuccessMark;
|
||||
}
|
||||
@Generated(hash = 1634164213)
|
||||
public ServerInfo() {
|
||||
}
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public String getUrl() {
|
||||
return this.Url;
|
||||
}
|
||||
public void setUrl(String Url) {
|
||||
this.Url = Url;
|
||||
}
|
||||
public String getSuccessMark() {
|
||||
return this.SuccessMark;
|
||||
}
|
||||
public void setSuccessMark(String SuccessMark) {
|
||||
this.SuccessMark = SuccessMark;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.db.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.db.entity.PCInfo;
|
||||
import com.itrycn.myeasywol.db.dao.PCInfoDao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PCInfoDb {
|
||||
/**
|
||||
* 添加PC信息
|
||||
*
|
||||
* @param context
|
||||
* @param pcInfo
|
||||
* @return
|
||||
*/
|
||||
public static boolean addPCInfo(Context context, PCInfo pcInfo) {
|
||||
try {
|
||||
DBHelper.getInstance(context).getDaoSession().getPCInfoDao().insert(pcInfo);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 批量添加PC数据
|
||||
*
|
||||
* @param context
|
||||
* @param pcInfos
|
||||
* @return
|
||||
*/
|
||||
public static boolean addPCInfos(Context context, List<PCInfo> pcInfos) {
|
||||
try {
|
||||
DBHelper.getInstance(context).getDaoSession().getPCInfoDao().insertInTx(pcInfos);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 更新PC信息
|
||||
*/
|
||||
public static boolean updatePCInfo(Context context, PCInfo info) {
|
||||
try {
|
||||
|
||||
String sql = "UPDATE ";
|
||||
sql += PCInfoDao.TABLENAME;
|
||||
sql += " SET " + PCInfoDao.Properties.Name.columnName + " =?,"+
|
||||
PCInfoDao.Properties.Ip.columnName+"=?,"+
|
||||
PCInfoDao.Properties.Port.columnName+"="+info.getPort()+","+
|
||||
PCInfoDao.Properties.Mac.columnName+"=?,"+
|
||||
PCInfoDao.Properties.ServerID.columnName+"="+info.getServerID();
|
||||
sql += " where " + PCInfoDao.Properties.Id.columnName + "="+info.getId();
|
||||
|
||||
String args[] = {info.getName(),info.getIp(), info.getMac()};
|
||||
DBHelper.getInstance(context).getWritableDatabase().execSQL(sql, args);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 删除PC信息
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static boolean deletePCInfo(Context context,Long id) {
|
||||
try {
|
||||
String sql = "DELETE FROM ";
|
||||
sql += PCInfoDao.TABLENAME;
|
||||
sql += " where " + PCInfoDao.Properties.Id.columnName + "="+id;
|
||||
DBHelper.getInstance(context).getWritableDatabase().execSQL(sql);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 获取指定服务器下的PC数量
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static int getPCCountByServer(Context context,Long ServerId) {
|
||||
Cursor cursor = null;
|
||||
int count = 0;
|
||||
try {
|
||||
//String args[] = {};
|
||||
String sql = "select count(*) from " + PCInfoDao.TABLENAME + " WHERE " + PCInfoDao.Properties.ServerID.columnName + "="+ServerId;
|
||||
cursor = DBHelper.getInstance(context).getWritableDatabase().rawQuery(sql, null);
|
||||
cursor.moveToFirst();
|
||||
count = cursor.getInt(0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.db.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.db.dao.ServerInfoDao;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ServerInfoDb {
|
||||
/**
|
||||
* 添加服务器信息
|
||||
*
|
||||
* @param context
|
||||
* @param pcInfo
|
||||
* @return
|
||||
*/
|
||||
public static boolean addServerInfo(Context context, ServerInfo pcInfo) {
|
||||
try {
|
||||
DBHelper.getInstance(context).getDaoSession().getServerInfoDao().insert(pcInfo);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 批量添加服务器数据
|
||||
*
|
||||
* @param context
|
||||
* @param serverInfos
|
||||
* @return
|
||||
*/
|
||||
public static boolean addServerInfos(Context context, List<ServerInfo> serverInfos) {
|
||||
try {
|
||||
DBHelper.getInstance(context).getDaoSession().getServerInfoDao().insertInTx(serverInfos);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 更新服务器数据
|
||||
*/
|
||||
public static boolean updateServerInfo(Context context, ServerInfo info) {
|
||||
try {
|
||||
|
||||
String sql = "UPDATE ";
|
||||
sql += ServerInfoDao.TABLENAME;
|
||||
sql += " SET " + ServerInfoDao.Properties.Name.columnName + " =?,"+
|
||||
ServerInfoDao.Properties.Url.columnName+"=?,"+
|
||||
ServerInfoDao.Properties.SuccessMark.columnName+"=?";
|
||||
sql += " where " + ServerInfoDao.Properties.Id.columnName + "="+info.getId();
|
||||
String args[] = {info.getName(),info.getUrl(),info.getSuccessMark()};
|
||||
DBHelper.getInstance(context).getWritableDatabase().execSQL(sql, args);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 删除服务器信息
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static boolean deleteServerInfo(Context context,Long id) {
|
||||
try {
|
||||
String sql = "DELETE FROM ";
|
||||
sql += ServerInfoDao.TABLENAME;
|
||||
sql += " where " + ServerInfoDao.Properties.Id.columnName + "="+id;
|
||||
DBHelper.getInstance(context).getWritableDatabase().execSQL(sql);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment;
|
||||
|
||||
import android.os.Message;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.grouplist.XUIGroupListView;
|
||||
import com.xuexiang.xutil.app.AppUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2019-10-30 00:02
|
||||
*/
|
||||
@Page(name = "关于")
|
||||
public class AboutFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.tv_version)
|
||||
TextView mVersionTextView;
|
||||
@BindView(R.id.about_list)
|
||||
XUIGroupListView mAboutGroupListView;
|
||||
@BindView(R.id.tv_copyright)
|
||||
TextView mCopyrightTextView;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_about;
|
||||
}
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mVersionTextView.setText(String.format("版本号:%s", AppUtils.getAppVersionName()));
|
||||
//.addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_homepage)), v -> AgentWebActivity.goWeb(getContext(), getString(R.string.url_project_github)))
|
||||
// .addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_author_github)), v -> AgentWebActivity.goWeb(getContext(), getString(R.string.url_author_github)))
|
||||
XUIGroupListView.newSection(getContext())
|
||||
.addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_homepage)), v -> XToastUtils.toast("暂无官网。"))
|
||||
.addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_author_github)), v -> XToastUtils.toast("作者:zilinsoft\n邮箱:zilinsoft@qq.com"))
|
||||
.addTo(mAboutGroupListView);
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy", Locale.CHINA);
|
||||
String currentYear = dateFormat.format(new Date());
|
||||
mCopyrightTextView.setText(String.format(getResources().getString(R.string.about_copyright), currentYear));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment;
|
||||
|
||||
import android.os.Message;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperTextView;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2019-10-15 22:38
|
||||
*/
|
||||
@Page(name = "设置")
|
||||
public class SettingsFragment extends BaseFragment implements SuperTextView.OnSuperTextViewClickListener {
|
||||
|
||||
@BindView(R.id.menu_common)
|
||||
SuperTextView menuCommon;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_settings;
|
||||
}
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void initViews() {
|
||||
menuCommon.setOnSuperTextViewClickListener(this);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@Override
|
||||
public void onClick(SuperTextView superTextView) {
|
||||
switch (superTextView.getId()) {
|
||||
case R.id.menu_common:
|
||||
XToastUtils.toast("暂无设置,无需在此处设置");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.news;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.db.entity.PCInfo;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
import com.itrycn.myeasywol.db.util.PCInfoDb;
|
||||
import com.itrycn.myeasywol.fragment.profile.MsgCode;
|
||||
import com.itrycn.myeasywol.utils.MyBroadcastReceiver;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.utils.WidgetUtils;
|
||||
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText;
|
||||
|
||||
import org.greenrobot.greendao.query.WhereCondition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
@Page(name = "设备管理")
|
||||
public class AddPCFragment extends BaseFragment {
|
||||
@BindView(R.id.et_name)
|
||||
MaterialEditText etName;
|
||||
@BindView(R.id.et_mac)
|
||||
MaterialEditText etMac;
|
||||
@BindView(R.id.et_ip)
|
||||
MaterialEditText etIP;
|
||||
@BindView(R.id.et_port)
|
||||
MaterialEditText etPort;
|
||||
@BindView(R.id.spinner_server)
|
||||
Spinner spinnerServer;
|
||||
@BindView(R.id.frag_name)
|
||||
TextView frag_name;
|
||||
Boolean isAdd=true;
|
||||
Long SelectedId=0L;
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_add_pcinfo;
|
||||
}
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void initViews() {
|
||||
List<ServerInfo> list =new ArrayList<ServerInfo>();
|
||||
ServerInfo info= new ServerInfo();
|
||||
info.setName(getString(R.string.sever_direct));
|
||||
info.setUrl("direct");
|
||||
info.setId(-1L);
|
||||
list.add(info);
|
||||
list.addAll(DBHelper.getInstance(getContext()).getDaoSession().getServerInfoDao().queryBuilder().list());
|
||||
WidgetUtils.initSpinnerStyle(spinnerServer);
|
||||
ServerAdapter _MyAdapter=new ServerAdapter(getContext(), list);
|
||||
spinnerServer.setAdapter(_MyAdapter);
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
Long id= bundle.getLong(MsgCode.ACTION_DATA_KEY,-1);
|
||||
if(id>=0) {
|
||||
List<PCInfo> list_pc = DBHelper.getInstance(getContext()).getDaoSession().getPCInfoDao().queryBuilder().where(new WhereCondition.StringCondition("_id=" + id)).list();
|
||||
if (list_pc.size() == 1) {
|
||||
etName.setText(list_pc.get(0).getName());
|
||||
etMac.setText(list_pc.get(0).getMac());
|
||||
etIP.setText(list_pc.get(0).getIp());
|
||||
if(list_pc.get(0).getPort()>0) {
|
||||
etPort.setText(String.valueOf(list_pc.get(0).getPort()));
|
||||
}
|
||||
SelectedId = list_pc.get(0).getId();
|
||||
isAdd = false;
|
||||
frag_name.setText("修改设备");
|
||||
Long ServerId = list_pc.get(0).getServerID();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (list.get(i).getId() == ServerId) {
|
||||
spinnerServer.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} }
|
||||
@SingleClick
|
||||
@OnClick({R.id.btn_ok})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_ok:
|
||||
String Name=etName.getEditValue();
|
||||
if(Name.length()<1)
|
||||
{
|
||||
XToastUtils.warning("请输入名称");
|
||||
return;
|
||||
}
|
||||
String Mac=etMac.getEditValue();
|
||||
if(Mac.length()!=17 && Mac.length()!=12)
|
||||
{
|
||||
XToastUtils.warning("请输入正确的MAC");
|
||||
return;
|
||||
}
|
||||
ServerInfo ss=(ServerInfo)spinnerServer.getSelectedItem();
|
||||
PCInfo info=new PCInfo();
|
||||
info.setName(Name);
|
||||
info.setMac(Mac);
|
||||
info.setIp(etIP.getEditValue());
|
||||
if(etPort.getEditValue().length()>0) {
|
||||
info.setPort(Integer.parseInt(etPort.getEditValue()));
|
||||
}
|
||||
else
|
||||
{
|
||||
info.setPort(-1);
|
||||
}
|
||||
info.setServerID(ss.getId());
|
||||
if(isAdd) {
|
||||
PCInfoDb.addPCInfo(getContext(),info);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.setId(SelectedId);
|
||||
PCInfoDb.updatePCInfo(getContext(),info);
|
||||
}
|
||||
popToBack();
|
||||
MyBroadcastReceiver.sendReceiver(getContext().getApplicationContext(), MsgCode.ACTION_CODE_UPDATE_PCLIST);
|
||||
//确定按钮
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.news;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
import com.itrycn.myeasywol.db.util.ServerInfoDb;
|
||||
import com.itrycn.myeasywol.fragment.profile.MsgCode;
|
||||
import com.itrycn.myeasywol.utils.MyBroadcastReceiver;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText;
|
||||
|
||||
import org.greenrobot.greendao.query.WhereCondition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
@Page(name = "服务器管理")
|
||||
public class AddServerFragment extends BaseFragment {
|
||||
@BindView(R.id.et_name)
|
||||
MaterialEditText etName;
|
||||
@BindView(R.id.et_url)
|
||||
MaterialEditText etUrl;
|
||||
@BindView(R.id.et_successmark)
|
||||
MaterialEditText etSuccessMark;
|
||||
@BindView(R.id.frag_name)
|
||||
TextView frag_name;
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_add_serverinfo;
|
||||
}
|
||||
Boolean isAdd=true;
|
||||
Long SelectedId=0L;
|
||||
@Override
|
||||
protected void initViews() {
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
Long id= bundle.getLong(MsgCode.ACTION_DATA_KEY,-1);
|
||||
if(id>=0) {
|
||||
List<ServerInfo> list = DBHelper.getInstance(getContext()).getDaoSession().getServerInfoDao().queryBuilder().where(new WhereCondition.StringCondition("_id=" + id)).list();
|
||||
if (list.size() == 1) {
|
||||
etName.setText(list.get(0).getName());
|
||||
etUrl.setText(list.get(0).getUrl());
|
||||
etSuccessMark.setText(list.get(0).getSuccessMark());
|
||||
SelectedId = list.get(0).getId();
|
||||
isAdd = false;
|
||||
frag_name.setText("修改服务器");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
}
|
||||
@SingleClick
|
||||
@OnClick({R.id.btn_ok})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_ok:
|
||||
String Name=etName.getEditValue();
|
||||
if(Name.length()<1)
|
||||
{
|
||||
XToastUtils.warning("请输入名称");
|
||||
return;
|
||||
}
|
||||
String Url=etUrl.getEditValue();
|
||||
if(Url.length()<5)
|
||||
{
|
||||
XToastUtils.warning("请输入正确的Url");
|
||||
return;
|
||||
}
|
||||
ServerInfo info=new ServerInfo();
|
||||
info.setName(Name);
|
||||
info.setUrl(Url);
|
||||
info.setSuccessMark(etSuccessMark.getEditValue());
|
||||
if(isAdd) {
|
||||
ServerInfoDb.addServerInfo(getContext(), info);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.setId(SelectedId);
|
||||
ServerInfoDb.updateServerInfo(getContext(), info);
|
||||
}
|
||||
popToBack();
|
||||
MyBroadcastReceiver.sendReceiver(getContext().getApplicationContext(), MsgCode.ACTION_CODE_UPDATE_SERVERLIST);
|
||||
//确定按钮
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.news;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
import com.alibaba.android.vlayout.VirtualLayoutManager;
|
||||
import com.alibaba.android.vlayout.layout.GridLayoutHelper;
|
||||
import com.alibaba.android.vlayout.layout.LinearLayoutHelper;
|
||||
import com.itrycn.myeasywol.adapter.base.delegate.BaseDelegateAdapter;
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.db.dao.PCInfoDao;
|
||||
import com.itrycn.myeasywol.db.entity.PCInfo;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
import com.itrycn.myeasywol.fragment.profile.MsgCode;
|
||||
import com.itrycn.myeasywol.utils.MyBroadcastReceiver;
|
||||
import com.itrycn.myeasywol.utils.RandomUtils;
|
||||
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.adapter.base.broccoli.BroccoliSimpleDelegateAdapter;
|
||||
import com.itrycn.myeasywol.adapter.base.delegate.SimpleDelegateAdapter;
|
||||
import com.itrycn.myeasywol.adapter.base.delegate.SingleDelegateAdapter;
|
||||
import com.itrycn.myeasywol.adapter.entity.NewInfo;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.utils.Utils;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
import com.xuexiang.xui.adapter.simple.AdapterItem;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.banner.widget.banner.SimpleImageBanner;
|
||||
import com.xuexiang.xui.widget.imageview.ImageLoader;
|
||||
import com.xuexiang.xui.widget.imageview.RadiusImageView;
|
||||
|
||||
import org.greenrobot.greendao.query.WhereCondition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.Attributes;
|
||||
|
||||
import butterknife.BindView;
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
/**
|
||||
* 首页动态
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-10-30 00:15
|
||||
*/
|
||||
@Page(anim = CoreAnim.none)
|
||||
public class PCFragment extends BaseFragment {
|
||||
/**
|
||||
* 广播
|
||||
*/
|
||||
private MyBroadcastReceiver mBroadcastReceiver;
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.refreshLayout)
|
||||
SmartRefreshLayout refreshLayout;
|
||||
private SimpleDelegateAdapter<PCInfo> commonAdapter;
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_news;
|
||||
}
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
}
|
||||
private static List<PCInfo> getPCList(Context context) {
|
||||
try {
|
||||
//按创建时间倒序
|
||||
List<PCInfo> audioInfos = DBHelper.getInstance(context).getDaoSession().getPCInfoDao().queryBuilder().list();
|
||||
return audioInfos;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ArrayList<PCInfo>();
|
||||
}
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(getContext());
|
||||
recyclerView.setLayoutManager(virtualLayoutManager);
|
||||
RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
|
||||
recyclerView.setRecycledViewPool(viewPool);
|
||||
viewPool.setMaxRecycledViews(0, 10);
|
||||
mBroadcastReceiver = new MyBroadcastReceiver();
|
||||
//轮播条
|
||||
// SingleDelegateAdapter bannerAdapter = new SingleDelegateAdapter(R.layout.include_head_view_banner) {
|
||||
// @Override
|
||||
// public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
|
||||
// SimpleImageBanner banner = holder.findViewById(R.id.sib_simple_usage);
|
||||
// banner.setSource(DemoDataProvider.getBannerList())
|
||||
// .setOnItemClickListener((view, item, position1) -> XToastUtils.toast("headBanner position--->" + position1)).startScroll();
|
||||
// }
|
||||
// };
|
||||
//九宫格菜单
|
||||
GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(4);
|
||||
gridLayoutHelper.setPadding(0, 16, 0, 0);
|
||||
gridLayoutHelper.setVGap(10);
|
||||
gridLayoutHelper.setHGap(0);
|
||||
gridLayoutHelper.setAutoExpand(false);
|
||||
commonAdapter = new SimpleDelegateAdapter<PCInfo>(R.layout.adapter_common_grid_item, gridLayoutHelper,getPCList(getContext())) {
|
||||
@Override
|
||||
protected void bindData(@NonNull RecyclerViewHolder holder, int position, PCInfo item) {
|
||||
if (item != null) {
|
||||
RadiusImageView imageView = holder.findViewById(R.id.riv_item);
|
||||
imageView.setCircle(true);
|
||||
Drawable[] draw=ResUtils.getDrawableArray(getContext(), R.array.grid_icons_entry);
|
||||
ImageLoader.get().loadImage(imageView,draw[RandomUtils.getRandom(0,draw.length)]);
|
||||
holder.text(R.id.tv_title, item.getName().toString().substring(0, 1));
|
||||
holder.text(R.id.tv_sub_title, item.getName());
|
||||
holder.click(R.id.ll_container,new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//打开排行页面
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(MsgCode.ACTION_DATA_KEY, item.getId());
|
||||
MyBroadcastReceiver.sendReceiver(getContext().getApplicationContext(), MsgCode.ACTION_CODE_WAKE_PC,MyBroadcastReceiver.ACTION_BUNDLEKEY,bundle);
|
||||
//XToastUtils.toast("点击了:" + item.getMac());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
DelegateAdapter delegateAdapter = new DelegateAdapter(virtualLayoutManager);
|
||||
// delegateAdapter.addAdapter(bannerAdapter);
|
||||
delegateAdapter.addAdapter(commonAdapter);
|
||||
|
||||
recyclerView.setAdapter(delegateAdapter);
|
||||
mBroadcastReceiver = new MyBroadcastReceiver();
|
||||
mBroadcastReceiver.setReceiverListener(new MyBroadcastReceiver.MyReceiverListener() {
|
||||
@Override
|
||||
public void onReceive(Context context, final Intent intent, final int code) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleAudioBroadcastReceiver(intent, code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleAudioBroadcastReceiver(Intent intent, int code) {
|
||||
switch (code) {
|
||||
case MsgCode.ACTION_CODE_UPDATE_PCLIST:
|
||||
refresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
mBroadcastReceiver.registerReceiver(getContext().getApplicationContext());
|
||||
}
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mBroadcastReceiver != null) {
|
||||
mBroadcastReceiver.unregisterReceiver(getContext());
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
//下拉刷新
|
||||
refreshLayout.setOnRefreshListener(refreshLayout -> {
|
||||
// TODO: 2020-02-25 这里只是模拟了网络请求
|
||||
refreshLayout.getLayout().post(() -> {
|
||||
refresh();
|
||||
refreshLayout.finishRefresh();
|
||||
});
|
||||
});
|
||||
//refreshLayout.autoRefresh();//第一次进入触发自动刷新,演示效果
|
||||
}
|
||||
private void refresh() {
|
||||
// refreshLayout.setEnableRefresh(true);
|
||||
loadData();
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
new Handler().post(() -> {
|
||||
commonAdapter.refresh(getPCList(getContext()));
|
||||
// if (refreshLayout != null) {
|
||||
// refreshLayout.setEnableRefresh(false);
|
||||
// }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.news;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ServerAdapter extends BaseAdapter {
|
||||
private List<ServerInfo> mList;
|
||||
private Context mContext;
|
||||
public ServerAdapter(Context pContext, List<ServerInfo> pList) {
|
||||
this.mContext = pContext;
|
||||
this.mList = pList;
|
||||
}
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mList.size();
|
||||
}
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mList.get(position);
|
||||
}
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
/**
|
||||
* 下面是重要代码
|
||||
*/
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
LayoutInflater _LayoutInflater=LayoutInflater.from(mContext);
|
||||
convertView=_LayoutInflater.inflate(R.layout.xui_layout_spinner_selected_item, null);
|
||||
if(convertView!=null)
|
||||
{
|
||||
TextView _TextView1=(TextView)convertView.findViewById(R.id.spinner_item);
|
||||
_TextView1.setText(mList.get(position).getName());
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.news;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.adapter.base.delegate.ServerRecyclerAdapter;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
import com.itrycn.myeasywol.db.util.PCInfoDb;
|
||||
import com.itrycn.myeasywol.db.util.ServerInfoDb;
|
||||
import com.itrycn.myeasywol.fragment.profile.MsgCode;
|
||||
import com.itrycn.myeasywol.utils.MyBroadcastReceiver;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.utils.WidgetUtils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog;
|
||||
import com.yanzhenjie.recyclerview.OnItemClickListener;
|
||||
import com.yanzhenjie.recyclerview.OnItemMenuClickListener;
|
||||
import com.yanzhenjie.recyclerview.SwipeMenuCreator;
|
||||
import com.yanzhenjie.recyclerview.SwipeMenuItem;
|
||||
import com.yanzhenjie.recyclerview.SwipeRecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
@Page(name = "服务器列表")
|
||||
public class ServerViewFragment extends BaseFragment {
|
||||
/**
|
||||
* 广播
|
||||
*/
|
||||
private MyBroadcastReceiver mBroadcastReceiver;
|
||||
@BindView(R.id.refresh_layout)
|
||||
SwipeRefreshLayout refreshLayout;
|
||||
|
||||
@BindView(R.id.recycler_view)
|
||||
SwipeRecyclerView recyclerView;
|
||||
|
||||
private ServerRecyclerAdapter ServerAdapter;
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
}
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
}
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_server;
|
||||
}
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
WidgetUtils.initRecyclerView(recyclerView);
|
||||
|
||||
//必须在setAdapter之前调用
|
||||
recyclerView.setSwipeMenuCreator(swipeMenuCreator);
|
||||
//必须在setAdapter之前调用
|
||||
recyclerView.setOnItemMenuClickListener(mMenuItemClickListener);
|
||||
recyclerView.setOnItemClickListener(ItemClickListener);
|
||||
//List<ServerInfo> audioInfos = DBHelper.getInstance(getContext()).getDaoSession().getServerInfoDao().queryBuilder().list();
|
||||
ServerAdapter = new ServerRecyclerAdapter();
|
||||
recyclerView.setAdapter(ServerAdapter);
|
||||
|
||||
refreshLayout.setColorSchemeColors(0xff0099cc, 0xffff4444, 0xff669900, 0xffaa66cc, 0xffff8800);
|
||||
mBroadcastReceiver = new MyBroadcastReceiver();
|
||||
mBroadcastReceiver.setReceiverListener(new MyBroadcastReceiver.MyReceiverListener() {
|
||||
@Override
|
||||
public void onReceive(Context context, final Intent intent, final int code) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleAudioBroadcastReceiver(intent, code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleAudioBroadcastReceiver(Intent intent, int code) {
|
||||
switch (code) {
|
||||
case MsgCode.ACTION_CODE_UPDATE_SERVERLIST:
|
||||
refresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
mBroadcastReceiver.registerReceiver(getContext().getApplicationContext());
|
||||
}
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mBroadcastReceiver != null) {
|
||||
mBroadcastReceiver.unregisterReceiver(getContext());
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
private OnItemClickListener ItemClickListener = (View itemView, int position) -> {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(MsgCode.ACTION_DATA_KEY, ServerAdapter.getItem(position).getId());
|
||||
MyBroadcastReceiver.sendReceiver(getContext().getApplicationContext(), MsgCode.ACTION_CODE_EDIT_SERVER,MyBroadcastReceiver.ACTION_BUNDLEKEY,bundle);
|
||||
};
|
||||
/**
|
||||
* 菜单创建器,在Item要创建菜单的时候调用。
|
||||
*/
|
||||
private SwipeMenuCreator swipeMenuCreator = (swipeLeftMenu, swipeRightMenu, position) -> {
|
||||
int width = getResources().getDimensionPixelSize(R.dimen.dp_70);
|
||||
|
||||
// 1. MATCH_PARENT 自适应高度,保持和Item一样高;
|
||||
// 2. 指定具体的高,比如80;
|
||||
// 3. WRAP_CONTENT,自身高度,不推荐;
|
||||
int height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
|
||||
|
||||
// 添加右侧的,如果不添加,则右侧不会出现菜单。
|
||||
{
|
||||
SwipeMenuItem deleteItem = new SwipeMenuItem(getContext()).setBackground(R.drawable.menu_selector_red)
|
||||
.setText("删除")
|
||||
.setTextColor(Color.WHITE)
|
||||
.setWidth(width)
|
||||
.setHeight(height);
|
||||
swipeRightMenu.addMenuItem(deleteItem);// 添加菜单到右侧。
|
||||
|
||||
SwipeMenuItem addItem = new SwipeMenuItem(getContext()).setBackground(R.drawable.menu_selector_green)
|
||||
.setText("编辑")
|
||||
.setTextColor(Color.WHITE)
|
||||
.setWidth(width)
|
||||
.setHeight(height);
|
||||
swipeRightMenu.addMenuItem(addItem); // 添加菜单到右侧。
|
||||
}
|
||||
};
|
||||
/**
|
||||
* RecyclerView的Item的Menu点击监听。
|
||||
*/
|
||||
private OnItemMenuClickListener mMenuItemClickListener = (menuBridge, position) -> {
|
||||
menuBridge.closeMenu();
|
||||
|
||||
int direction = menuBridge.getDirection(); // 左侧还是右侧菜单。
|
||||
int menuPosition = menuBridge.getPosition(); // 菜单在RecyclerView的Item中的Position。
|
||||
|
||||
if (direction == SwipeRecyclerView.RIGHT_DIRECTION) {
|
||||
if(menuPosition==0)//删除
|
||||
{
|
||||
MaterialDialog.Builder materialDialog= new MaterialDialog.Builder(getContext());
|
||||
materialDialog.content("是否确认要删除该服务器?")
|
||||
.positiveText(R.string.lab_yes)
|
||||
.negativeText(R.string.lab_no)
|
||||
.onPositive((dialog, which) -> {
|
||||
Long ServerId=ServerAdapter.getItem(position).getId();
|
||||
int count= PCInfoDb.getPCCountByServer(getContext(),ServerId);
|
||||
if(count==0) {
|
||||
ServerInfoDb.deleteServerInfo(getContext(), ServerId);
|
||||
ServerAdapter.getListData().remove(position);
|
||||
ServerAdapter.notifyDataSetChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
new MaterialDialog.Builder(getContext())
|
||||
.iconRes(R.drawable.icon_tip)
|
||||
.title("提示")
|
||||
.content("当前中转服务器下还有设备,请先删除设备后再删除中转服务器。")
|
||||
.positiveText("确定")
|
||||
.show();
|
||||
}
|
||||
}).show();
|
||||
|
||||
}
|
||||
else if(menuPosition==1)//编辑
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(MsgCode.ACTION_DATA_KEY, ServerAdapter.getItem(position).getId());
|
||||
MyBroadcastReceiver.sendReceiver(getContext().getApplicationContext(), MsgCode.ACTION_CODE_EDIT_SERVER,MyBroadcastReceiver.ACTION_BUNDLEKEY,bundle);
|
||||
}
|
||||
//XToastUtils.toast("list第" + position + "; 右侧菜单第" + menuPosition+"-->"+ServerAdapter.getItem(position).getName());
|
||||
} else if (direction == SwipeRecyclerView.LEFT_DIRECTION) {
|
||||
//XToastUtils.toast("list第" + position + "; 左侧菜单第" + menuPosition);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
//下拉刷新
|
||||
refreshLayout.setOnRefreshListener(this::loadData);
|
||||
refresh(); //第一次进入触发自动刷新,演示效果
|
||||
}
|
||||
private void refresh() {
|
||||
refreshLayout.setRefreshing(true);
|
||||
loadData();
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
new Handler().postDelayed(() -> {
|
||||
List<ServerInfo> audioInfos = DBHelper.getInstance(getContext()).getDaoSession().getServerInfoDao().queryBuilder().list();
|
||||
ServerAdapter.refresh(audioInfos);
|
||||
if (refreshLayout != null) {
|
||||
refreshLayout.setRefreshing(false);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.news;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.db.DBHelper;
|
||||
import com.itrycn.myeasywol.db.entity.PCInfo;
|
||||
import com.itrycn.myeasywol.db.entity.ServerInfo;
|
||||
import com.itrycn.myeasywol.db.util.PCInfoDb;
|
||||
import com.itrycn.myeasywol.fragment.profile.MagicBoot;
|
||||
import com.itrycn.myeasywol.fragment.profile.MsgCode;
|
||||
import com.itrycn.myeasywol.utils.MyBroadcastReceiver;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog;
|
||||
|
||||
import org.greenrobot.greendao.query.WhereCondition;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
@Page(name = "唤醒设备")
|
||||
public class WakePCFragment extends BaseFragment {
|
||||
private PopupMenu mPopupMenu;
|
||||
@BindView(R.id.iv_back)
|
||||
ImageView mBackImageView;
|
||||
@BindView(R.id.toolbar_title)
|
||||
TextView mTitleTextView;
|
||||
@BindView(R.id.iv_more)
|
||||
ImageView mMoreImageView;
|
||||
/**
|
||||
* 唤醒成功
|
||||
*/
|
||||
private final int Wake_Successs = 1;
|
||||
/**
|
||||
* 唤醒失败
|
||||
*/
|
||||
private final int Wake_Failure = -1;
|
||||
/**
|
||||
* 唤醒失败,没有发现服务器
|
||||
*/
|
||||
private final int Wake_UnfoundServer = -2;
|
||||
/**
|
||||
* 唤醒失败,发送出错
|
||||
*/
|
||||
private final int Wake_Error = -3;
|
||||
/**
|
||||
* 广播
|
||||
*/
|
||||
private MyBroadcastReceiver mBroadcastReceiver;
|
||||
PCInfo pcitem;
|
||||
@BindView(R.id.lblpcname)
|
||||
TextView lblpcname;
|
||||
@BindView(R.id.lblservername)
|
||||
TextView lblservername;
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_wake_pc;
|
||||
}
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
}
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case Wake_Successs:
|
||||
XToastUtils.success("远程唤醒数据包发送成功。");
|
||||
break;
|
||||
case Wake_Failure:
|
||||
XToastUtils.error( "远程唤醒数据包发送失败。\r\n请重试。");
|
||||
break;
|
||||
case Wake_UnfoundServer:
|
||||
XToastUtils.warning("没有发现服务器,远程唤醒失败。");
|
||||
break;
|
||||
case Wake_Error:
|
||||
XToastUtils.error("发送失败,出现错误。");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mTitleTextView.setText("唤醒设备");
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
Long id= bundle.getLong(MsgCode.ACTION_DATA_KEY);
|
||||
List<PCInfo> list= DBHelper.getInstance(getContext()).getDaoSession().getPCInfoDao().queryBuilder().where(new WhereCondition.StringCondition("_id="+id)).list();
|
||||
if(list.size()==1)
|
||||
{
|
||||
pcitem=list.get(0);
|
||||
lblpcname.setText(pcitem.getName());
|
||||
if(pcitem.getServerID()==-1)
|
||||
{
|
||||
lblservername.setText(R.string.sever_direct);
|
||||
}
|
||||
else {
|
||||
List<ServerInfo> list_server = DBHelper.getInstance(getContext()).getDaoSession().getServerInfoDao().queryBuilder().where(new WhereCondition.StringCondition("_id=" + pcitem.getServerID())).list();
|
||||
if (list_server.size() == 1) {
|
||||
lblservername.setText(list_server.get(0).getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mBroadcastReceiver = new MyBroadcastReceiver();
|
||||
mBroadcastReceiver.setReceiverListener(new MyBroadcastReceiver.MyReceiverListener() {
|
||||
@Override
|
||||
public void onReceive(Context context, final Intent intent, final int code) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleAudioBroadcastReceiver(intent, code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleAudioBroadcastReceiver(Intent intent, int code) {
|
||||
switch (code) {
|
||||
case MsgCode.ACTION_CODE_UPDATE_PCLIST:
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
Long id= bundle.getLong(MsgCode.ACTION_DATA_KEY);
|
||||
List<PCInfo> list= DBHelper.getInstance(getContext()).getDaoSession().getPCInfoDao().queryBuilder().where(new WhereCondition.StringCondition("_id="+id)).list();
|
||||
if(list.size()==1)
|
||||
{
|
||||
pcitem=list.get(0);
|
||||
lblpcname.setText(pcitem.getName());
|
||||
if(pcitem.getServerID()==-1)
|
||||
{
|
||||
lblservername.setText(R.string.sever_direct);
|
||||
}
|
||||
else {
|
||||
List<ServerInfo> list_server = DBHelper.getInstance(getContext()).getDaoSession().getServerInfoDao().queryBuilder().where(new WhereCondition.StringCondition("_id=" + pcitem.getServerID())).list();
|
||||
if (list_server.size() == 1) {
|
||||
lblservername.setText(list_server.get(0).getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
mBroadcastReceiver.registerReceiver(getContext().getApplicationContext());
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mBroadcastReceiver != null) {
|
||||
mBroadcastReceiver.unregisterReceiver(getContext().getApplicationContext());
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
/**
|
||||
* 显示更多菜单
|
||||
*
|
||||
* @param view 菜单依附在该View下面
|
||||
*/
|
||||
private void showPoPup(View view) {
|
||||
if (mPopupMenu == null) {
|
||||
mPopupMenu = new PopupMenu(getContext(), view);
|
||||
mPopupMenu.inflate(R.menu.menu_toolbar_edit);
|
||||
mPopupMenu.setOnMenuItemClickListener(mOnMenuItemClickListener);
|
||||
}
|
||||
mPopupMenu.show();
|
||||
}
|
||||
/**
|
||||
* 菜单事件
|
||||
*/
|
||||
private PopupMenu.OnMenuItemClickListener mOnMenuItemClickListener = new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.edit:
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(MsgCode.ACTION_DATA_KEY, pcitem.getId());
|
||||
MyBroadcastReceiver.sendReceiver(getContext().getApplicationContext(), MsgCode.ACTION_CODE_EDIT_PC,MyBroadcastReceiver.ACTION_BUNDLEKEY,bundle);
|
||||
return true;
|
||||
case R.id.delete:
|
||||
MaterialDialog.Builder materialDialog= new MaterialDialog.Builder(getContext());
|
||||
materialDialog.content("是否确认要删除该设备?")
|
||||
.positiveText(R.string.lab_yes)
|
||||
.negativeText(R.string.lab_no)
|
||||
.onPositive((dialog, which) -> {
|
||||
PCInfoDb.deletePCInfo(getContext(),pcitem.getId());
|
||||
MyBroadcastReceiver.sendReceiver(getContext().getApplicationContext(), MsgCode.ACTION_CODE_UPDATE_PCLIST);
|
||||
popToBack();
|
||||
}).show();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
@SingleClick
|
||||
@OnClick({R.id.btn_wake,R.id.iv_back,R.id.iv_more})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_wake:
|
||||
if(pcitem!=null) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO Auto-generated method stub
|
||||
Long ServerID=pcitem.getServerID();
|
||||
if(ServerID==-1)//直链唤醒
|
||||
{
|
||||
new Thread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
int port=pcitem.getPort();
|
||||
if(port<=0){port=20201;}
|
||||
try {
|
||||
boolean result = MagicBoot.SendMagic(pcitem.getMac(), pcitem.getIp(), port);
|
||||
if (result) {
|
||||
mUIHandler.sendEmptyMessage(Wake_Successs);
|
||||
} else {
|
||||
mUIHandler.sendEmptyMessage(Wake_Failure);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
mUIHandler.sendEmptyMessage(Wake_Error);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start(); //这段代码在主线程中调用,开启一个线程
|
||||
|
||||
//mUIHandler.sendEmptyMessage(Wake_UnfoundServer);
|
||||
}
|
||||
else {
|
||||
new Thread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
int port=pcitem.getPort();
|
||||
if(port<=0){port=20201;}
|
||||
List<ServerInfo> list = DBHelper.getInstance(getContext()).getDaoSession().getServerInfoDao().queryBuilder().where(new WhereCondition.StringCondition("_id=" + ServerID)).list();
|
||||
if (list.size() == 1) {
|
||||
SendMagic(pcitem.getMac(), pcitem.getIp(), list.get(0).getUrl(),port,list.get(0).getSuccessMark());
|
||||
}
|
||||
else
|
||||
{
|
||||
mUIHandler.sendEmptyMessage(Wake_UnfoundServer);
|
||||
}
|
||||
}
|
||||
}).start(); //这段代码在主线程中调用,开启一个线程
|
||||
}
|
||||
}
|
||||
}).start(); //这段代码在主线程中调用,开启一个线程
|
||||
}
|
||||
//确定按钮
|
||||
break;
|
||||
case R.id.iv_back:
|
||||
popToBack();
|
||||
break;
|
||||
case R.id.iv_more:
|
||||
showPoPup(view);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void SendMagic(String Mac,String IP,String Url,int Port,String SuccessMark)
|
||||
{
|
||||
String result;
|
||||
String _Url=Url;
|
||||
if(_Url.contains("{mac}")) {
|
||||
_Url = _Url.replace("{mac}", Mac);
|
||||
_Url = _Url.replace("{ip}", IP);
|
||||
_Url = _Url.replace("{port}", String.valueOf(Port));
|
||||
result = sendGetMessage(_Url,"utf-8");
|
||||
}
|
||||
else {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("a", "magic");
|
||||
params.put("mac", Mac);
|
||||
params.put("ip", IP);
|
||||
params.put("port", String.valueOf(Port));
|
||||
result = sendPostMessage(_Url, params, "utf-8");
|
||||
}
|
||||
if(result.equals("ok") || result.contains("success") || result.contains("成功") || (SuccessMark!=null && !SuccessMark.equals("") && result.contains(SuccessMark)))
|
||||
{
|
||||
mUIHandler.sendEmptyMessage(Wake_Successs);
|
||||
}
|
||||
else
|
||||
{
|
||||
mUIHandler.sendEmptyMessage(Wake_Failure);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param params 填写的url的参数
|
||||
* @param encode 字节编码
|
||||
* @return
|
||||
*/
|
||||
public static String sendPostMessage(String url, Map<String, String> params, String encode){
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
try {//把请求的主体写入正文!!
|
||||
URL uri = new URL(url);
|
||||
if(params != null&&!params.isEmpty()){
|
||||
//迭代器
|
||||
//Map.Entry 是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Value)
|
||||
for(Map.Entry<String, String> entry : params.entrySet()){
|
||||
buffer.append(entry.getKey()).append("=").
|
||||
append(URLEncoder.encode(entry.getValue(),encode)).
|
||||
append("&");
|
||||
}
|
||||
// System.out.println(buffer.toString());
|
||||
//删除最后一个字符&,多了一个;主体设置完毕
|
||||
buffer.deleteCharAt(buffer.length()-1);
|
||||
}
|
||||
HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
|
||||
connection.setConnectTimeout(3000);
|
||||
connection.setDoInput(true);//表示从服务器获取数据
|
||||
connection.setDoOutput(true);//表示向服务器写数据
|
||||
|
||||
connection.setRequestMethod("POST");
|
||||
//是否使用缓存
|
||||
connection.setUseCaches(false);
|
||||
//表示设置请求体的类型是文本类型
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
byte[] mydata = buffer.toString().getBytes();
|
||||
connection.setRequestProperty("Content-Length", String.valueOf(mydata.length));
|
||||
connection.connect(); //连接,不写也可以。。??有待了解
|
||||
|
||||
//获得输出流,向服务器输出数据
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(mydata,0,mydata.length);
|
||||
//获得服务器响应的结果和状态码
|
||||
int responseCode = connection.getResponseCode();
|
||||
if(responseCode == HttpURLConnection.HTTP_OK){
|
||||
return changeInputeStream(connection.getInputStream(),encode);
|
||||
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public static String sendGetMessage(String url, String encode)
|
||||
{
|
||||
//1. URL
|
||||
try
|
||||
{
|
||||
URL uri = new URL(url);
|
||||
//2. HttpURLConnection
|
||||
HttpURLConnection conn=(HttpURLConnection)uri.openConnection();
|
||||
//3. set(GET)
|
||||
conn.setRequestMethod("GET");
|
||||
//4. getInputStream
|
||||
InputStream is = conn.getInputStream();
|
||||
//5. 解析is,获取responseText,这里用缓冲字符
|
||||
int responseCode = conn.getResponseCode();
|
||||
if(responseCode == HttpURLConnection.HTTP_OK) {
|
||||
return changeInputeStream(conn.getInputStream(), encode);
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
/**
|
||||
* 将一个输入流转换成字符串
|
||||
* @param inputStream
|
||||
* @param encode
|
||||
* @return
|
||||
*/
|
||||
private static String changeInputeStream(InputStream inputStream, String encode) {
|
||||
//通常叫做内存流,写在内存中的
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
byte[] data = new byte[1024];
|
||||
int len = 0;
|
||||
String result = "";
|
||||
if(inputStream != null){
|
||||
try {
|
||||
while((len = inputStream.read(data))!=-1){
|
||||
data.toString();
|
||||
outputStream.write(data, 0, len);
|
||||
}
|
||||
//result是在服务器端设置的doPost函数中的
|
||||
result = new String(outputStream.toByteArray(),encode);
|
||||
outputStream.flush();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.profile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class MagicBoot {
|
||||
/**
|
||||
* 发送开机魔术包
|
||||
*/
|
||||
public static boolean SendMagic(String macAddress,String destIP)
|
||||
{
|
||||
return SendMagic(macAddress,destIP,20105);
|
||||
}
|
||||
/**
|
||||
* 发送开机魔术包
|
||||
*/
|
||||
public static boolean SendMagic(String macAddress,String destIP,int port)
|
||||
{
|
||||
try {
|
||||
if(macAddress==null || destIP==null){return false;}
|
||||
// String destIP = "255.255.255.255";// 广播地址
|
||||
// 检测 mac 地址,并将其转换为二进制
|
||||
byte[] destMac = getMacBytes(macAddress);
|
||||
if (destMac == null)
|
||||
return false;
|
||||
InetAddress destHost = InetAddress.getByName(destIP);
|
||||
// construct packet data
|
||||
byte[] magicBytes = new byte[102];
|
||||
// 将数据包的前6位放入0xFF即 "FF"的二进制
|
||||
for (int i = 0; i < 6; i++)
|
||||
magicBytes[i] = (byte) 0xFF;
|
||||
// 从第7个位置开始把mac地址放入16次
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < destMac.length; j++) {
|
||||
magicBytes[6 + destMac.length * i + j] = destMac[j];
|
||||
}
|
||||
}
|
||||
// create packet
|
||||
DatagramPacket dp = null;
|
||||
dp = new DatagramPacket(magicBytes, magicBytes.length, destHost, port);
|
||||
DatagramSocket ds = new DatagramSocket();
|
||||
ds.send(dp);
|
||||
ds.close();
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private static byte[] getMacBytes(String macStr) throws IllegalArgumentException {
|
||||
byte[] bytes = new byte[6];
|
||||
String[] hex = macStr.split("(\\:|\\-)");
|
||||
if (hex.length != 6) {
|
||||
throw new IllegalArgumentException("Invalid MAC address.");
|
||||
}
|
||||
try {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
bytes[i] = (byte) Integer.parseInt(hex[i], 16);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Invalid hex digit in MAC address.");
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.profile;
|
||||
|
||||
public class MsgCode {
|
||||
/**
|
||||
* 更新服务器列表
|
||||
*/
|
||||
public static final int ACTION_CODE_UPDATE_SERVERLIST = 100;
|
||||
/**
|
||||
* 发送编辑服务器消息
|
||||
*/
|
||||
public static final int ACTION_CODE_EDIT_SERVER = 101;
|
||||
/**
|
||||
* 获取服务器内容
|
||||
*/
|
||||
public static final int ACTION_CODE_GET_SERVER = 102;
|
||||
/**
|
||||
* 发送唤醒消息
|
||||
*/
|
||||
public static final int ACTION_CODE_WAKE_PC = 103;
|
||||
/**
|
||||
* 更新设备列表
|
||||
*/
|
||||
public static final int ACTION_CODE_UPDATE_PCLIST = 104;
|
||||
/**
|
||||
* 发送编辑设备消息
|
||||
*/
|
||||
public static final int ACTION_CODE_EDIT_PC = 105;
|
||||
/**
|
||||
* data key
|
||||
*/
|
||||
public static final String ACTION_DATA_KEY = "com.itryn.myeasywol.receiver.action.data.key";
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.profile;
|
||||
|
||||
import android.os.Message;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.itrycn.myeasywol.fragment.AboutFragment;
|
||||
import com.itrycn.myeasywol.fragment.SettingsFragment;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperTextView;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2019-10-30 00:18
|
||||
*/
|
||||
@Page(anim = CoreAnim.none)
|
||||
public class ProfileFragment extends BaseFragment implements SuperTextView.OnSuperTextViewClickListener {
|
||||
@BindView(R.id.menu_settings)
|
||||
SuperTextView menuSettings;
|
||||
@BindView(R.id.menu_about)
|
||||
SuperTextView menuAbout;
|
||||
@BindView(R.id.menu_yijian)
|
||||
SuperTextView menu_yijian;
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
menuSettings.setOnSuperTextViewClickListener(this);
|
||||
menuAbout.setOnSuperTextViewClickListener(this);
|
||||
menu_yijian.setOnSuperTextViewClickListener(this);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@Override
|
||||
public void onClick(SuperTextView view) {
|
||||
switch(view.getId()) {
|
||||
case R.id.menu_yijian:
|
||||
XToastUtils.toast("请通过邮箱:zilinsoft@qq.com进行反馈。");;
|
||||
break;
|
||||
case R.id.menu_settings:
|
||||
openNewPage(SettingsFragment.class);
|
||||
break;
|
||||
case R.id.menu_about:
|
||||
openNewPage(AboutFragment.class);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.profile;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.itrycn.myeasywol.utils.MyBroadcastReceiver;
|
||||
|
||||
public class SendMsg {
|
||||
/**
|
||||
* 发null广播
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static void sendUpdateServer(Context context) {
|
||||
MyBroadcastReceiver.sendReceiver(context, MsgCode.ACTION_CODE_UPDATE_SERVERLIST);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.fragment.trending;
|
||||
|
||||
import android.os.Message;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.BaseFragment;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2019-10-30 00:19
|
||||
*/
|
||||
@Page(anim = CoreAnim.none)
|
||||
public class TrendingFragment extends BaseFragment {
|
||||
|
||||
@Override
|
||||
protected void handleUIMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleWorkerMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_trending;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.tencent.mmkv.MMKV;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* MMKV工具类
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-07-04 10:20
|
||||
*/
|
||||
public final class MMKVUtils {
|
||||
|
||||
private MMKVUtils() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
private static MMKV sMMKV;
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static void init(Context context) {
|
||||
MMKV.initialize(context.getApplicationContext());
|
||||
sMMKV = MMKV.defaultMMKV();
|
||||
}
|
||||
|
||||
public static MMKV getsMMKV() {
|
||||
if (sMMKV == null) {
|
||||
sMMKV = MMKV.defaultMMKV();
|
||||
}
|
||||
return sMMKV;
|
||||
}
|
||||
|
||||
//=======================================键值保存==================================================//
|
||||
|
||||
/**
|
||||
* 保存键值
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static boolean put(String key, Object value) {
|
||||
if (value instanceof Integer) {
|
||||
return getsMMKV().encode(key, (Integer) value);
|
||||
} else if (value instanceof Float) {
|
||||
return getsMMKV().encode(key, (Float) value);
|
||||
} else if (value instanceof String) {
|
||||
return getsMMKV().encode(key, (String) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
return getsMMKV().encode(key, (Boolean) value);
|
||||
} else if (value instanceof Long) {
|
||||
return getsMMKV().encode(key, (Long) value);
|
||||
} else if (value instanceof Double) {
|
||||
return getsMMKV().encode(key, (Double) value);
|
||||
} else if (value instanceof Parcelable) {
|
||||
return getsMMKV().encode(key, (Parcelable) value);
|
||||
} else if (value instanceof byte[]) {
|
||||
return getsMMKV().encode(key, (byte[]) value);
|
||||
} else if (value instanceof Set) {
|
||||
return getsMMKV().encode(key, (Set<String>) value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//=======================================键值获取==================================================//
|
||||
|
||||
/**
|
||||
* 获取键值
|
||||
*
|
||||
* @param key
|
||||
* @param defaultValue
|
||||
* @return
|
||||
*/
|
||||
public static Object get(String key, Object defaultValue) {
|
||||
if (defaultValue instanceof Integer) {
|
||||
return getsMMKV().decodeInt(key, (Integer) defaultValue);
|
||||
} else if (defaultValue instanceof Float) {
|
||||
return getsMMKV().decodeFloat(key, (Float) defaultValue);
|
||||
} else if (defaultValue instanceof String) {
|
||||
return getsMMKV().decodeString(key, (String) defaultValue);
|
||||
} else if (defaultValue instanceof Boolean) {
|
||||
return getsMMKV().decodeBool(key, (Boolean) defaultValue);
|
||||
} else if (defaultValue instanceof Long) {
|
||||
return getsMMKV().decodeLong(key, (Long) defaultValue);
|
||||
} else if (defaultValue instanceof Double) {
|
||||
return getsMMKV().decodeDouble(key, (Double) defaultValue);
|
||||
} else if (defaultValue instanceof byte[]) {
|
||||
return getsMMKV().decodeBytes(key);
|
||||
} else if (defaultValue instanceof Set) {
|
||||
return getsMMKV().decodeStringSet(key, (Set<String>) defaultValue);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据key获取boolean值
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return
|
||||
*/
|
||||
public static boolean getBoolean(String key, boolean defValue) {
|
||||
try {
|
||||
return getsMMKV().getBoolean(key, defValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key获取long值
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return
|
||||
*/
|
||||
public static long getLong(String key, long defValue) {
|
||||
try {
|
||||
return getsMMKV().getLong(key, defValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key获取float值
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return
|
||||
*/
|
||||
public static float getFloat(String key, float defValue) {
|
||||
try {
|
||||
return getsMMKV().getFloat(key, defValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key获取String值
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return
|
||||
*/
|
||||
public static String getString(String key, String defValue) {
|
||||
try {
|
||||
return getsMMKV().getString(key, defValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key获取int值
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return
|
||||
*/
|
||||
public static int getInt(String key, int defValue) {
|
||||
try {
|
||||
return getsMMKV().getInt(key, defValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据key获取double值
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return
|
||||
*/
|
||||
public static double getDouble(String key, double defValue) {
|
||||
try {
|
||||
return getsMMKV().decodeDouble(key, defValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取对象
|
||||
*
|
||||
* @param key
|
||||
* @param tClass 类型
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T extends Parcelable> T getObject(String key, Class<T> tClass) {
|
||||
return getsMMKV().decodeParcelable(key, tClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象
|
||||
*
|
||||
* @param key
|
||||
* @param tClass 类型
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T extends Parcelable> T getObject(String key, Class<T> tClass, T defValue) {
|
||||
try {
|
||||
return getsMMKV().decodeParcelable(key, tClass, defValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断键值对是否存在
|
||||
*
|
||||
* @param key 键
|
||||
* @return 键值对是否存在
|
||||
*/
|
||||
public static boolean containsKey(String key) {
|
||||
return getsMMKV().containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除指定键值对
|
||||
*
|
||||
* @param key 键
|
||||
*/
|
||||
public static void remove(String key) {
|
||||
getsMMKV().remove(key).apply();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class MyBroadcastReceiver {
|
||||
/**
|
||||
* audio的receiver的action
|
||||
*/
|
||||
private static final String RECEIVER_ACTION = "com.itrycn.myeasywol.receiver.action";
|
||||
/**
|
||||
* code key
|
||||
*/
|
||||
public static final String ACTION_CODE_KEY = "com.itrycn.myeasywol.action.code.key";
|
||||
/**
|
||||
* bundle key
|
||||
*/
|
||||
public static final String ACTION_BUNDLEKEY = "com.itrycn.myeasywol.receiver.action.bundle.key";
|
||||
/**
|
||||
* 动态广播自定义权限
|
||||
*/
|
||||
public final static String RECEIVER_PERMISSION = "com.itrycn.myeasywol.permissions.RECEIVER";
|
||||
private android.content.BroadcastReceiver mBroadcastReceiver;
|
||||
private IntentFilter mIntentFilter;
|
||||
private MyReceiverListener mReceiverListener;
|
||||
|
||||
public MyBroadcastReceiver() {
|
||||
mIntentFilter = new IntentFilter();
|
||||
mIntentFilter.addAction(RECEIVER_ACTION);
|
||||
}
|
||||
/**
|
||||
* 注册广播
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public void registerReceiver(Context context) {
|
||||
|
||||
mBroadcastReceiver = new android.content.BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
if (mReceiverListener != null) {
|
||||
int code = intent.getIntExtra(ACTION_CODE_KEY, -1);
|
||||
if (code != -1) {
|
||||
mReceiverListener.onReceive(context, intent, code);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
context.registerReceiver(mBroadcastReceiver, mIntentFilter, RECEIVER_PERMISSION, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发广播
|
||||
*
|
||||
* @param context
|
||||
* @param code
|
||||
* @param bundleKey
|
||||
* @param bundleValue
|
||||
*/
|
||||
public static void sendReceiver(Context context, int code, String bundleKey, Bundle bundleValue) {
|
||||
Intent intent = new Intent(RECEIVER_ACTION);
|
||||
intent.putExtra(ACTION_CODE_KEY, code);
|
||||
if (!TextUtils.isEmpty(bundleKey) && bundleValue != null) {
|
||||
intent.putExtra(bundleKey, bundleValue);
|
||||
}
|
||||
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
context.sendBroadcast(intent,RECEIVER_PERMISSION);
|
||||
}
|
||||
/**
|
||||
* 发广播
|
||||
*
|
||||
* @param context
|
||||
* @param code
|
||||
*/
|
||||
public static void sendReceiver(Context context, int code) {
|
||||
sendReceiver(context, code, null, null);
|
||||
}
|
||||
/**
|
||||
* 取消注册广播
|
||||
*/
|
||||
public void unregisterReceiver(Context context) {
|
||||
if (mBroadcastReceiver != null) {
|
||||
context.unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
public interface MyReceiverListener {
|
||||
void onReceive(Context context, Intent intent, int code);
|
||||
}
|
||||
|
||||
public void setReceiverListener(MyReceiverListener ReceiverListener) {
|
||||
this.mReceiverListener = ReceiverListener;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.itrycn.myeasywol.utils;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* desc : Random Utils
|
||||
* author : xuexiang
|
||||
* time : 2018/4/28 上午12:41
|
||||
* </pre>
|
||||
* <ul>
|
||||
* Shuffling algorithm
|
||||
* <li>{@link #shuffle(Object[])} Shuffling algorithm, Randomly permutes the specified array using a default source of
|
||||
* randomness</li>
|
||||
* <li>{@link #shuffle(Object[], int)} Shuffling algorithm, Randomly permutes the specified array</li>
|
||||
* <li>{@link #shuffle(int[])} Shuffling algorithm, Randomly permutes the specified int array using a default source of
|
||||
* randomness</li>
|
||||
* <li>{@link #shuffle(int[], int)} Shuffling algorithm, Randomly permutes the specified int array</li>
|
||||
* </ul>
|
||||
* <ul>
|
||||
* get random int
|
||||
* <li>{@link #getRandom(int)} get random int between 0 and max</li>
|
||||
* <li>{@link #getRandom(int, int)} get random int between min and max</li>
|
||||
* </ul>
|
||||
* <ul>
|
||||
* get random numbers or letters
|
||||
* <li>{@link #getRandomCapitalLetters(int)} get a fixed-length random string, its a mixture of uppercase letters</li>
|
||||
* <li>{@link #getRandomLetters(int)} get a fixed-length random string, its a mixture of uppercase and lowercase letters
|
||||
* </li>
|
||||
* <li>{@link #getRandomLowerCaseLetters(int)} get a fixed-length random string, its a mixture of lowercase letters</li>
|
||||
* <li>{@link #getRandomNumbers(int)} get a fixed-length random string, its a mixture of numbers</li>
|
||||
* <li>{@link #getRandomNumbersAndLetters(int)} get a fixed-length random string, its a mixture of uppercase, lowercase
|
||||
* letters and numbers</li>
|
||||
* <li>{@link #getRandom(String, int)} get a fixed-length random string, its a mixture of chars in source</li>
|
||||
* <li>{@link #getRandom(char[], int)} get a fixed-length random string, its a mixture of chars in sourceChar</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
public final class RandomUtils {
|
||||
|
||||
public static final String NUMBERS_AND_LETTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public static final String NUMBERS = "0123456789";
|
||||
public static final String LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public static final String LOWER_CASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
/**
|
||||
* Don't let anyone instantiate this class.
|
||||
*/
|
||||
private RandomUtils() {
|
||||
throw new Error("Do not need instantiate!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 在数字和英文字母中获取一个定长的随机字符串
|
||||
*
|
||||
* @param length 长度
|
||||
* @return 随机字符串
|
||||
* @see RandomUtils#getRandom(String source, int length)
|
||||
*/
|
||||
public static String getRandomNumbersAndLetters(int length) {
|
||||
return getRandom(NUMBERS_AND_LETTERS, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在数字中获取一个定长的随机字符串
|
||||
*
|
||||
* @param length 长度
|
||||
* @return 随机数字符串
|
||||
* @see RandomUtils#getRandom(String source, int length)
|
||||
*/
|
||||
public static String getRandomNumbers(int length) {
|
||||
return getRandom(NUMBERS, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在英文字母中获取一个定长的随机字符串
|
||||
*
|
||||
* @param length 长度
|
||||
* @return 随机字母字符串
|
||||
* @see RandomUtils#getRandom(String source, int length)
|
||||
*/
|
||||
public static String getRandomLetters(int length) {
|
||||
return getRandom(LETTERS, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在大写英文字母中获取一个定长的随机字符串
|
||||
*
|
||||
* @param length 长度
|
||||
* @return 随机字符串 只包含大写字母
|
||||
* @see RandomUtils#getRandom(String source, int length)
|
||||
*/
|
||||
public static String getRandomCapitalLetters(int length) {
|
||||
return getRandom(CAPITAL_LETTERS, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在小写英文字母中获取一个定长的随机字符串
|
||||
*
|
||||
* @param length 长度
|
||||
* @return 随机字符串 只包含小写字母
|
||||
* @see RandomUtils#getRandom(String source, int length)
|
||||
*/
|
||||
public static String getRandomLowerCaseLetters(int length) {
|
||||
return getRandom(LOWER_CASE_LETTERS, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在一个字符数组源中获取一个定长的随机字符串
|
||||
*
|
||||
* @param source 源字符串
|
||||
* @param length 长度
|
||||
* @return <ul>
|
||||
* <li>if source is null or empty, return null</li>
|
||||
* <li>else see {@link RandomUtils#getRandom(char[] sourceChar, int length)}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static String getRandom(String source, int length) {
|
||||
return TextUtils.isEmpty(source) ? null : getRandom(source.toCharArray(), length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在一个字符数组源中获取一个定长的随机字符串
|
||||
*
|
||||
* @param sourceChar 字符数组源
|
||||
* @param length 长度
|
||||
* @return <ul>
|
||||
* <li>if sourceChar is null or empty, return null</li>
|
||||
* <li>if length less than 0, return null</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static String getRandom(char[] sourceChar, int length) {
|
||||
if (sourceChar == null || sourceChar.length == 0 || length < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder str = new StringBuilder(length);
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < length; i++) {
|
||||
str.append(sourceChar[random.nextInt(sourceChar.length)]);
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* get random int between 0 and max
|
||||
*
|
||||
* @param max 最大随机数
|
||||
* @return <ul>
|
||||
* <li>if max <= 0, return 0</li>
|
||||
* <li>else return random int between 0 and max</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static int getRandom(int max) {
|
||||
return getRandom(0, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* get random int between min and max
|
||||
*
|
||||
* @param min 最小随机数
|
||||
* @param max 最大随机数
|
||||
* @return <ul>
|
||||
* <li>if min > max, return 0</li>
|
||||
* <li>if min == max, return min</li>
|
||||
* <li>else return random int between min and max</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static int getRandom(int min, int max) {
|
||||
if (min > max) {
|
||||
return 0;
|
||||
}
|
||||
if (min == max) {
|
||||
return min;
|
||||
}
|
||||
return min + new Random().nextInt(max - min);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机颜色
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static int getRandomColor() {
|
||||
Random random = new Random();
|
||||
int r = random.nextInt(256);
|
||||
int g = random.nextInt(256);
|
||||
int b = random.nextInt(256);
|
||||
return Color.rgb(r, g, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机打乱数组中的内容
|
||||
*
|
||||
* @param objArray
|
||||
* @return
|
||||
*/
|
||||
public static boolean shuffle(Object[] objArray) {
|
||||
if (objArray == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return shuffle(objArray, getRandom(objArray.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机打乱数组中的内容
|
||||
*
|
||||
* @param objArray
|
||||
* @param shuffleCount
|
||||
* @return
|
||||
*/
|
||||
public static boolean shuffle(Object[] objArray, int shuffleCount) {
|
||||
int length;
|
||||
if (objArray == null || shuffleCount < 0 || (length = objArray.length) < shuffleCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= shuffleCount; i++) {
|
||||
int random = getRandom(length - i);
|
||||
Object temp = objArray[length - i];
|
||||
objArray[length - i] = objArray[random];
|
||||
objArray[random] = temp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机打乱数组中的内容
|
||||
*
|
||||
* @param intArray
|
||||
* @return
|
||||
*/
|
||||
public static int[] shuffle(int[] intArray) {
|
||||
if (intArray == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return shuffle(intArray, getRandom(intArray.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机打乱数组中的内容
|
||||
*
|
||||
* @param intArray
|
||||
* @param shuffleCount
|
||||
* @return
|
||||
*/
|
||||
public static int[] shuffle(int[] intArray, int shuffleCount) {
|
||||
int length;
|
||||
if (intArray == null || shuffleCount < 0 || (length = intArray.length) < shuffleCount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int[] out = new int[shuffleCount];
|
||||
for (int i = 1; i <= shuffleCount; i++) {
|
||||
int random = getRandom(length - i);
|
||||
out[i - 1] = intArray[random];
|
||||
int temp = intArray[length - i];
|
||||
intArray[length - i] = intArray[random];
|
||||
intArray[random] = temp;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.itrycn.myeasywol.utils;
|
||||
|
||||
|
||||
/**
|
||||
* SharedPreferences管理工具基类
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/11/27 下午5:16
|
||||
*/
|
||||
public final class SettingUtils {
|
||||
|
||||
private SettingUtils() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
private static final String IS_FIRST_OPEN_KEY = "is_first_open_key";
|
||||
|
||||
private static final String IS_AGREE_PRIVACY_KEY = "is_agree_privacy_key";
|
||||
|
||||
/**
|
||||
* 是否是第一次启动
|
||||
*/
|
||||
public static boolean isFirstOpen() {
|
||||
return MMKVUtils.getBoolean(IS_FIRST_OPEN_KEY, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否是第一次启动
|
||||
*/
|
||||
public static void setIsFirstOpen(boolean isFirstOpen) {
|
||||
MMKVUtils.put(IS_FIRST_OPEN_KEY, isFirstOpen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 是否同意隐私政策
|
||||
*/
|
||||
public static boolean isAgreePrivacy() {
|
||||
return MMKVUtils.getBoolean(IS_AGREE_PRIVACY_KEY, false);
|
||||
}
|
||||
|
||||
public static void setIsAgreePrivacy(boolean isAgreePrivacy) {
|
||||
MMKVUtils.put(IS_AGREE_PRIVACY_KEY, isAgreePrivacy);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
|
||||
/**
|
||||
* Token管理工具
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-17 22:37
|
||||
*/
|
||||
public final class TokenUtils {
|
||||
|
||||
private static String sToken;
|
||||
|
||||
private static final String KEY_TOKEN = "com.itrycn.myeasywol.utils.KEY_TOKEN";
|
||||
|
||||
private TokenUtils() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
private static final String KEY_PROFILE_CHANNEL = "github";
|
||||
|
||||
/**
|
||||
* 初始化Token信息
|
||||
*/
|
||||
public static void init(Context context) {
|
||||
MMKVUtils.init(context);
|
||||
sToken = MMKVUtils.getString(KEY_TOKEN, "");
|
||||
}
|
||||
|
||||
public static void setToken(String token) {
|
||||
sToken = token;
|
||||
MMKVUtils.put(KEY_TOKEN, token);
|
||||
}
|
||||
|
||||
public static void clearToken() {
|
||||
sToken = null;
|
||||
MMKVUtils.remove(KEY_TOKEN);
|
||||
}
|
||||
|
||||
public static String getToken() {
|
||||
return sToken;
|
||||
}
|
||||
|
||||
public static boolean hasToken() {
|
||||
return MMKVUtils.containsKey(KEY_TOKEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理登录成功的事件
|
||||
*
|
||||
* @param token 账户信息
|
||||
*/
|
||||
public static boolean handleLoginSuccess(String token) {
|
||||
if (!StringUtils.isEmpty(token)) {
|
||||
XToastUtils.success("登录成功!");
|
||||
setToken(token);
|
||||
return true;
|
||||
} else {
|
||||
XToastUtils.error("登录失败!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理登出的事件
|
||||
*/
|
||||
public static void handleLogoutSuccess() {
|
||||
//登出时,清除账号信息
|
||||
clearToken();
|
||||
XToastUtils.success("登出成功!");
|
||||
//跳转到登录页
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itrycn.myeasywol.R;
|
||||
import com.itrycn.myeasywol.core.webview.AgentWebActivity;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.widget.dialog.DialogLoader;
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction;
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
|
||||
import static com.itrycn.myeasywol.core.webview.AgentWebFragment.KEY_URL;
|
||||
|
||||
/**
|
||||
* 工具类
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020-02-23 15:12
|
||||
*/
|
||||
public final class Utils {
|
||||
|
||||
private Utils() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里填写你的应用隐私政策网页地址
|
||||
*/
|
||||
private static final String PRIVACY_URL = "https://gitee.com/xuexiangjys/TemplateAppProject/raw/master/LICENSE";
|
||||
|
||||
/**
|
||||
* 显示隐私政策的提示
|
||||
*
|
||||
* @param context
|
||||
* @param submitListener 同意的监听
|
||||
* @return
|
||||
*/
|
||||
public static Dialog showPrivacyDialog(Context context, MaterialDialog.SingleButtonCallback submitListener) {
|
||||
MaterialDialog dialog = new MaterialDialog.Builder(context).title(R.string.title_reminder).autoDismiss(false).cancelable(false)
|
||||
.positiveText(R.string.lab_agree).onPositive((dialog1, which) -> {
|
||||
if (submitListener != null) {
|
||||
submitListener.onClick(dialog1, which);
|
||||
} else {
|
||||
dialog1.dismiss();
|
||||
}
|
||||
})
|
||||
.negativeText(R.string.lab_disagree).onNegative(new MaterialDialog.SingleButtonCallback() {
|
||||
@Override
|
||||
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
|
||||
dialog.dismiss();
|
||||
DialogLoader.getInstance().showConfirmDialog(context, ResUtils.getString(R.string.title_reminder), String.format(ResUtils.getString(R.string.content_privacy_explain_again), ResUtils.getString(R.string.app_name)), ResUtils.getString(R.string.lab_look_again), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
showPrivacyDialog(context, submitListener);
|
||||
}
|
||||
}, ResUtils.getString(R.string.lab_still_disagree), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
DialogLoader.getInstance().showConfirmDialog(context, ResUtils.getString(R.string.content_think_about_it_again), ResUtils.getString(R.string.lab_look_again), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
showPrivacyDialog(context, submitListener);
|
||||
}
|
||||
}, ResUtils.getString(R.string.lab_exit_app), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
XUtil.exitApp();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}).build();
|
||||
dialog.setContent(getPrivacyContent(context));
|
||||
//开始响应点击事件
|
||||
dialog.getContentView().setMovementMethod(LinkMovementMethod.getInstance());
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 隐私政策说明
|
||||
*/
|
||||
private static SpannableStringBuilder getPrivacyContent(Context context) {
|
||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder()
|
||||
.append(" 欢迎来到").append(ResUtils.getString(R.string.app_name)).append("!\n")
|
||||
.append(" 我们深知个人信息对你的重要性,也感谢你对我们的信任。\n")
|
||||
.append(" 为了更好地保护你的权益,同时遵守相关监管的要求,我们将通过");
|
||||
stringBuilder.append(getPrivacyLink(context, PRIVACY_URL))
|
||||
.append("向你说明我们会如何收集、存储、保护、使用及对外提供你的信息,并说明你享有的权利。\n")
|
||||
.append(" 更多详情,敬请查阅")
|
||||
.append(getPrivacyLink(context, PRIVACY_URL))
|
||||
.append("全文。");
|
||||
return stringBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context 隐私政策的链接
|
||||
* @return
|
||||
*/
|
||||
private static SpannableString getPrivacyLink(Context context, String privacyUrl) {
|
||||
String privacyName = String.format(ResUtils.getString(R.string.lab_privacy_name), ResUtils.getString(R.string.app_name));
|
||||
SpannableString spannableString = new SpannableString(privacyName);
|
||||
spannableString.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull View widget) {
|
||||
goWeb(context, privacyUrl);
|
||||
}
|
||||
}, 0, privacyName.length(), Spanned.SPAN_MARK_MARK);
|
||||
return spannableString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 请求浏览器
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public static void goWeb(Context context, final String url) {
|
||||
Intent intent = new Intent(context, AgentWebActivity.class);
|
||||
intent.putExtra(KEY_URL, url);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否是深色的颜色
|
||||
*
|
||||
* @param color
|
||||
* @return
|
||||
*/
|
||||
public static boolean isColorDark(@ColorInt int color) {
|
||||
double darkness =
|
||||
1
|
||||
- (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color))
|
||||
/ 255;
|
||||
return darkness >= 0.382;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils;
|
||||
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import com.xuexiang.xui.XUI;
|
||||
import com.xuexiang.xui.widget.toast.XToast;
|
||||
|
||||
/**
|
||||
* xtoast 工具类
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-06-30 19:04
|
||||
*/
|
||||
public final class XToastUtils {
|
||||
|
||||
|
||||
private XToastUtils() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
static {
|
||||
XToast.Config.get()
|
||||
.setAlpha(200)
|
||||
.allowQueue(false);
|
||||
}
|
||||
|
||||
//======普通土司=======//
|
||||
|
||||
@MainThread
|
||||
public static void toast(@NonNull CharSequence message) {
|
||||
XToast.normal(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void toast(@StringRes int message) {
|
||||
XToast.normal(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void toast(@NonNull CharSequence message, int duration) {
|
||||
XToast.normal(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void toast(@StringRes int message, int duration) {
|
||||
XToast.normal(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
//======错误【红色】=======//
|
||||
|
||||
@MainThread
|
||||
public static void error(@NonNull Throwable throwable) {
|
||||
XToast.error(XUI.getContext(), throwable.getMessage()).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void error(@NonNull CharSequence message) {
|
||||
XToast.error(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void error(@StringRes int message) {
|
||||
XToast.error(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void error(@NonNull CharSequence message, int duration) {
|
||||
XToast.error(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void error(@StringRes int message, int duration) {
|
||||
XToast.error(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
//======成功【绿色】=======//
|
||||
|
||||
@MainThread
|
||||
public static void success(@NonNull CharSequence message) {
|
||||
XToast.success(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void success(@StringRes int message) {
|
||||
XToast.success(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void success(@NonNull CharSequence message, int duration) {
|
||||
XToast.success(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void success(@StringRes int message, int duration) {
|
||||
XToast.success(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
//======信息【蓝色】=======//
|
||||
|
||||
@MainThread
|
||||
public static void info(@NonNull CharSequence message) {
|
||||
XToast.info(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void info(@StringRes int message) {
|
||||
XToast.info(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void info(@NonNull CharSequence message, int duration) {
|
||||
XToast.info(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void info(@StringRes int message, int duration) {
|
||||
XToast.info(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
//=======警告【黄色】======//
|
||||
|
||||
@MainThread
|
||||
public static void warning(@NonNull CharSequence message) {
|
||||
XToast.warning(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void warning(@StringRes int message) {
|
||||
XToast.warning(XUI.getContext(), message).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void warning(@NonNull CharSequence message, int duration) {
|
||||
XToast.warning(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public static void warning(@StringRes int message, int duration) {
|
||||
XToast.warning(XUI.getContext(), message, duration).show();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils.sdkinit;
|
||||
|
||||
import com.github.anrwatchdog.ANRWatchDog;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* ANR看门狗监听器初始化
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020-02-18 15:08
|
||||
*/
|
||||
public final class ANRWatchDogInit {
|
||||
|
||||
private static final String TAG = "ANRWatchDog";
|
||||
|
||||
private ANRWatchDogInit() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
/**
|
||||
* ANR看门狗
|
||||
*/
|
||||
private static ANRWatchDog sANRWatchDog;
|
||||
|
||||
/**
|
||||
* ANR监听触发的时间
|
||||
*/
|
||||
private static final int ANR_DURATION = 4000;
|
||||
|
||||
|
||||
/**
|
||||
* ANR静默处理【就是不处理,直接记录一下日志】
|
||||
*/
|
||||
private final static ANRWatchDog.ANRListener SILENT_LISTENER = error -> Logger.eTag(TAG, error);
|
||||
|
||||
/**
|
||||
* ANR自定义处理【可以是记录日志用于上传】
|
||||
*/
|
||||
private final static ANRWatchDog.ANRListener CUSTOM_LISTENER = error -> {
|
||||
Logger.eTag(TAG, "Detected Application Not Responding!", error);
|
||||
//这里进行ANR的捕获后的操作
|
||||
|
||||
throw error;
|
||||
};
|
||||
|
||||
public static void init() {
|
||||
//这里设置监听的间隔为2秒
|
||||
sANRWatchDog = new ANRWatchDog(2000);
|
||||
sANRWatchDog.setANRInterceptor(duration -> {
|
||||
long ret = ANR_DURATION - duration;
|
||||
if (ret > 0) {
|
||||
Logger.wTag(TAG, "Intercepted ANR that is too short (" + duration + " ms), postponing for " + ret + " ms.");
|
||||
}
|
||||
//当返回是0或者负数时,就会触发ANR监听回调
|
||||
return ret;
|
||||
}).setANRListener(SILENT_LISTENER).start();
|
||||
}
|
||||
|
||||
public static ANRWatchDog getANRWatchDog() {
|
||||
return sANRWatchDog;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils.sdkinit;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.itrycn.myeasywol.MyApp;
|
||||
import com.itrycn.myeasywol.core.BaseActivity;
|
||||
import com.itrycn.myeasywol.utils.TokenUtils;
|
||||
import com.itrycn.myeasywol.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.XAOP;
|
||||
import com.xuexiang.xhttp2.XHttpSDK;
|
||||
import com.xuexiang.xpage.AppPageConfig;
|
||||
import com.xuexiang.xpage.PageConfig;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.XUI;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
|
||||
/**
|
||||
* X系列基础库初始化
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-06-30 23:54
|
||||
*/
|
||||
public final class XBasicLibInit {
|
||||
|
||||
private XBasicLibInit() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化基础库SDK
|
||||
*/
|
||||
public static void init(Application application) {
|
||||
//工具类
|
||||
initXUtil(application);
|
||||
|
||||
//网络请求框架
|
||||
initXHttp2(application);
|
||||
|
||||
//页面框架
|
||||
initXPage(application);
|
||||
|
||||
//切片框架
|
||||
initXAOP(application);
|
||||
|
||||
//UI框架
|
||||
initXUI(application);
|
||||
|
||||
//路由框架
|
||||
initRouter(application);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化XUtil工具类
|
||||
*/
|
||||
private static void initXUtil(Application application) {
|
||||
XUtil.init(application);
|
||||
XUtil.debug(MyApp.isDebug());
|
||||
TokenUtils.init(application);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化XHttp2
|
||||
*/
|
||||
private static void initXHttp2(Application application) {
|
||||
//初始化网络请求框架,必须首先执行
|
||||
XHttpSDK.init(application);
|
||||
//需要调试的时候执行
|
||||
if (MyApp.isDebug()) {
|
||||
XHttpSDK.debug();
|
||||
}
|
||||
// XHttpSDK.debug(new CustomLoggingInterceptor()); //设置自定义的日志打印拦截器
|
||||
//设置网络请求的全局基础地址
|
||||
XHttpSDK.setBaseUrl("https://gitee.com/");
|
||||
// //设置动态参数添加拦截器
|
||||
// XHttpSDK.addInterceptor(new CustomDynamicInterceptor());
|
||||
// //请求失效校验拦截器
|
||||
// XHttpSDK.addInterceptor(new CustomExpiredInterceptor());
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化XPage页面框架
|
||||
*/
|
||||
private static void initXPage(Application application) {
|
||||
PageConfig.getInstance()
|
||||
//页面注册
|
||||
.setPageConfiguration(context -> {
|
||||
//自动注册页面,是编译时自动生成的,build一下就出来了
|
||||
return AppPageConfig.getInstance().getPages();
|
||||
})
|
||||
.debug(MyApp.isDebug() ? "PageLog" : null)
|
||||
.enableWatcher(MyApp.isDebug())
|
||||
.setContainActivityClazz(BaseActivity.class)
|
||||
.init(application);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化XAOP
|
||||
*/
|
||||
private static void initXAOP(Application application) {
|
||||
XAOP.init(application);
|
||||
XAOP.debug(MyApp.isDebug());
|
||||
//设置动态申请权限切片 申请权限被拒绝的事件响应监听
|
||||
XAOP.setOnPermissionDeniedListener(permissionsDenied -> XToastUtils.error("权限申请被拒绝:" + StringUtils.listToString(permissionsDenied, ",")));
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化XUI框架
|
||||
*/
|
||||
private static void initXUI(Application application) {
|
||||
XUI.init(application);
|
||||
XUI.debug(MyApp.isDebug());
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化路由框架
|
||||
*/
|
||||
private static void initRouter(Application application) {
|
||||
// 这两行必须写在init之前,否则这些配置在init过程中将无效
|
||||
if (MyApp.isDebug()) {
|
||||
XRouter.openLog(); // 打印日志
|
||||
XRouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
|
||||
}
|
||||
XRouter.init(application);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils.sdkinit;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.itrycn.myeasywol.MyApp;
|
||||
import com.itrycn.myeasywol.utils.update.CustomUpdateDownloader;
|
||||
import com.itrycn.myeasywol.utils.update.CustomUpdateFailureListener;
|
||||
import com.itrycn.myeasywol.utils.update.XHttpUpdateHttpServiceImpl;
|
||||
import com.xuexiang.xupdate.XUpdate;
|
||||
import com.xuexiang.xupdate.utils.UpdateUtils;
|
||||
|
||||
/**
|
||||
* XUpdate 版本更新 SDK 初始化
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-06-18 15:51
|
||||
*/
|
||||
public final class XUpdateInit {
|
||||
|
||||
private XUpdateInit() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用版本更新的检查地址
|
||||
*/
|
||||
private static final String KEY_UPDATE_URL = "http://www.itrycn.com/update/myeasywol.json";
|
||||
|
||||
public static void init(Application application) {
|
||||
XUpdate.get()
|
||||
.debug(MyApp.isDebug())
|
||||
//默认设置只在wifi下检查版本更新
|
||||
.isWifiOnly(false)
|
||||
//默认设置使用get请求检查版本
|
||||
.isGet(true)
|
||||
//默认设置非自动模式,可根据具体使用配置
|
||||
.isAutoMode(false)
|
||||
//设置默认公共请求参数
|
||||
.param("versionCode", UpdateUtils.getVersionCode(application))
|
||||
.param("appKey", application.getPackageName())
|
||||
//这个必须设置!实现网络请求功能。
|
||||
.setIUpdateHttpService(new XHttpUpdateHttpServiceImpl())
|
||||
.setIUpdateDownLoader(new CustomUpdateDownloader())
|
||||
//这个必须初始化
|
||||
.init(application);
|
||||
}
|
||||
|
||||
/**
|
||||
* 进行版本更新检查
|
||||
*/
|
||||
public static void checkUpdate(Context context, boolean needErrorTip) {
|
||||
XUpdate.newBuild(context).updateUrl(KEY_UPDATE_URL).update();
|
||||
XUpdate.get().setOnUpdateFailureListener(new CustomUpdateFailureListener(needErrorTip));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils.service;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xrouter.annotation.Router;
|
||||
import com.xuexiang.xrouter.facade.service.SerializationService;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* @author XUE
|
||||
* @since 2019/3/27 16:39
|
||||
*/
|
||||
@Router(path = "/service/json")
|
||||
public class JsonSerializationService implements SerializationService {
|
||||
/**
|
||||
* 对象序列化为json
|
||||
*
|
||||
* @param instance obj
|
||||
* @return json string
|
||||
*/
|
||||
@Override
|
||||
public String object2Json(Object instance) {
|
||||
return JsonUtil.toJson(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* json反序列化为对象
|
||||
*
|
||||
* @param input json string
|
||||
* @param clazz object type
|
||||
* @return instance of object
|
||||
*/
|
||||
@Override
|
||||
public <T> T parseObject(String input, Type clazz) {
|
||||
return JsonUtil.fromJson(input, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 进程初始化的方法
|
||||
*
|
||||
* @param context 上下文
|
||||
*/
|
||||
@Override
|
||||
public void init(Context context) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.itrycn.myeasywol.utils.update;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.xuexiang.xupdate.entity.UpdateEntity;
|
||||
import com.xuexiang.xupdate.proxy.impl.DefaultUpdateDownloader;
|
||||
import com.xuexiang.xupdate.service.OnFileDownloadListener;
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
|
||||
/**
|
||||
* 重写DefaultUpdateDownloader,在取消下载时,弹出提示
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-06-14 23:47
|
||||
*/
|
||||
public class CustomUpdateDownloader extends DefaultUpdateDownloader {
|
||||
|
||||
private boolean mIsStartDownload;
|
||||
|
||||
@Override
|
||||
public void startDownload(@NonNull UpdateEntity updateEntity, @Nullable OnFileDownloadListener downloadListener) {
|
||||
super.startDownload(updateEntity, downloadListener);
|
||||
mIsStartDownload = true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelDownload() {
|
||||
super.cancelDownload();
|
||||
if (mIsStartDownload) {
|
||||
mIsStartDownload = false;
|
||||
ActivityUtils.startActivity(UpdateTipDialog.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user