1
0

add v1.0.0

This commit is contained in:
田梓萱 2022-03-26 23:24:22 +08:00
parent d189281a40
commit 8ca49856c2
121 changed files with 9108 additions and 0 deletions

16
DaKa/.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
*.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
/entry/.preview
.cxx
/node_modules

3
DaKa/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

6
DaKa/.idea/compiler.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

24
DaKa/.idea/gradle.xml generated Normal file
View File

@ -0,0 +1,24 @@
<?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="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="C:\Program Files\Huawei\DevEco Studio 3.0.0.800\tools\gradle" />
<option name="gradleJvm" value="#JAVA_INTERNAL" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/entry" />
<option value="$PROJECT_DIR$/jianjia" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

View File

@ -0,0 +1,36 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="date" />
</inspection_tool>
</profile>
</component>

141
DaKa/.idea/intellij-javadocs-4.0.1.xml generated Normal file
View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaDocConfiguration">
<GENERAL>
<MODE>UPDATE</MODE>
<OVERRIDDEN_METHODS>false</OVERRIDDEN_METHODS>
<SPLITTED_CLASS_NAME>true</SPLITTED_CLASS_NAME>
<LEVELS>
<LEVEL>TYPE</LEVEL>
<LEVEL>FIELD</LEVEL>
<LEVEL>METHOD</LEVEL>
</LEVELS>
<VISIBILITIES>
<VISIBILITY>DEFAULT</VISIBILITY>
<VISIBILITY>PUBLIC</VISIBILITY>
<VISIBILITY>PROTECTED</VISIBILITY>
</VISIBILITIES>
</GENERAL>
<TEMPLATES>
<CLASSES>
<CLASS>
<KEY>^.*(public|protected|private)*.+interface\s+\w+.*</KEY>
<VALUE>/**\n
* The interface ${name}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;&lt;#list element.typeParameters as typeParameter&gt; * @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt; */</VALUE>
</CLASS>
<CLASS>
<KEY>^.*(public|protected|private)*.+enum\s+\w+.*</KEY>
<VALUE>/**\n
* The enum ${name}.\n
*/</VALUE>
</CLASS>
<CLASS>
<KEY>^.*(public|protected|private)*.+class\s+\w+.*</KEY>
<VALUE>/**\n
* The type ${name}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;&lt;#list element.typeParameters as typeParameter&gt; * @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt; */</VALUE>
</CLASS>
<CLASS>
<KEY>.+</KEY>
<VALUE>/**\n
* The type ${name}.\n
*/</VALUE>
</CLASS>
</CLASSES>
<CONSTRUCTORS>
<CONSTRUCTOR>
<KEY>.+</KEY>
<VALUE>/**\n
* Instantiates a new ${name}.\n
&lt;#if element.parameterList.parameters?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.parameterList.parameters as parameter&gt; * @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;&lt;#if element.throwsList.referenceElements?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.throwsList.referenceElements as exception&gt; * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt; */</VALUE>
</CONSTRUCTOR>
</CONSTRUCTORS>
<METHODS>
<METHOD>
<KEY>^.*(public|protected|private)*\s*.*(\w(\s*&lt;.+&gt;)*)+\s+get\w+\s*\(.*\).+</KEY>
<VALUE>/**\n
* Gets ${partName}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;&lt;#list element.typeParameters as typeParameter&gt; * @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;&lt;#if element.parameterList.parameters?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.parameterList.parameters as parameter&gt; * @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;&lt;#if isNotVoid&gt; *\n
* @return the ${partName}\n
&lt;/#if&gt;&lt;#if element.throwsList.referenceElements?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.throwsList.referenceElements as exception&gt; * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt; */</VALUE>
</METHOD>
<METHOD>
<KEY>^.*(public|protected|private)*\s*.*(void|\w(\s*&lt;.+&gt;)*)+\s+set\w+\s*\(.*\).+</KEY>
<VALUE>/**\n
* Sets ${partName}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;&lt;#list element.typeParameters as typeParameter&gt; * @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;&lt;#if element.parameterList.parameters?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.parameterList.parameters as parameter&gt; * @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;&lt;#if isNotVoid&gt; *\n
* @return the ${partName}\n
&lt;/#if&gt;&lt;#if element.throwsList.referenceElements?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.throwsList.referenceElements as exception&gt; * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt; */</VALUE>
</METHOD>
<METHOD>
<KEY>^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+</KEY>
<VALUE>/**\n
* The entry point of application.\n
&lt;#if element.parameterList.parameters?has_content&gt; *\n
&lt;/#if&gt; * @param ${element.parameterList.parameters[0].name} the input arguments\n
&lt;#if element.throwsList.referenceElements?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.throwsList.referenceElements as exception&gt; * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt; */</VALUE>
</METHOD>
<METHOD>
<KEY>.+</KEY>
<VALUE>/**\n
* ${name}&lt;#if isNotVoid&gt; ${return}&lt;/#if&gt;.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;&lt;#list element.typeParameters as typeParameter&gt; * @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;&lt;#if element.parameterList.parameters?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.parameterList.parameters as parameter&gt; * @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;&lt;#if isNotVoid&gt; *\n
* @return the ${return}\n
&lt;/#if&gt;&lt;#if element.throwsList.referenceElements?has_content&gt; *\n
&lt;/#if&gt;&lt;#list element.throwsList.referenceElements as exception&gt; * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt; */</VALUE>
</METHOD>
</METHODS>
<FIELDS>
<FIELD>
<KEY>^.*(public|protected|private)*.+static.*(\w\s\w)+.+</KEY>
<VALUE>/**\n
* The constant ${element.getName()}.\n
*/</VALUE>
</FIELD>
<FIELD>
<KEY>^.*(public|protected|private)*.*(\w\s\w)+.+</KEY>
<VALUE>/**\n
&lt;#if element.parent.isInterface()&gt; * The constant ${element.getName()}.\n
&lt;#else&gt; * The ${name}.\n
&lt;/#if&gt; */</VALUE>
</FIELD>
<FIELD>
<KEY>.+</KEY>
<VALUE>/**\n
&lt;#if element.parent.isEnum()&gt; *${name} ${typeName}.\n
&lt;#else&gt; * The ${name}.\n
&lt;/#if&gt;*/</VALUE>
</FIELD>
</FIELDS>
</TEMPLATES>
</component>
</project>

35
DaKa/.idea/jarRepositories.xml generated Normal file
View File

@ -0,0 +1,35 @@
<?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="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://developer.huawei.com/repo/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://repo.huaweicloud.com/repository/maven/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://mirrors.huaweicloud.com/repository/maven/" />
</remote-repository>
</component>
</project>

4
DaKa/.idea/misc.xml generated Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>

View File

@ -0,0 +1,25 @@
{
"setting": {
"1.0.1": {
"Language": {
"args": {
"Language": "zh-CN"
}
}
}
},
"frontend": {
"1.0.0": {
"Resolution": {
"args": {
"Resolution": "360*780"
}
},
"DeviceType": {
"args": {
"DeviceType": "phone"
}
}
}
}
}

View File

@ -0,0 +1,25 @@
{
"setting": {
"1.0.1": {
"Language": {
"args": {
"Language": "zh_CN"
}
}
}
},
"frontend": {
"1.0.0": {
"Resolution": {
"args": {
"Resolution": "360*780"
}
},
"DeviceType": {
"args": {
"DeviceType": "phone"
}
}
}
}
}

View File

@ -0,0 +1,61 @@
{
"1.0.0": {
"LastPreviewDevice": {}
},
"1.0.1": {
"profileList": [
{
"id": "P40",
"deviceType": "phone",
"width": 1080,
"height": 2340,
"shape": "rect",
"dpi": 480,
"orientation": "portrait",
"language": "zh_CN",
"colorMode": "light"
},
{
"id": "MateX2",
"deviceType": "phone",
"width": 2200,
"height": 2480,
"shape": "rect",
"dpi": 520,
"orientation": "portrait",
"language": "zh_CN",
"colorMode": "light"
},
{
"id": "MatePadPro",
"deviceType": "tablet",
"width": 2560,
"height": 1600,
"shape": "rect",
"dpi": 400,
"orientation": "landscape",
"language": "zh_CN",
"colorMode": "light"
},
{
"id": "Watch3",
"deviceType": "wearable",
"width": 466,
"height": 466,
"shape": "circle",
"dpi": 320,
"orientation": "landscape",
"language": "zh_CN",
"colorMode": "light"
}
],
"runningProfileList": [
"P40"
],
"availableProfileList": [
"MateX2",
"MatePadPro",
"Watch3"
]
}
}

View File

@ -0,0 +1,25 @@
{
"setting": {
"1.0.1": {
"Language": {
"args": {
"Language": "zh-CN"
}
}
}
},
"frontend": {
"1.0.0": {
"Resolution": {
"args": {
"Resolution": "1024*640"
}
},
"DeviceType": {
"args": {
"DeviceType": "tablet"
}
}
}
}
}

View File

@ -0,0 +1,25 @@
{
"setting": {
"1.0.1": {
"Language": {
"args": {
"Language": "zh-CN"
}
}
}
},
"frontend": {
"1.0.0": {
"Resolution": {
"args": {
"Resolution": "466*466"
}
},
"DeviceType": {
"args": {
"DeviceType": "wearable"
}
}
}
}
}

View File

@ -0,0 +1,2 @@
{ java:S120"ZRename this package name to match the regular expression '^[a-z_]+(\.[a-z_][a-z0-9_]*)*$'.(Þ…‡Ýùÿÿÿÿ8±ï±¶ü/

View File

@ -0,0 +1,5 @@
u
java:S3008"SRename this field "Instance" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(‘⋈ûÿÿÿÿ8ØŽŸü/
S
java:S26964"6Make the enclosing method "static" or remove this set.(Ä“±Ï8®ØŽŸü/

View File

@ -0,0 +1,14 @@
t
java:S1104"RMake result a static final constant or non-public and provide accessors if needed.(¥<>ÅÚþÿÿÿÿ8®Ü±¶ü/
y
java:S1104"\Make addressComponent a static final constant or non-public and provide accessors if needed.(¦Ì<C2A6>Â8¯Ü±¶ü/
v
java:S1104""TMake province a static final constant or non-public and provide accessors if needed.(º«ä„ùÿÿÿÿ8¯Ü±¶ü/
r
java:S1104&"PMake city a static final constant or non-public and provide accessors if needed.(ÎÉâåúÿÿÿÿ8¯Ü±¶ü/
q
java:S1104*"TMake district a static final constant or non-public and provide accessors if needed.(¡ßçê8¯Ü±¶ü/
t
java:S1104."RMake street a static final constant or non-public and provide accessors if needed.(ØÚ©ªÿÿÿÿÿ8¯Ü±¶ü/
{ java:S120"ZRename this package name to match the regular expression '^[a-z_]+(\.[a-z_][a-z0-9_]*)*$'.(Þ…‡Ýùÿÿÿÿ8¯Ü±¶ü/

View File

@ -0,0 +1,11 @@
C java:S108/")Either remove or fill this block of code.(äõ”óýÿÿÿÿ
C java:S1084")Either remove or fill this block of code.(äõ”óýÿÿÿÿ
A
java:S1452H"&Remove usage of generic wildcard type.(ÆÚÝ¥ùÿÿÿÿ
O
java:S3400R"9Remove this method and declare a constant for this value.(ȸå<C2B8>
<
java:S1452Z"&Remove usage of generic wildcard type.(ÏŽü˜
B
java:S3011u",This accessibility update should be removed.(”ÝÙ®

View File

@ -0,0 +1,8 @@
| java:S116"[Rename this field "MainAbilitySlice" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(²ÌÐ<C38C>üÿÿÿÿ8þÖÞžü/
h java:S100!"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(Úœï ûÿÿÿÿ
1
java:S3626J"Remove this redundant jump.(ûÁÝ…
< java:S1316""Add a default case to this switch.(×ö³–úÿÿÿÿ
f
java:S13016"KReplace this "switch" statement by "if" statements to increase readability.(×ö³–úÿÿÿÿ

View File

@ -0,0 +1,12 @@
r
java:S3008"PRename this field "pd_pd" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(«ñûÉøÿÿÿÿ8ÚôŽŸü/
T
java:S1135"2Complete the task associated to this TODO comment.(¢é” ýÿÿÿÿ8ìôŽŸü/
X java:S125!"<This block of commented-out lines of code should be removed.(Ø•ºá8íôŽŸü/
X java:S1250"<This block of commented-out lines of code should be removed.(¥üä€8îôŽŸü/
] java:S125?"<This block of commented-out lines of code should be removed.(íñˆ¬ýÿÿÿÿ8ïôŽŸü/
s
java:S1104"QMake pd_pd a static final constant or non-public and provide accessors if needed.(«ñûÉøÿÿÿÿ8ðôŽŸü/
M
java:S1444"+Make this "public static pd_pd" field final(«ñûÉøÿÿÿÿ8ðôŽŸü/

View File

@ -0,0 +1,30 @@
v java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(È»§ã8í䎟ü/
{ java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(šÅïùÿÿÿÿ8î䎟ü/
v java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(<28>°ë¯8î䎟ü/
{ java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(©úÛùûÿÿÿÿ8î䎟ü/
{ java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(âÙ<C3A2>¹þÿÿÿÿ8î䎟ü/
{ java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(ù‚Ù¦þÿÿÿÿ8î䎟ü/
j java:S100]"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(‡±<E280A1>8<>原ü/
o java:S100a"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(™¹Æ¾ûÿÿÿÿ8<>原ü/
j java:S100e"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(Û´º¥8原ü/
o java:S100i"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(üÍÁ®þÿÿÿÿ8原ü/
o java:S100m"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(ÌÑÄöûÿÿÿÿ8原ü/
o java:S100q"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(‚¾¥´ýÿÿÿÿ8“原ü/
j java:S100u"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(ñÒÆÃ8”原ü/
o java:S100y"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(¼½ÎÂúÿÿÿÿ8•åŽŸü/
j java:S100}"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(·‘Õì8•åŽŸü/
k java:S100<18>"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(á—<C3A1>¼8原ü/
M
java:S1144$"1Remove this unused private "writeCounter" method.(„ÈÄ8—原ü/
R
java:S1144E"0Remove this unused private "readCounter" method.(£Ô¬’üÿÿÿÿ8—原ü/
e
java:S1192 "HDefine a constant instead of duplicating this literal "],key=[" 3 times.(”–¸ã8˜åŽŸü/
i
java:S1192 "LDefine a constant instead of duplicating this literal "],message=[" 3 times.(”–¸ã8˜åŽŸü/
p
java:S1104"SMake context a static final constant or non-public and provide accessors if needed.(Òò®­8™åŽŸü/
J
java:S1444"-Make this "public static context" field final(Òò®­8™åŽŸü/
n java:S101"MRename this class name to match the regular expression '^[A-Z][a-zA-Z0-9]*$'.(ŪëÝüÿÿÿÿ8™åŽŸü/

View File

@ -0,0 +1,4 @@
X
java:S2696M"6Make the enclosing method "static" or remove this set.(²ö±ûøÿÿÿÿ8¨…±¶ü/
{ java:S120"ZRename this package name to match the regular expression '^[a-z_]+(\.[a-z_][a-z0-9_]*)*$'.(þ±†Áÿÿÿÿÿ8®…±¶ü/

View File

@ -0,0 +1,4 @@
l
java:S1104"OMake msg a static final constant or non-public and provide accessors if needed.(ÝѺŒ8¹ä±¶ü/
{ java:S120"ZRename this package name to match the regular expression '^[a-z_]+(\.[a-z_][a-z0-9_]*)*$'.(Þ…‡Ýùÿÿÿÿ8ºä±¶ü/

View File

@ -0,0 +1,47 @@
E
java:S3740¦"/Provide the parametrized type for this generic.(÷õË
n java:S116F"TRename this field "Longitude" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(ãÊñ‡üÿÿÿÿ
k
java:S1450W"VRemove the "context" field and declare it as a local variable in the relevant methods.(êÝç
h
java:S3776\"RRefactor this method to reduce its Cognitive Complexity from 32 to the 15 allowed.(Öìâ±
P
java:S1135¸"2Complete the task associated to this TODO comment.(¹‘ÆŽ8ãÀ©¶ü/
C
java:S1602À",Remove useless curly braces around statement(̇‘´
H
java:S1602Ä",Remove useless curly braces around statement(ŽÕʾøÿÿÿÿ
5
java:S2119ó"Save and re-use this "Random".(ÊŒ±Ð
5
java:S2119ý"Save and re-use this "Random".(ÊŒ±Ð
5
java:S2119ˆ"Save and re-use this "Random".(ÊŒ±Ð
i java:S100Ï"NRename this method name to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(Úœï ûÿÿÿÿ
C
java:S1602â",Remove useless curly braces around statement(̇‘´
H
java:S1602æ",Remove useless curly braces around statement(ŽÕʾøÿÿÿÿ
@
java:S1068W"+Remove this unused "context" private field.(êÝç
u
java:S2293"YReplace the type specification in this constructor call with the diamond operator ("<>").(òÒëÆúÿÿÿÿ
u
java:S2293·"YReplace the type specification in this constructor call with the diamond operator ("<>").(ßî×ãûÿÿÿÿ
>
java:S1604¦"(Make this anonymous inner class a lambda(÷õË
D
java:S1604­"(Make this anonymous inner class a lambda(Ÿ<> ¹ÿÿÿÿÿ
?
java:S1604»"(Make this anonymous inner class a lambda(ñ<>¼É
D
java:S1604å"(Make this anonymous inner class a lambda(Òñ<C392>±þÿÿÿÿ
?
java:S1604<18>"(Make this anonymous inner class a lambda(Éæ²³
D
java:S1604 "(Make this anonymous inner class a lambda(®¥Ïªÿÿÿÿÿ
?
java:S1604°"(Make this anonymous inner class a lambda(ü‹¼Ô
z
java:S1104&"_Make fusedLocationClient a static final constant or non-public and provide accessors if needed.(»»¾ªýÿÿÿÿ

37
DaKa/.idea/sonarlint/issuestore/index.pb generated Normal file
View File

@ -0,0 +1,37 @@
X
(gradle/wrapper/gradle-wrapper.properties,f\b\fbe448ebfc3eb2d4e308f6b8b043666f5b57235e
c
3jianjia/src/main/java/com/net/jianjia/Platform.java,3\f\3fb907f4e71bcffa5291e02efe576a814a42762e
g
7entry/src/main/java/com/xcl/location/MyApplication.java,1\f\1fca71afd5c1d5be301d96e6944f0f72e7cfe336
g
7entry/src/main/java/com/xcl/location/Preference_RW.java,a\4\a4eac0e11cd512bf75961f45bc949d4f8033203e
^
.entry/src/main/java/com/xcl/location/XLog.java,a\4\a49d04c34d269757f710cdd66ee499b30ca4d012
e
5entry/src/main/java/com/xcl/location/MainAbility.java,4\6\4658bbfeed30bc3c16d89bdde88d0ce1bb94d3a7
H
entry/proguard-rules.pro,1\a\1a0bfe7a027837ed647b6bd5b6e2500c8555362e
<
build.gradle,f\0\f07866736216be0ee2aba49e392191aeae700a35
B
entry/build.gradle,a\d\ad38b2dea33752cac233aa09d7dfbe582e9dded6
l
<entry/src/main/java/com/xcl/location/Util/MyToastDialog.java,b\2\b21eebb6b040e2b10cd428205c5acd1f68cc6d50
b
2entry/src/main/java/com/xcl/location/Net/DXJX.java,2\5\25dacbaab99cc1fe7e73d185785207a3337590fb
b
2entry/src/main/java/com/xcl/location/Net/TJXX.java,c\e\cea9463d59754ba3cdc565e6279149e7440edadf
a
1entry/src/main/java/com/xcl/location/Net/Wan.java,1\5\15d8bcbfc11a5f476138f9bcb53e2052e1a9dfbf
J
entry/src/main/config.json,1\0\10f965cf51fe14a5ef0ca2ebefb1bd7e4607eeb2
M
entry/agconnect-services.json,9\c\9c0629d9ee39e937c45ba4e3206cabded9f4c3be
L
jianjia/src/main/config.json,0\f\0fc04922cd9a34622b859cd4d1a67a89f33da940
<
package.json,7\0\7030d0b2f71b999ff89a343de08c414af32fc93a
p
@entry/src/main/java/com/xcl/location/slice/MainAbilitySlice.java,e\0\e0da17fc7f5e236564b670ddce19a468201781e3

6
DaKa/.idea/vcs.xml generated Normal file
View 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>

45
DaKa/build.gradle Normal file
View File

@ -0,0 +1,45 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply plugin: 'com.huawei.ohos.app'
//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
ohos {
compileSdkVersion 6
defaultConfig {
compatibleSdkVersion 6
}
}
buildscript {
repositories {
maven {
url 'https://mirrors.huaweicloud.com/repository/maven/'
}
maven {
url 'https://developer.huawei.com/repo/'
}
maven {
url 'https://repo.huaweicloud.com/repository/maven/'
}
mavenCentral()
}
dependencies {
classpath 'com.huawei.ohos:hap:3.0.5.2'
classpath 'com.huawei.ohos:decctest:1.2.7.2'
classpath 'com.huawei.agconnect:agcp-harmony:1.3.0.300'
}
}
allprojects {
repositories {
maven {
url 'https://mirrors.huaweicloud.com/repository/maven/'
}
maven {
url 'https://developer.huawei.com/repo/'
}
maven {
url 'https://repo.huaweicloud.com/repository/maven/'
}
mavenCentral()
}
}

2
DaKa/entry/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/build
/node_modules

View File

@ -0,0 +1 @@
agconnect-services.json

45
DaKa/entry/build.gradle Normal file
View File

@ -0,0 +1,45 @@
apply plugin: 'com.huawei.ohos.hap'
apply plugin: 'com.huawei.ohos.decctest'
apply plugin: 'com.huawei.agconnect'
//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
ohos {
compileSdkVersion 6
defaultConfig {
compatibleSdkVersion 6
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
proguardOpt {
proguardEnabled true
rulesFiles 'proguard-rules.pro'
}
}
debug {
proguardOpt {
proguardEnabled true
rulesFiles 'proguard-rules.pro'
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
testImplementation 'junit:junit:4.13.1'
ohosTestImplementation 'com.huawei.ohos.testkit:runner:2.0.0.200'
implementation 'org.json:json:20211205'
implementation 'org.conscrypt:conscrypt-openjdk:2.5.2'
implementation project(':jianjia')
implementation "com.google.code.gson:gson:2.9.0"//Json数据解析
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.9'//
implementation 'com.huawei.agconnect:agconnect-core-harmony:1.3.0.300'//agc核心依赖
implementation 'com.huawei.hms:hianalytics-harmony:6.3.2.301'//HMS服务
implementation 'com.huawei.hms:location-harmony:6.3.0.300'//HMS定位
}
decc {
supportType = ['html', 'xml']
}

130
DaKa/entry/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,130 @@
-dontwarn
# 代码混淆压缩比在0~7之间
-optimizationpasses 5
# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames
# 在读取依赖的库文件时不要略过那些非public类成员
-dontskipnonpubliclibraryclassmembers
# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 不做预校验preverify是proguard的四个步骤之一去掉这一步能够加快混淆速度
-dontpreverify
-verbose
# google推荐算法
#-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-dontoptimize#注意在上传时配置,本地无需配置
# 保留注解内部类泛型匿名类
-keepattributes *Annotation*,Exceptions,InnerClasses,Signature,EnclosingMethod
# 重命名抛出异常时的文件名称
-renamesourcefileattribute SourceFile
# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
-dontwarn javax.annotation.**
# 保留本地native方法不被混淆
-keepclasseswithmembernames,allowshrinking class * {
native <methods>;
}
# 保留枚举类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保留自定义类
-keep class com.xcl.location.MyApplication
-keep class com.xcl.location.Net.**{*;}
# 忽略数据库有关
-keep class com.litesuits.orm.**
-keepclassmembers class com.litesuits.orm.**{*;}
-keep enum com.litesuits.orm.**
-keepclassmembers enum com.litesuits.orm.**{*;}
-keep interface com.litesuits.orm.**
-keepclassmembers interface com.litesuits.orm.**{*;}
-keep class com.xcl.study.DataANet.**{*;}
# 忽略继承
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# 保留HMS相关接入[AnalyticsKit SDK和依赖SDK的混淆配置]
-ignorewarnings
-repackageclasses
-keep class com.huawei.agconnect.**{*;}
-keep class com.huawei.hms.analytics.**{*;}
-keep class com.huawei.hms.push.**{*;}
-keep class com.huawei.hms.**{*;}
# 保留fastjson
#-dontwarn com.alibaba.fastjson.**
#-keep class com.alibaba.fastjson.**{*; }
# 保留okhttp
-keep class com.squareup.okhttp.** { *;}
-dontwarn com.squareup.okhttp.**
-dontwarn org.apache.http.**
-keep class okio.**{*;}
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
# HMS接口服务
-keepattributes Exceptions
-keep interface com.huawei.hms.analytics.type.HAEventType{*;}
-keep interface com.huawei.hms.analytics.type.HAParamType{*;}
-keep class com.huawei.hms.analytics.HiAnalyticsInstance{*;}
-keep class com.huawei.hms.analytics.HiAnalytics{*;}
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.harmony.**{*;}
-keep class com.huawei.mylibrary.**{*;}
# 保留HarmonyOS应用/服务入口类
-keep public class * extends *.aafwk.ability.Ability
-keep public class * extends *.ace.ability.AceAbility
-keep public class * extends *.aafwk.ability.AbilitySlice
-keep public class * extends *.aafwk.ability.AbilityPackage
-dontwarn java.lang.invoke.**
-dontwarn javax.naming.**
# 保留HarmonyOS定位服务
-keep public class com.huawei.hms.location.harmony.* {*;}
-keep public class com.huawei.hms.location.harmony.base.* {*;}
-keep class com.huawei.hmf.tasks.* {*;}
#网络有关
#okgo
-dontwarn com.lzy.okgo.**
-keep class com.lzy.okgo.**{*;}
#okrx
-dontwarn com.lzy.okrx.**
-keep class com.lzy.okrx.**{*;}
#okrx2
-dontwarn com.lzy.okrx2.**
-keep class com.lzy.okrx2.**{*;}
#okserver
-dontwarn com.lzy.okserver.**
-keep class com.lzy.okserver.**{*;}
-keepattributes Signature, InnerClasses, EnclosingMethod, Exceptions
# 蒹葭
-dontwarn com.net.jianjia.**
-keep class com.net.jianjia.** { *; }
-keep class com.net.jianjia.gson.** { *; }
-keep class com.net.jianjia.conventer.** { *; }
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@com.net.jianjia.http.* <methods>;
}
# OkHttp3
-dontwarn okhttp3.logging.**
-keep class okhttp3.internal.**{*;}
-dontwarn okio.**
# gson
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# 保留配置文件
-printmapping mapping.txt

View File

@ -0,0 +1,87 @@
{
"app": {
"bundleName": "com.xcl.location",
"vendor": "xcl",
"version": {
"code": 326,
"name": "1.0.1.220326"
}
},
"deviceConfig": {
"default": {
"supportBackup": true
}
},
"module": {
"package": "com.xcl.location",
"name": ".MyApplication",
"mainAbility": "com.xcl.location.MainAbility",
"deviceType": [
"phone",
"tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"visible": true,
"name": "com.xcl.location.MainAbility",
"icon": "$media:icon",
"label": "$string:entry_MainAbility",
"type": "page",
"launchType": "standard"
},
{
"permissions": [
"com.huawei.agconnect.core.DataAbilityShellProvider.PROVIDER"
],
"name": "com.huawei.agconnect.core.provider.AGConnectInitializeAbility",
"type": "data",
"uri": "dataability://com.xcl.location.location.AGConnectInitializeAbility"
}
],
"metaData": {
"customizeData": [
{
"name": "hwc-theme",
"extra": "",
"value": "androidhwext:style/Theme.Emui.Wallpaper.NoTitleBar"
}
]
},
"reqPermissions": [
{
"name": "ohos.permission.LOCATION",
"reason": "定位",
"usedScene": {
"ability": [
"com.xcl.location.MainAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.GET_NETWORK_INFO",
"reason": "Allows programs to obtain network information status"
},
{
"name": "ohos.permission.LOCATION_IN_BACKGROUND"
}
]
}
}

View File

@ -0,0 +1,103 @@
package com.xcl.location;
import com.xcl.location.Util.MyToastDialog;
import com.xcl.location.slice.MainAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.service.WindowManager;
import ohos.bundle.IBundleManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.utils.IntentConstants;
import ohos.utils.net.Uri;
/**
* The type Main ability.
*/
public class MainAbility extends Ability {
private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00234, "MainAbility");
/**
* The Main ability slice.
*/
MainAbilitySlice MainAbilitySlice;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setAbilitySliceAnimator(null);
super.setTransitionAnimation(0, 0);
this.getWindow().addFlags(WindowManager.LayoutConfig.MARK_ALLOW_EXTEND_LAYOUT);
super.setMainRoute(MainAbilitySlice.class.getName());
super.setAbilitySliceAnimator(null);
super.setTransitionAnimation(0, 0);
}
private void ShowDialog(String text1) {
try {
new MyToastDialog(this.getContext(), text1, ResourceTable.Graphic_xtoast_framem, 36, 25)
.setDuration(120)
.setAlignment(LayoutAlignment.BOTTOM)
.setOffset(0, 100)
.show();
} catch (Exception e) {
XLog.error(label, e.getMessage());
}
}
/**
* 权限
*
* @param requestCode the request code
* @param permissions the permissions
* @param grantResults the grant results
*/
@Override
public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsFromUserResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 20220109: {
// 匹配requestPermissions的requestCode
if (grantResults.length > 0
&& grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
// 权限被授予之后做相应业务逻辑的处理
} else {
// 权限被拒绝
this.ShowDialog("权限被拒绝");
this.ShowDialog("请在设置中开启定位权限");
/*无参--页面跳转开始*/
Intent intent1 = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction(IntentConstants.ACTION_APPLICATION_DETAILS_SETTINGS)
.withUri(Uri.getUriFromParts("package", getBundleName(), null))
.build();
intent1.setOperation(operation);
startAbility(intent1);
this.onBackPressed();
}
return;
}
}
}
/**
* Gets main ability slice.
*
* @return the main ability slice
*/
public MainAbilitySlice getMainAbilitySlice() {
return this.MainAbilitySlice;
}
/**
* Sets main ability slice.
*
* @param bianQianShareAbilitySlice the bian qian share ability slice
*/
public void setMainAbilitySlice(MainAbilitySlice bianQianShareAbilitySlice) {
this.MainAbilitySlice = bianQianShareAbilitySlice;
}
}

View File

@ -0,0 +1,76 @@
package com.xcl.location;
import com.huawei.hms.analytics.HiAnalyticsTools;
import com.net.jianjia.JianJia;
import com.net.jianjia.gson.GsonConverterFactory;
import com.xcl.location.Net.Wan;
import ohos.aafwk.ability.AbilityPackage;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
/**
* The type My application.
*/
public class MyApplication extends AbilityPackage {
private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00234, "MyApplication");
private static MyApplication Instance;
private JianJia mJianJia;
private Wan mWan;
/**
* Gets instance.
*
* @return the instance
*/
public static MyApplication getInstance() {
return Instance;
}
/**
* Gets jian jia.
*
* @return the jian jia
*/
public JianJia getJianJia() {
return this.mJianJia;
}
/**
* Gets wan.
*
* @return the wan
*/
public Wan getWan() {
return this.mWan;
}
@Override
public void onInitialize() {
super.onInitialize();
try {
Preference_RW.context = this.getContext();
XLog.pd_pd = Preference_RW.ff7_r();
XLog.pd_pd = 555;
HiAnalyticsTools.enableLog();
//创建日志拦截器
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
//为OKHTTP添加日志拦截器
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
this.mJianJia = new JianJia.Builder()
// 使用自定义的okHttpClient对象
.callFactory(okHttpClient)
.baseUrl("https://api.xuegao-xcl.tech")
.addConverterFactory(GsonConverterFactory.create())
.build();
Instance = this;
this.mWan = this.mJianJia.create(Wan.class);
} catch (Exception e) {
XLog.error(label, e.getMessage());
}
}
}

View File

@ -0,0 +1,49 @@
package com.xcl.location.Net;
import java.io.Serializable;
/**
* The type Dxjx.
*
* @author Xcl
* @date 2022 /3/25
* @package com.xcl.location.Net
*/
public class DXJX {
/**
* The Result.
*/
public Result result;
/**
* The type Result.
*/
public static class Result implements Serializable {
/**
* The Address component.
*/
public AddressComponent addressComponent;
/**
* The type Address component.
*/
public static class AddressComponent implements Serializable {
/**
* The Province.
*/
public String province;
/**
* The City.
*/
public String city;
/**
* The District.
*/
public String district;
/**
* The Street.
*/
public String street;
}
}
}

View File

@ -0,0 +1,15 @@
package com.xcl.location.Net;
/**
* The type Tjxx.
*
* @author Xcl
* @date 2022 /3/25
* @package com.xcl.location.Net
*/
public class TJXX {
/**
* The Msg.
*/
public String msg;
}

View File

@ -0,0 +1,36 @@
package com.xcl.location.Net;
import com.net.jianjia.Call;
import com.net.jianjia.http.*;
import java.util.Map;
/**
* The interface Wan.
*
* @author Xcl
* @date 2022 /2/18
* @package com.xcl.study.DataANet
*/
public interface Wan {
/**
* Gets dkxx.
*
* @param param the param
* @return the dkxx
*/
@BaseUrl("https://api.map.baidu.com/")
@GET("/reverse_geocoding/v3")
Call<DXJX> getDKXX(@QueryMap Map<String, String> param);
/**
* Post dkxx call.
*
* @param param the param
* @return the call
*/
@BaseUrl("https://yx.ty-ke.com/")
@POST("/Home/Monitor/monitor_add")
@FormUrlEncoded
Call<TJXX> postDKXX(@FieldMap Map<String, String> param);
}

View File

@ -0,0 +1,187 @@
package com.xcl.location;
import ohos.aafwk.ability.Ability;
import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.preferences.Preferences;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
/**
* The type Preference rw.
*
* @author Xcl
* @date 2022 /3/25
* @package com.xcl.location
*/
public class Preference_RW extends Ability {
private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00234, "Preference_RW");
private static final String preferenceFile = "messages_tzx_xcl_dx";
private static final String counterKey7 = "DeBug";
private static final String counterKey1 = "dszh";
private static final String counterKey2 = "dxtempd";
private static final String counterKey3 = "dxtem";
private static final String counterKey4 = "autodxpd";
/**
* The constant context.
*/
public static Context context;
private static void writeCounter(String key, int message) {
try {
DatabaseHelper databaseHelper = new DatabaseHelper(context);
Preferences preferences = databaseHelper.getPreferences(preferenceFile);
preferences.putInt(key, message);
preferences.flush();
} catch (Exception e) {
HiLog.error(label, "写发生错误[" + e.getMessage() + "],key=[" + key + "],message=[" + message + "]");
}
}
private static void writeCounter(String key, long message) {
try {
DatabaseHelper databaseHelper = new DatabaseHelper(context);
Preferences preferences = databaseHelper.getPreferences(preferenceFile);
preferences.putLong(key, message);
preferences.flush();
} catch (Exception e) {
HiLog.error(label, "写发生错误[" + e.getMessage() + "],key=[" + key + "],message=[" + message + "]");
}
}
private static void writeCounter(String key, String message) {
try {
DatabaseHelper databaseHelper = new DatabaseHelper(context);
Preferences preferences = databaseHelper.getPreferences(preferenceFile);
preferences.putString(key, message);
preferences.flush();
} catch (Exception e) {
HiLog.warn(label, "xcl写发生错误[" + e.getMessage() + "],key=[" + key + "],message=[" + message + "]");
}
}
private static int readCounter(String key) {
try {
DatabaseHelper databaseHelper = new DatabaseHelper(context);
Preferences preferences = databaseHelper.getPreferences(preferenceFile);
return preferences.getInt(key, 0);
} catch (Exception e) {
HiLog.error(label, "读发生错误" + e.getMessage());
return 0;
}
}
private static long readCounter(String key, int a) {
try {
XLog.info(label, "没必要的数据:" + a);
DatabaseHelper databaseHelper = new DatabaseHelper(context);
Preferences preferences = databaseHelper.getPreferences(preferenceFile);
return preferences.getLong(key, 0);
} catch (Exception e) {
HiLog.error(label, "读发生错误" + e.getMessage());
return 0;
}
}
private static String readCounter(String key, String a) {
try {
XLog.info(label, "没必要的数据:" + a);
DatabaseHelper databaseHelper = new DatabaseHelper(context);
Preferences preferences = databaseHelper.getPreferences(preferenceFile);
return preferences.getString(key, String.valueOf(0));
} catch (Exception e) {
HiLog.warn(label, "xcl读发生错误" + e.getMessage());
return "0";
}
}
/**
* Ff 7 r int.
*
* @return the int
*/
public static int ff7_r() {
return readCounter(counterKey7);
}
/**
* Ff 7 w.
*
* @param a1 the a 1
*/
public static void ff7_w(int a1) {
Preference_RW.writeCounter(counterKey7, a1);
}
/**
* Ff 2 r int.
*
* @return the int
*/
public static int ff2_r() {
return readCounter(counterKey2);
}
/**
* Ff 2 w.
*
* @param a1 the a 1
*/
public static void ff2_w(int a1) {
Preference_RW.writeCounter(counterKey2, a1);
}
/**
* Ff 4 r int.
*
* @return the int
*/
public static int ff4_r() {
return readCounter(counterKey4);
}
/**
* Ff 4 w.
*
* @param a1 the a 1
*/
public static void ff4_w(int a1) {
Preference_RW.writeCounter(counterKey4, a1);
}
/**
* Ff 1 r string.
*
* @return the string
*/
public static String ff1_r() {
return readCounter(counterKey1, "0");
}
/**
* Ff 1 w.
*
* @param a1 the a 1
*/
public static void ff1_w(String a1) {
Preference_RW.writeCounter(counterKey1, a1);
}
/**
* Ff 3 r string.
*
* @return the string
*/
public static String ff3_r() {
return readCounter(counterKey3, "0");
}
/**
* Ff 3 w.
*
* @param a1 the a 1
*/
public static void ff3_w(String a1) {
Preference_RW.writeCounter(counterKey3, a1);
}
}

View File

@ -0,0 +1,93 @@
package com.xcl.location.Util;
import com.xcl.location.Preference_RW;
import com.xcl.location.XLog;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
/**
* The type My toast dialog.
*
* @author Xcl
* @date 2021 /12/31
* @package com.xcl.study.slice.Dialog
*/
public class MyToastDialog extends ToastDialog {
/**
* The constant label.
*/
private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00234, "MyToastDialog");
/**
* The Text component.
*/
private Text textComponent;
/**
* Instantiates a new My toast dialog.
*
* @param context the context
* @param text the text
* @param style the style
* @param size the size
* @param pad the pad
*/
public MyToastDialog(Context context, String text, int style, int size, int pad) {
super(context);
this.init(context, style, size, pad);
this.setText(text);
}
/**
* Init.
*
* @param context the context
* @param style the style
* @param size the size
* @param pad the pad
*/
private void init(Context context, int style, int size, int pad) {
try {
this.textComponent = new Text(context);
this.textComponent.setPadding(pad, pad, pad, pad);
this.textComponent.setTextColor(Color.BLACK);
this.textComponent.setTextAlignment(TextAlignment.CENTER);
this.textComponent.setTextSize(size);
ShapeElement shapeElement = new ShapeElement(context, style);
this.textComponent.setBackground(shapeElement);
this.textComponent.setMultipleLine(true);
DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig();
layoutConfig.width = ComponentContainer.LayoutConfig.MATCH_CONTENT;
layoutConfig.height = ComponentContainer.LayoutConfig.MATCH_CONTENT;
layoutConfig.alignment = LayoutAlignment.CENTER;
this.textComponent.setLayoutConfig(layoutConfig);
this.setTransparent(true);
this.setComponent(this.textComponent);
this.setCornerRadius(AttrHelper.vp2px(25, context));
} catch (Exception e) {
XLog.pd_pd = Preference_RW.ff7_r();
XLog.error(label, e.getMessage());
}
}
/**
* Sets text.
*
* @param text the text
* @return the text
*/
@Override
public MyToastDialog setText(String text) {
this.textComponent.setText(text);
return this;
}
}

View File

@ -0,0 +1,68 @@
package com.xcl.location;
import ohos.aafwk.ability.Ability;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
/**
* The type X log.
*
* @author Xcl
* @date 2022 /1/24
* @package com.xcl.study.Log
*/
public class XLog extends Ability {
/**
* The constant pd_pd.
*/
public static int pd_pd;
/**
* The .
*/
static int i = 0;//TODO:其实这个值P用没有只是因为有些情况下不输出日志就会卡死
/**
* Info.
*
* @param label the label
* @param message the message
*/
public static void info(HiLogLabel label, String message) {
if (pd_pd == 555) {
HiLog.info(label, "信息:[" + message + "]");
} else {
i++;
}
//HiLog.info(label, "信息:[" + message + "]");
}
/**
* Warn.
*
* @param label the label
* @param message the message
*/
public static void warn(HiLogLabel label, String message) {
if (pd_pd == 555) {
HiLog.warn(label, "警告:[" + message + "]");
} else {
i++;
}
//HiLog.warn(label, "警告:[" + message + "]");
}
/**
* Error.
*
* @param label the label
* @param message the message
*/
public static void error(HiLogLabel label, String message) {
if (pd_pd == 555) {
HiLog.error(label, "错误:[" + message + "]");
} else {
i++;
}
//HiLog.error(label, "错误:[" + message + "]");
}
}

View File

@ -0,0 +1,369 @@
package com.xcl.location.slice;
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.hms.location.harmony.*;
import com.net.jianjia.Call;
import com.net.jianjia.Callback;
import com.net.jianjia.Response;
import com.xcl.location.*;
import com.xcl.location.Net.DXJX;
import com.xcl.location.Net.TJXX;
import com.xcl.location.Util.MyToastDialog;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.*;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;
import ohos.bundle.IBundleManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.utils.IntentConstants;
import ohos.utils.net.Uri;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* The type Main ability slice.
*/
public class MainAbilitySlice extends AbilitySlice {
private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00111, "MainAbilitySlice");
/**
* The Fused location client.
*/
public FusedLocationClient fusedLocationClient;
/**
* The Settings provider client.
*/
SettingsProviderClient settingsProviderClient;
/**
* The Location callback.
*/
LocationCallback locationCallback;
/**
* The Location request.
*/
LocationRequest locationRequest = new LocationRequest();
/**
* The Input.
*/
TextField input;
/**
* The Inputtem.
*/
TextField inputtem;
/**
* The Result.
*/
Text result;
/**
* The Latitude.
*/
Double latitude;
/**
* The Longitude.
*/
Double Longitude;
/**
* The Province.
*/
String province;
/**
* The City.
*/
String city;
/**
* The District.
*/
String district;
/**
* The Street.
*/
String street;
private Context context;
private Text geoAddressInfoText;
private Text locationInfoText;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_main_ability_slice);
MainAbility bianQianShareAbility = (MainAbility) this.getAbility();
bianQianShareAbility.setMainAbilitySlice(this);
if (this.verifySelfPermission(ohos.security.SystemPermission.DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) {
if (this.canRequestPermission(ohos.security.SystemPermission.DISTRIBUTED_DATASYNC)) {
this.requestPermissionsFromUser(
new String[]{ohos.security.SystemPermission.LOCATION}, 20220109);
} else {
// 显示应用需要权限的理由提示用户进入设置授权
this.ShowDialog("请在设置中开启定位权限");
/*无参--页面跳转开始*/
Intent intent1 = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction(IntentConstants.ACTION_APPLICATION_DETAILS_SETTINGS)
.withUri(Uri.getUriFromParts("package", getBundleName(), null))
.build();
intent1.setOperation(operation);
startAbility(intent1);
this.onBackPressed();
}
}
locationInfoText = (Text) findComponentById(ResourceTable.Id_location_info);
geoAddressInfoText = (Text) findComponentById(ResourceTable.Id_geo_address_info);
input = (TextField) findComponentById(ResourceTable.Id_dxzh);
inputtem = (TextField) findComponentById(ResourceTable.Id_dxtem);
result = (Text) findComponentById(ResourceTable.Id_dkjg);
inputtem.setEnabled(false);
if (Preference_RW.ff1_r() == null || Preference_RW.ff1_r().equals("") || Preference_RW.ff1_r().equals("0")) {
input.setText("");
} else {
input.setText(Preference_RW.ff1_r());
}
if (Preference_RW.ff2_r() == 2) {
if (Preference_RW.ff3_r() == null || Preference_RW.ff3_r().equals("") || Preference_RW.ff3_r().equals("0")) {
inputtem.setText("");
} else {
inputtem.setText(Preference_RW.ff3_r());
}
}
XLog.info(label, "onStart start");
fusedLocationClient = new FusedLocationClient(this);
settingsProviderClient = new SettingsProviderClient(this);
// 设置位置更新的间隔毫秒单位
locationRequest.setInterval(5000);
// 设置权重
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// 可选设置是否需要返回地址信息
locationRequest.setNeedAddress(true);
// 可选设置返回地址信息的语言
locationRequest.setLanguage("zh");
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
// 处理位置回调结果
XLog.info(label, "onLocationResult");
latitude = locationResult.getLastHWLocation().getLatitude();
Longitude = locationResult.getLastHWLocation().getLongitude();
}
}
@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
super.onLocationAvailability(locationAvailability);
if (locationAvailability != null) {
// 处理位置状态
XLog.info(label, "onLocationAvailability");
}
}
};
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback)
.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Object v) {
// 接口调用成功的处理
XLog.info(label, "requestLocationUpdates success");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// 接口调用失败的处理
XLog.error(label, "requestLocationUpdates failure");
}
});
context = this;
Button stopLocatingButton = (Button) findComponentById(ResourceTable.Id_stop_locating);
Map<String, String> url = new HashMap<String, String>();
Map<String, String> url1 = new HashMap<String, String>();
url.put("ak", "此处填写你的百度地图ak");//TODO:百度地图ak
url.put("output", "json");
url.put("coordtype", "wgs84ll");
stopLocatingButton.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
// 注意停止位置更新时mLocationCallback与requestLocationUpdates()中的LocationCallback参数为同一对象
fusedLocationClient.removeLocationUpdates(locationCallback)
.addOnSuccessListener(v -> {
// 接口调用成功的处理
XLog.info(label, "removeLocationUpdates success");
})
.addOnFailureListener(e -> {
// 接口调用失败的处理
XLog.error(label, "removeLocationUpdates failure");
});
locationInfoText.setText(latitude + "," + Longitude);
XLog.error(label, latitude + "," + Longitude);
url.put("location", latitude + "," + Longitude);
MyApplication.getInstance().getWan().getDKXX(url).enqueue(new Callback<DXJX>() {
@Override
public void onResponse(Call<DXJX> call, Response<DXJX> response) {
province = response.body().result.addressComponent.province;
city = response.body().result.addressComponent.city;
district = response.body().result.addressComponent.district;
street = response.body().result.addressComponent.street;
geoAddressInfoText.setText(response.body().result.addressComponent.province +
response.body().result.addressComponent.city +
response.body().result.addressComponent.district +
response.body().result.addressComponent.street);
XLog.error(label, response.body().result.addressComponent.province +
response.body().result.addressComponent.city +
response.body().result.addressComponent.district +
response.body().result.addressComponent.street);
}
@Override
public void onFailure(Call<DXJX> call, Throwable t) {
XLog.error(label, t.getMessage());
}
});
}
});
Button save = (Button) findComponentById(ResourceTable.Id_save_button);
save.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
Preference_RW.ff1_w(input.getText());
if (Preference_RW.ff2_r() == 2) {
Preference_RW.ff3_w(inputtem.getText());
}
ShowDialog("保存成功!");
}
});
RadioContainer radioContainer = (RadioContainer) findComponentById(ResourceTable.Id_radio_container0);
radioContainer.cancelMarks();
if (Preference_RW.ff2_r() == 1) {
radioContainer.mark(0);
Random rand = new Random();//36.0-36.9
DecimalFormat df = new DecimalFormat("0.0");
inputtem.setText(df.format((float) (rand.nextInt(10) + 360) / 10));
} else if (Preference_RW.ff2_r() == 2) {
radioContainer.mark(1);
inputtem.setText("");
inputtem.setEnabled(true);
} else {
radioContainer.mark(0);
Preference_RW.ff2_w(1);
Random rand = new Random();//36.0-36.9
DecimalFormat df = new DecimalFormat("0.0");
inputtem.setText(df.format((float) (rand.nextInt(10) + 360) / 10));
}
radioContainer.setMarkChangedListener(new RadioContainer.CheckedStateChangedListener() {
@Override
public void onCheckedChanged(RadioContainer radioContainer, int i) {
XLog.info(label, "用户选择的是:" + i);
if (i == 0) {
XLog.info(label, "用户选择的是:是");
Preference_RW.ff2_w(1);
Random rand = new Random();//36.0-36.9
DecimalFormat df = new DecimalFormat("0.0");
inputtem.setText(df.format((float) (rand.nextInt(10) + 360) / 10));
inputtem.setEnabled(false);
} else if (i == 1) {
XLog.info(label, "用户选择的是:否");
Preference_RW.ff2_w(2);
inputtem.setText("");
inputtem.setEnabled(true);
} else {
XLog.error(label, "这tm不可能");
}
}
});
RadioContainer radioContainer1 = (RadioContainer) findComponentById(ResourceTable.Id_radio_container1);
radioContainer1.cancelMarks();
if (Preference_RW.ff4_r() == 1) {
radioContainer1.mark(0);
} else if (Preference_RW.ff4_r() == 2) {
radioContainer1.mark(1);
} else {
radioContainer1.mark(0);
Preference_RW.ff4_w(1);
}
radioContainer1.setMarkChangedListener(new RadioContainer.CheckedStateChangedListener() {
@Override
public void onCheckedChanged(RadioContainer radioContainer, int i) {
XLog.info(label, "用户选择的是:" + i);
if (i == 0) {
XLog.info(label, "用户选择的是:是");
Preference_RW.ff4_w(1);
} else if (i == 1) {
XLog.info(label, "用户选择的是:否");
Preference_RW.ff4_w(2);
} else {
XLog.error(label, "这tm不可能");
}
}
});
Button daka = (Button) findComponentById(ResourceTable.Id_sddk_button);
daka.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
url1.put("mobile", Preference_RW.ff1_r());
url1.put("city", city);
url1.put("jk_type", "健康");
url1.put("district", district);
url1.put("address", province + city + district + street);
url1.put("title", inputtem.getText());
url1.put("jc_type", "");
url1.put("wc_type", "");
url1.put("is_verify", "0");
url1.put("province", province);
MyApplication.getInstance().getWan().postDKXX(url1).enqueue(new Callback<TJXX>() {
@Override
public void onResponse(Call<TJXX> call, Response<TJXX> response) {
ShowDialog("打卡成功!");
XLog.info(label, response.body().msg);
result.setText(response.body().msg);
}
@Override
public void onFailure(Call<TJXX> call, Throwable t) {
XLog.error(label, t.getMessage());
ShowDialog("打卡失败!错误原因:" + t.getMessage());
}
});
}
});
}
private void ShowDialog(String text1) {
try {
new MyToastDialog(this.getContext(), text1, ResourceTable.Graphic_xtoast_framem, 36, 25)
.setDuration(120)
.setAlignment(LayoutAlignment.BOTTOM)
.setOffset(0, 100)
.show();
} catch (Exception e) {
XLog.error(label, e.getMessage());
}
}
@Override
protected void onStop() {
XLog.info(label, "onStop start");
super.onStop();
try {
fusedLocationClient.removeLocationUpdates(locationCallback)
.addOnSuccessListener(v -> {
// 接口调用成功的处理
XLog.info(label, "removeLocationUpdates success");
})
.addOnFailureListener(e -> {
// 接口调用失败的处理
XLog.error(label, "removeLocationUpdates failure");
});
} catch (Exception e) {
XLog.error(label, e.getMessage());
}
XLog.info(label, "onStop end");
}
}

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "entry_MainAbility",
"value": "校企通[魔改版]"
},
{
"name": "mainability_description",
"value": "Java_Empty Ability"
},
{
"name": "mainability_HelloWorld",
"value": "Hello World"
}
]
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<solid
ohos:color="#D89BCBFF"/>
<corners
ohos:radius="4"/>
</shape>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<stroke
ohos:width="5"
ohos:color="#FF6D788A"/>
<corners
ohos:radius="4"/>
</shape>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<state-container
xmlns:ohos="http://schemas.huawei.com/res/ohos">
<item
ohos:element="$graphic:background_checkbox_checkedm"
ohos:state="component_state_checked"/>
<item
ohos:element="$graphic:background_checkbox_emptym"
ohos:state="component_state_empty"/>
</state-container>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<corners
ohos:radius="30vp"/>
<solid
ohos:color="#FFE2C7C7"/>
</shape>

View File

@ -0,0 +1,345 @@
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="#F8F3ECEC"
ohos:bottom_padding="20vp"
ohos:left_padding="15vp"
ohos:orientation="vertical"
ohos:right_padding="15vp"
ohos:top_padding="30vp">
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="1"
>
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:text="打卡账号"
ohos:text_color="black"
ohos:text_size="25vp"
ohos:weight="2"
/>
<TextField
ohos:id="$+id:dxzh"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:bubble_height="15px"
ohos:bubble_left_height="17px"
ohos:bubble_left_width="20px"
ohos:bubble_right_height="17px"
ohos:bubble_right_width="20px"
ohos:bubble_width="15px"
ohos:hint="学号或身份证号"
ohos:hint_color="#FFAE8787"
ohos:layout_alignment="center"
ohos:left_padding="10vp"
ohos:text_alignment="vertical_center|left"
ohos:text_color="#FFA77728"
ohos:text_size="16.5vp"
ohos:truncation_mode="auto_scrolling"
ohos:weight="3"
/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="2"
>
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:multiple_lines="true"
ohos:text="位置信息"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="2"
/>
<Text
ohos:id="$+id:location_info"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:multiple_lines="true"
ohos:scrollable="true"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="4"
/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="2"
>
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:multiple_lines="true"
ohos:text="当前地理位置信息"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="2"
/>
<Text
ohos:id="$+id:geo_address_info"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:multiple_lines="true"
ohos:scrollable="true"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="4"
/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="1"
>
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:text="是否随机温度"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="2"
/>
<RadioContainer
ohos:id="$+id:radio_container0"
ohos:height="match_parent"
ohos:width="0vp"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="3"
>
<RadioButton
ohos:id="$+id:radio_button_1"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:check_element="$graphic:checkbox_check_elementm"
ohos:text="是"
ohos:text_color_off="#FF8A9AB5"
ohos:text_color_on="#FF1773EF"
ohos:text_size="23vp"
ohos:weight="8"/>
<RadioButton
ohos:id="$+id:radio_button_2"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:check_element="$graphic:checkbox_check_elementm"
ohos:text="否"
ohos:text_color_off="#FF8A9AB5"
ohos:text_color_on="#FF1773EF"
ohos:text_size="23vp"
ohos:weight="8"/>
</RadioContainer>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="1"
>
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:text="打卡温度"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="2"
/>
<TextField
ohos:id="$+id:dxtem"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:bubble_height="15px"
ohos:bubble_left_height="17px"
ohos:bubble_left_width="20px"
ohos:bubble_right_height="17px"
ohos:bubble_right_width="20px"
ohos:bubble_width="15px"
ohos:hint="温度"
ohos:hint_color="#FFAB9B9B"
ohos:layout_alignment="center"
ohos:left_padding="10vp"
ohos:text_alignment="vertical_center|left"
ohos:text_color="#FF9D8051"
ohos:text_size="20.5vp"
ohos:truncation_mode="auto_scrolling"
ohos:weight="3"
/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="1"
>
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:text="是否自动打卡"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="2"
/>
<RadioContainer
ohos:id="$+id:radio_container1"
ohos:height="match_parent"
ohos:width="0vp"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="3"
>
<RadioButton
ohos:id="$+id:radio_button_11"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:check_element="$graphic:checkbox_check_elementm"
ohos:text="是"
ohos:text_color_off="#FF8A9AB5"
ohos:text_color_on="#FF1773EF"
ohos:text_size="23vp"
ohos:weight="8"/>
<RadioButton
ohos:id="$+id:radio_button_21"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:check_element="$graphic:checkbox_check_elementm"
ohos:text="否"
ohos:text_color_off="#FF8A9AB5"
ohos:text_color_on="#FF1773EF"
ohos:text_size="23vp"
ohos:weight="8"/>
</RadioContainer>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="1"
>
<Button
ohos:id="$+id:stop_locating"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:text="停止定位"
ohos:text_color="#FFFF0000"
ohos:text_size="20vp"
ohos:weight="1.5"
/>
<Button
ohos:id="$+id:save_button"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:text="保存"
ohos:text_color="#FF8800FF"
ohos:text_size="20vp"
ohos:weight="1.5"
/>
<Button
ohos:id="$+id:sddk_button"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="#F8ACA3A3"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:text="点击打卡"
ohos:text_color="#FF152D00"
ohos:text_size="22vp"
ohos:weight="2"
/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:orientation="horizontal"
ohos:weight="2"
>
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:multiple_lines="true"
ohos:text="打卡状态"
ohos:text_color="black"
ohos:text_size="20vp"
ohos:weight="2"
/>
<Text
ohos:id="$+id:dkjg"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:margin="1vp"
ohos:multiple_lines="true"
ohos:text_color="#FF30FA2D"
ohos:text_size="20vp"
ohos:weight="4"
/>
</DirectionalLayout>
</DirectionalLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1 @@
agconnect-services.json

View File

@ -0,0 +1,14 @@
package com.xcl.location;
import ohos.aafwk.ability.delegation.AbilityDelegatorRegistry;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ExampleOhosTest {
@Test
public void testBundleName() {
final String actualBundleName = AbilityDelegatorRegistry.getArguments().getTestBundleName();
assertEquals("com.xcl.location", actualBundleName);
}
}

View File

@ -0,0 +1,9 @@
package com.xcl.location;
import org.junit.Test;
public class ExampleTest {
@Test
public void onStart() {
}
}

13
DaKa/gradle.properties Normal file
View File

@ -0,0 +1,13 @@
# Project-wide Gradle settings.
# IDE (e.g. DevEco Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# If the Chinese output is garbled, please configure the following parameter.
# This function is enabled by default when the DevEco Studio builds the hap/app,if you need disable gradle parallel,you should set org.gradle.parallel false.
# more information see https://docs.gradle.org/current/userguide/performance.html
# org.gradle.parallel=false
# org.gradle.jvmargs=-Dfile.encoding=GBK

BIN
DaKa/gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://repo.huaweicloud.com/gradle/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

183
DaKa/gradlew vendored Normal file
View File

@ -0,0 +1,183 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

103
DaKa/gradlew.bat vendored Normal file
View File

@ -0,0 +1,103 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

2
DaKa/jianjia/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/build
/node_modules

29
DaKa/jianjia/build.gradle Normal file
View File

@ -0,0 +1,29 @@
apply plugin: 'com.huawei.ohos.library'
//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
ohos {
compileSdkVersion 6
defaultConfig {
compatibleSdkVersion 6
}
buildTypes {
release {
proguardOpt {
proguardEnabled true
rulesFiles 'proguard-rules.pro'
}
}
debug {
proguardOpt {
proguardEnabled true
rulesFiles 'proguard-rules.pro'
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13.1'
api "com.squareup.okhttp3:okhttp:3.14.9"
api "com.google.code.gson:gson:2.9.0"
}

View File

@ -0,0 +1 @@
# Add har specific ProGuard rules for consumer here.

133
DaKa/jianjia/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,133 @@
-dontwarn
# 代码混淆压缩比在0~7之间
-optimizationpasses 5
# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames
# 在读取依赖的库文件时不要略过那些非public类成员
-dontskipnonpubliclibraryclassmembers
# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 不做预校验preverify是proguard的四个步骤之一去掉这一步能够加快混淆速度
-dontpreverify
-verbose
# google推荐算法
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
# 保留注解内部类泛型匿名类
-keepattributes *Annotation*,Exceptions,InnerClasses,Signature,EnclosingMethod
# 重命名抛出异常时的文件名称
-renamesourcefileattribute SourceFile
# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
-dontwarn javax.annotation.**
# 保留本地native方法不被混淆
-keepclasseswithmembernames,allowshrinking class * {
native <methods>;
}
# 保留枚举类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保留自定义类
-keep class com.xcl.calculator.slice.BianQian.first.**{*;}
-keep class com.xcl.calculator.slice.BianQian.WatchOnly.**{*;}
-keep class com.xcl.calculator.slice.BianQian.second.**{*;}
-keep class com.xcl.calculator.MyApplication
-keep class com.xcl.calculator.Ability.CaiDanAbility
-keep class com.xcl.calculator.net.**{*;}
-keep class com.xcl.calculator.widget.widget.**{*;}
-keep class com.xcl.calculator.widget.widget1.**{*;}
-keep class com.xcl.calculator.widget.controller.**{*;}
-keep class com.xcl.calculator.widget.**{*;}
# 忽略数据库有关
-keep class com.litesuits.orm.**
-keepclassmembers class com.litesuits.orm.**{*;}
-keep enum com.litesuits.orm.**
-keepclassmembers enum com.litesuits.orm.**{*;}
-keep interface com.litesuits.orm.**
-keepclassmembers interface com.litesuits.orm.**{*;}
-keep class com.xcl.calculator.DataANet.**{*;}
# 忽略继承
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# 保留HMS相关接入[AnalyticsKit SDK和依赖SDK的混淆配置]
-ignorewarnings
-repackageclasses
-keep class com.huawei.agconnect.**{*;}
-keep class com.huawei.hms.analytics.**{*;}
-keep class com.huawei.hms.push.**{*;}
-keep class com.huawei.hms.**{*;}
# 保留fastjson
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.**{*; }
# 保留okhttp
-keep class com.squareup.okhttp.** { *;}
-dontwarn com.squareup.okhttp.**
-dontwarn org.apache.http.**
-keep class okio.**{*;}
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
# HMS接口服务
-keepattributes Exceptions
-keep interface com.huawei.hms.analytics.type.HAEventType{*;}
-keep interface com.huawei.hms.analytics.type.HAParamType{*;}
-keep class com.huawei.hms.analytics.HiAnalyticsInstance{*;}
-keep class com.huawei.hms.analytics.HiAnalytics{*;}
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.harmony.**{*;}
-keep class com.huawei.mylibrary.**{*;}
# 保留HarmonyOS应用/服务入口类
-keep public class * extends *.aafwk.ability.Ability
-keep public class * extends *.ace.ability.AceAbility
-keep public class * extends *.aafwk.ability.AbilitySlice
-keep public class * extends *.aafwk.ability.AbilityPackage
-dontwarn java.lang.invoke.**
-dontwarn javax.naming.**
#网络有关
#okgo
-dontwarn com.lzy.okgo.**
-keep class com.lzy.okgo.**{*;}
#okrx
-dontwarn com.lzy.okrx.**
-keep class com.lzy.okrx.**{*;}
#okrx2
-dontwarn com.lzy.okrx2.**
-keep class com.lzy.okrx2.**{*;}
#okserver
-dontwarn com.lzy.okserver.**
-keep class com.lzy.okserver.**{*;}
-keepattributes Signature, InnerClasses, EnclosingMethod, Exceptions
# 蒹葭
-dontwarn com.net.jianjia.**
-keep class com.net.jianjia.** { *; }
-keep class com.net.jianjia.gson.** { *; }
-keep class com.net.jianjia.conventer.** { *; }
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@com.net.jianjia.http.* <methods>;
}
# OkHttp3
-dontwarn okhttp3.logging.**
-keep class okhttp3.internal.**{*;}
-dontwarn okio.**
# gson
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# 保留配置文件
-printmapping mapping.txt

View File

@ -0,0 +1,24 @@
{
"app": {
"bundleName": "com.xcl.location",
"vendor": "xcl",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "com.net.jianjia",
"deviceType": [
"phone",
"tablet",
"wearable"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "jianjia",
"moduleType": "har"
}
}
}

View File

@ -0,0 +1,175 @@
package com.net.jianjia;
import com.net.jianjia.http.Streaming;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* 默认的数据转换器如果调用者没有添加{@link Converter}对象就会使用这个默认的数据转换器
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
class BuiltInConverters extends Converter.Factory {
/**
* Request body converter converter.
*
* @param type the type
* @param parameterAnnotations the parameter annotations
* @param methodAnnotations the method annotations
* @param jianJia the jian jia
* @return the converter
*/
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, JianJia jianJia) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}
/**
* Response body converter converter.
*
* @param type the type
* @param annotations the annotations
* @param jianJia the jian jia
* @return the converter
*/
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, JianJia jianJia) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class) ?
StreamingResponseBodyConverter.INSTANCE :
BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
/**
* The type Request body converter.
*/
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
/**
* The Instance.
*/
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
/**
* Convert request body.
*
* @param value the value
* @return the request body
*/
@Override
public RequestBody convert(RequestBody value) {
return value;
}
}
/**
* The type Streaming response body converter.
*/
static final class StreamingResponseBodyConverter implements Converter<ResponseBody, ResponseBody> {
/**
* The Instance.
*/
static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
/**
* Convert response body.
*
* @param value the value
* @return the response body
* @throws IOException the io exception
*/
@Override
public ResponseBody convert(ResponseBody value) throws IOException {
return value;
}
}
/**
* The type Buffering response body converter.
*/
static final class BufferingResponseBodyConverter implements Converter<ResponseBody, ResponseBody> {
/**
* The Instance.
*/
static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();
/**
* Convert response body.
*
* @param value the value
* @return the response body
* @throws IOException the io exception
*/
@Override
public ResponseBody convert(ResponseBody value) throws IOException {
try {
return Utils.buffer(value);
} finally {
value.close();
}
}
}
/**
* The type Void response body converter.
*/
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
/**
* The Instance.
*/
static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();
/**
* Convert void.
*
* @param value the value
* @return the void
* @throws IOException the io exception
*/
@Override
public Void convert(ResponseBody value) throws IOException {
value.close();
return null;
}
}
/**
* The type To string converter.
*/
static final class ToStringConverter implements Converter<Object, String> {
/**
* The Instance.
*/
static final ToStringConverter INSTANCE = new ToStringConverter();
/**
* 直接调用toString方法
*
* @param value the value
* @return string string
* @throws IOException the io exception
*/
@Override
public String convert(Object value) throws IOException {
return value.toString();
}
}
}

View File

@ -0,0 +1,67 @@
package com.net.jianjia;
import okhttp3.Request;
import java.io.IOException;
/**
* 通过调用相应的方法向服务器发送请求并返回响应每一次调用都产生请求和响应
* 如果出现了失败重试的情况可以调用{@link #clone}方法复制
* 同步调用 采用{@link #execute}方法
* 异步采用{@link #enqueue}方法在任何情况下一个请求都有可以通过{@link #cancel}取消
* 一个Call在写入请求或读取响应的时候是可能产生IO异常的
*
* @param <T> 响应体类型
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public interface Call<T> extends Cloneable {
/**
* 同步请求直接返回响应对象
*
* @return response response
* @throws IOException the io exception
*/
Response<T> execute() throws IOException;
/**
* 异步请求通过回调将结果告知调用者
*
* @param callback the callback
*/
void enqueue(Callback<T> callback);
/**
* 如果请求正在执行返回true
*
* @return boolean boolean
*/
boolean isExecuted();
/**
* 取消请求
*/
void cancel();
/**
* 如果请求取消了返回true
*
* @return boolean boolean
*/
boolean isCanceled();
/**
* 复制一个新的call对象
*
* @return call call
*/
Call<T> clone();
/**
* 返回请求对象
*
* @return 请求对象 request
*/
Request request();
}

View File

@ -0,0 +1,49 @@
package com.net.jianjia;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* 将响应类型为{@code R}{@link Call}适配为{@code T}类型实例由对应的Factory来创建
* 这个对应的Factory是通过{@linkplain JianJia.Builder#addCallAdapterFactory(Factory)}方法添加到JianJia对象中的
*
* @param <R> the type parameter
* @param <T> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public interface CallAdapter<R, T> {
/**
* 返回响应类型例如"Call <Repo>"的响应类型是"Repo"
*
* @return type type
*/
Type responseType();
/**
* Call<T> 是适配成另外一个另外一个对象
*
* @param call the call
* @return t t
*/
T adapt(Call<R> call);
/**
* The type Factory.
*/
abstract class Factory {
/**
* 创建CallAdapter对象
*
* @param returnType 带有泛型的返回值
* @param annotations the annotations
* @param jianJia the jian jia
* @return call adapter
*/
public abstract CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
JianJia jianJia);
}
}

View File

@ -0,0 +1,27 @@
package com.net.jianjia;
/**
* The interface Callback.
*
* @param <T> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public interface Callback<T> {
/**
* On response.
*
* @param call the call
* @param response the response
*/
void onResponse(Call<T> call, Response<T> response);
/**
* On failure.
*
* @param call the call
* @param t the t
*/
void onFailure(Call<T> call, Throwable t);
}

View File

@ -0,0 +1,76 @@
package com.net.jianjia;
import com.net.jianjia.http.*;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* 数据转换器Converter这个类的实例由Factory创建{@linkplain JianJia.Builder#addConverterFactory(Factory)}方法来进行初始化的
*
* @param <F> the type parameter
* @param <T> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public interface Converter<F, T> {
/**
* 把F转化为T
*
* @param value the value
* @return t t
* @throws IOException the io exception
*/
T convert(F value) throws IOException;
/**
* The type Factory.
*/
abstract class Factory {
/**
* 返回一个处理请求体的转换器这个转换器主要是为了处理{@link Body}注解{@link Part}注解
*
* @param type the type
* @param parameterAnnotations the parameter annotations
* @param methodAnnotations the method annotations
* @param jianJia the jian jia
* @return converter converter
*/
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, JianJia jianJia) {
return null;
}
/**
* 返回一个处理响应体的转换器例如Call<SimpleResponse>则响应体的类型应该是SimpleResponse
*
* @param type the type
* @param annotations the annotations
* @param jianJia the jian jia
* @return converter converter
*/
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, JianJia jianJia) {
return null;
}
/**
* 返回一个处理字符串的转换器这个转换器主要是为了处理{@link Field}注解, {@link FieldMap}注解
* {@link Header}注解{@link HeaderMap}注解{@link Path}注解{@link Query}注解
* {@link QueryMap}注解
*
* @param type the type
* @param annotations the annotations
* @param jianJia the jian jia
* @return converter converter
*/
Converter<?, String> stringConverter(Type type, Annotation[] annotations, JianJia jianJia) {
return null;
}
}
}

View File

@ -0,0 +1,186 @@
package com.net.jianjia;
import com.net.jianjia.http.SkipCallbackExecutor;
import okhttp3.Request;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.Executor;
/**
* 默认的类型转换器如果调用者没有添加{@link CallAdapter}对象就会使用这个默认的类型转换器
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
class DefaultCallAdapterFactory extends CallAdapter.Factory {
/**
* The Callback executor.
*/
private final Executor callbackExecutor;
/**
* Instantiates a new Default call adapter factory.
*
* @param callbackExecutor the callback executor
*/
DefaultCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
/**
* Get call adapter.
*
* @param returnType the return type
* @param annotations the annotations
* @param jianJia the jian jia
* @return the call adapter
*/
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, JianJia jianJia) {
if (Utils.getRawType(returnType) != Call.class) return null;
// 返回值没有泛型
if (!(returnType instanceof ParameterizedType)) throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
// executor为空说明不需要将结果回调到主线程
Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ?
null : this.callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<?> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
/**
* The type Executor callback call.
*
* @param <T> the type parameter
*/
static final class ExecutorCallbackCall<T> implements Call<T> {
/**
* The Callback executor.
*/
final Executor callbackExecutor;
/**
* The Delegate.
*/
final Call<T> delegate;
/**
* Instantiates a new Executor callback call.
*
* @param callbackExecutor the callback executor
* @param delegate the delegate
*/
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
/**
* Execute response.
*
* @return the response
* @throws IOException the io exception
*/
@Override
public Response<T> execute() throws IOException {
return this.delegate.execute();
}
/**
* Enqueue.
*
* @param callback the callback
*/
@Override
public void enqueue(Callback<T> callback) {
Utils.checkNotNull(callback, "callback == null");
this.delegate.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, Response<T> response) {
ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
if (ExecutorCallbackCall.this.delegate.isCanceled())
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
else
callback.onResponse(ExecutorCallbackCall.this, response);
}
});
}
@Override
public void onFailure(Call<T> call, Throwable t) {
ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
/**
* Is executed boolean.
*
* @return the boolean
*/
@Override
public boolean isExecuted() {
return this.delegate.isExecuted();
}
/**
* Cancel.
*/
@Override
public void cancel() {
this.delegate.cancel();
}
/**
* Is canceled boolean.
*
* @return the boolean
*/
@Override
public boolean isCanceled() {
return this.delegate.isCanceled();
}
/**
* Clone call.
*
* @return the call
*/
@Override
public Call<T> clone() {
return new ExecutorCallbackCall<>(this.callbackExecutor, this.delegate.clone());
}
/**
* Request request.
*
* @return the request
*/
@Override
public Request request() {
return this.delegate.request();
}
}
}

View File

@ -0,0 +1,183 @@
package com.net.jianjia;
import okhttp3.ResponseBody;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/**
* The type Http service method.
*
* @param <ResponseT> the type parameter
* @param <ReturnT> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
/**
* The Request factory.
*/
private final RequestFactory requestFactory;
/**
* The Call factory.
*/
private final okhttp3.Call.Factory callFactory;
/**
* The Response converter.
*/
private final Converter<ResponseBody, ResponseT> responseConverter;
/**
* Instantiates a new Http service method.
*
* @param requestFactory the request factory
* @param callFactory the call factory
* @param responseConverter the response converter
*/
HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
/**
* Parse annotations http service method.
*
* @param <ResponseT> the type parameter
* @param <ReturnT> the type parameter
* @param jianJia the jian jia
* @param method the method
* @param requestFactory the request factory
* @return the http service method
*/
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
JianJia jianJia, Method method, RequestFactory requestFactory) {
Annotation[] annotations = method.getAnnotations();
Type adapterType = method.getGenericReturnType();
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(jianJia, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw Utils.methodError(method, "'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw Utils.methodError(method, "Response must include generic type (e.g., Response<String>)");
}
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw Utils.methodError(method, "HEAD method must use Void as response type.");
}
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(jianJia, method, responseType);
okhttp3.Call.Factory callFactory = jianJia.callFactory;
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
/**
* Create response converter converter.
*
* @param <ResponseT> the type parameter
* @param jianJia the jian jia
* @param method the method
* @param responseType the response type
* @return the converter
*/
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
JianJia jianJia, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return jianJia.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw Utils.methodError(method, e, "Unable to create converter for %s", responseType);
}
}
/**
* Create call adapter call adapter.
*
* @param <ReturnT> the type parameter
* @param <ResponseT> the type parameter
* @param jianJia the jian jia
* @param method the method
* @param returnType the return type
* @param annotations the annotations
* @return the call adapter
*/
private static <ReturnT, ResponseT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
JianJia jianJia, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) jianJia.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw Utils.methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
/**
* Invoke return t.
*
* @param args the args
* @return the return t
*/
@Override
public ReturnT invoke(Object[] args) {
OkHttpCall<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
/**
* Adapt return t.
*
* @param call the call
* @param args the args
* @return the return t
*/
protected abstract ReturnT adapt(Call<ResponseT> call, Object[] args);
/**
* The type Call adapted.
*
* @param <ResponseT> the type parameter
* @param <ReturnT> the type parameter
*/
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
/**
* The Call adapter.
*/
private final CallAdapter<ResponseT, ReturnT> callAdapter;
/**
* Instantiates a new Call adapted.
*
* @param requestFactory the request factory
* @param callFactory the call factory
* @param responseConverter the response converter
* @param callAdapter the call adapter
*/
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
/**
* Adapt return t.
*
* @param call the call
* @param args the args
* @return the return t
*/
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
}

View File

@ -0,0 +1,76 @@
package com.net.jianjia;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* The type Invocation.
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public final class Invocation {
/**
* The Method.
*/
private final Method method;
/**
* The Arguments.
*/
private final List<?> arguments;
/**
* Trusted constructor assumes ownership of {@code arguments}. @param method the method
*
* @param method the method
* @param arguments the arguments
*/
private Invocation(Method method, List<?> arguments) {
this.method = method;
this.arguments = Collections.unmodifiableList(arguments);
}
/**
* Of invocation.
*
* @param method the method
* @param arguments the arguments
* @return the invocation
*/
public static Invocation of(Method method, List<?> arguments) {
Utils.checkNotNull(method, "method == null");
Utils.checkNotNull(arguments, "arguments == null");
return new Invocation(method, new ArrayList<>(arguments)); // Defensive copy.
}
/**
* Method method.
*
* @return the method
*/
public Method method() {
return this.method;
}
/**
* Arguments list.
*
* @return the list
*/
public List<?> arguments() {
return this.arguments;
}
/**
* To string string.
*
* @return the string
*/
@Override
public String toString() {
return String.format("%s.%s() %s",
this.method.getDeclaringClass().getName(), this.method.getName(), this.arguments);
}
}

View File

@ -0,0 +1,484 @@
package com.net.jianjia;
import okhttp3.Call;
import okhttp3.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
/**
* The type Jian jia.
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public class JianJia {
/**
* 默认使用OkHttpClient如果需要对OkHttpClient进行详细的设置需要构建OkHttpClient对象然后传入过来
*/
final Call.Factory callFactory;
/**
* 域名
*/
final HttpUrl baseUrl;
/**
* 用于转换数据可以将返回的responseBody转化为实体对象
*/
private final List<Converter.Factory> converterFactories;
/**
* 对call对象进行转换默认情况下接口的方法的返回值为call对象
* 如果不想使用call对象那就可以添加一个callAdapterFactory对象
*/
private final List<CallAdapter.Factory> callAdapterFactories;
/**
* 用于将响应结果回调到主线程
*/
private final Executor callbackExecutor;
/**
* 如果为true当调用{@link #create}方法时就会去解析接口里面的所有的非默认非静态的方法
* 如果为false只有当调用接口里面的某个方法时才会去解析这个方法
*/
private final boolean validateEagerly;
/**
* 接口里面的方法可能会被多次调用如果不使用缓存每当调用接口里面的方法时都会解析方法这样就做了重复的工作
* 这里使用ConcurrentHashMap来缓存已经解析过的方法
*/
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
/**
* Instantiates a new Jian jia.
*
* @param callFactory the call factory
* @param baseUrl the base url
* @param converterFactories the converter factories
* @param callAdapterFactories the call adapter factories
* @param callbackExecutor the callback executor
* @param validateEagerly the validate eagerly
*/
JianJia(Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories;
this.callAdapterFactories = callAdapterFactories;
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
/**
* Create t.
*
* @param <T> the type parameter
* @param service the service
* @return the t
*/
public <T> T create(Class<T> service) {
Utils.validateServiceInterface(service);
if (this.validateEagerly) this.eagerlyValidateMethods(service);
return (T) Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[]{service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object类中的方法直接调用
if (method.getDeclaringClass() == Object.class) method.invoke(this, args);
args = args != null ? args : this.emptyArgs;
if (this.platform.isDefaultMethod(method))
this.platform.invokeDefaultMethod(method, service, proxy, args);
return JianJia.this.loadServiceMethod(method).invoke(args);
}
});
}
/**
* 优先验证接口里面的方法
*
* @param service the service
*/
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods())
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers()))
this.loadServiceMethod(method);
}
/**
* 加载接口里面的方法
*
* @param method the method
* @return service method
*/
private ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = this.serviceMethodCache.get(method);
// 之前已经解析过该方法不需要再次解析
if (result != null) return result;
synchronized (this.serviceMethodCache) {
result = this.serviceMethodCache.get(method);
if (result == null) {
// 之前没有解析过该方法解析
result = ServiceMethod.parseAnnotations(this, method);
// 将解析完的方法放入到缓存
this.serviceMethodCache.put(method, result);
}
}
return result;
}
/**
* String converter converter.
*
* @param <T> the type parameter
* @param type the type
* @param annotations the annotations
* @return the converter
*/
<T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
Utils.checkNotNull(type, "type == null");
Utils.checkNotNull(annotations, "annotations == null");
int count = this.converterFactories.size();
for (int i = 0; i < count; i++) {
Converter<?, String> converter = this.converterFactories.get(i).stringConverter(type, annotations, this);
if (converter != null) return (Converter<T, String>) converter;
}
return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
}
/**
* Call adapter call adapter.
*
* @param returnType the return type
* @param annotations the annotations
* @return the call adapter
*/
CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return this.nextCallAdapter(null, returnType, annotations);
}
/**
* Next call adapter call adapter.
*
* @param skipPast the skip past
* @param returnType the return type
* @param annotations the annotations
* @return the call adapter
*/
private CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
Utils.checkNotNull(returnType, "returnType == null");
Utils.checkNotNull(annotations, "annotations == null");
int start = this.callAdapterFactories.indexOf(skipPast) + 1;
int count = this.callAdapterFactories.size();
for (int i = start; i < count; i++) {
CallAdapter<?, ?> callAdapter = this.callAdapterFactories.get(i).get(returnType, annotations, this);
if (callAdapter != null) return callAdapter;
}
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++)
builder.append("\n * ").append(this.callAdapterFactories.get(i).getClass().getName());
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start; i < count; i++)
builder.append("\n * ").append(this.callAdapterFactories.get(i).getClass().getName());
throw new IllegalArgumentException(builder.toString());
}
/**
* Request body converter converter.
*
* @param <T> the type parameter
* @param type the type
* @param parameterAnnotations the parameter annotations
* @param methodAnnotations the method annotations
* @return the converter
*/
<T> Converter<T, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
return this.nextRequestBodyConverter(null, type, parameterAnnotations, methodAnnotations);
}
/**
* Next request body converter converter.
*
* @param <T> the type parameter
* @param skipPast the skip past
* @param type the type
* @param parameterAnnotations the parameter annotations
* @param methodAnnotations the method annotations
* @return the converter
*/
private <T> Converter<T, RequestBody> nextRequestBodyConverter(
Converter.Factory skipPast, Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations) {
Utils.checkNotNull(type, "type == null");
Utils.checkNotNull(parameterAnnotations, "parameterAnnotations == null");
Utils.checkNotNull(methodAnnotations, "methodAnnotations == null");
int start = this.converterFactories.indexOf(skipPast) + 1;
for (int i = start; i < this.converterFactories.size(); i++) {
Converter<?, RequestBody> converter = this.converterFactories.get(i).requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);
if (converter != null) return (Converter<T, RequestBody>) converter;
}
StringBuilder builder = new StringBuilder("Could not locate RequestBody converter for ")
.append(type)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++)
builder.append("\n * ").append(this.converterFactories.get(i).getClass().getName());
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = this.converterFactories.size(); i < count; i++)
builder.append("\n * ").append(this.converterFactories.get(i).getClass().getName());
throw new IllegalArgumentException(builder.toString());
}
/**
* Response body converter converter.
*
* @param <T> the type parameter
* @param type the type
* @param annotations the annotations
* @return the converter
*/
<T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return this.nextResponseBodyConverter(null, type, annotations);
}
/**
* Next response body converter converter.
*
* @param <T> the type parameter
* @param skipPast the skip past
* @param type the type
* @param annotations the annotations
* @return the converter
*/
private <T> Converter<ResponseBody, T> nextResponseBodyConverter(
Converter.Factory skipPast, Type type, Annotation[] annotations) {
Utils.checkNotNull(type, "type == null");
Utils.checkNotNull(annotations, "annotations == null");
int start = this.converterFactories.indexOf(skipPast) + 1;
int count = this.converterFactories.size();
for (int i = start; i < count; i++) {
Converter<ResponseBody, ?> converter = this.converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) return (Converter<ResponseBody, T>) converter;
}
StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
.append(type)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++)
builder.append("\n * ").append(this.converterFactories.get(i).getClass().getName());
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start; i < count; i++)
builder.append("\n * ").append(this.converterFactories.get(i).getClass().getName());
throw new IllegalArgumentException(builder.toString());
}
/**
* The type Builder.
*/
public static final class Builder {
/**
* The Platform.
*/
private final Platform platform;
/**
* The Converter factories.
*/
private final List<Converter.Factory> converterFactories = new ArrayList<>();
/**
* The Call adapter factories.
*/
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
/**
* The Base url.
*/
private HttpUrl baseUrl;
/**
* The Call factory.
*/
private Call.Factory callFactory;
/**
* The Callback executor.
*/
private Executor callbackExecutor;
/**
* The Validate eagerly.
*/
private boolean validateEagerly;
/**
* Instantiates a new Builder.
*/
public Builder() {
this(Platform.get());
}
/**
* Instantiates a new Builder.
*
* @param platform the platform
*/
Builder(Platform platform) {
this.platform = platform;
}
/**
* Base url builder.
*
* @param baseUrl the base url
* @return the builder
*/
public Builder baseUrl(String baseUrl) {
Utils.checkNotNull(baseUrl, "baseUrl == null");
return this.baseUrl(HttpUrl.get(baseUrl));
}
/**
* Base url builder.
*
* @param baseUrl the base url
* @return the builder
*/
Builder baseUrl(HttpUrl baseUrl) {
Utils.checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1)))
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
this.baseUrl = baseUrl;
return this;
}
/**
* Client builder.
*
* @param client the client
* @return the builder
*/
public Builder client(OkHttpClient client) {
Utils.checkNotNull(client, "client == null");
return this.callFactory(client);
}
/**
* Call factory builder.
*
* @param callFactory the call factory
* @return the builder
*/
public Builder callFactory(Call.Factory callFactory) {
this.callFactory = Utils.checkNotNull(callFactory, "callFactory == null");
return this;
}
/**
* Add converter factory builder.
*
* @param converterFactory the converter factory
* @return the builder
*/
public Builder addConverterFactory(Converter.Factory converterFactory) {
this.converterFactories.add(Utils.checkNotNull(converterFactory, "convertFactory == null"));
return this;
}
/**
* Add call adapter factory builder.
*
* @param callAdapterFactory the call adapter factory
* @return the builder
*/
Builder addCallAdapterFactory(CallAdapter.Factory callAdapterFactory) {
this.callAdapterFactories.add(Utils.checkNotNull(callAdapterFactory, "callAdapterFactory == null"));
return this;
}
/**
* Callback executor builder.
*
* @param callbackExecutor the callback executor
* @return the builder
*/
public Builder callbackExecutor(Executor callbackExecutor) {
this.callbackExecutor = Utils.checkNotNull(callbackExecutor, "callbackExecutor == null");
return this;
}
/**
* Validate eagerly builder.
*
* @param validateEagerly the validate eagerly
* @return the builder
*/
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
/**
* Converter factories list.
*
* @return the list
*/
public List<Converter.Factory> converterFactories() {
return this.converterFactories;
}
/**
* Call adapter factories list.
*
* @return the list
*/
public List<CallAdapter.Factory> callAdapterFactories() {
return this.callAdapterFactories;
}
/**
* Build jian jia.
*
* @return the jian jia
*/
public JianJia build() {
if (this.baseUrl == null) throw new IllegalArgumentException("base url required");
Call.Factory callFactory = this.callFactory;
if (callFactory == null) callFactory = new OkHttpClient();
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) callbackExecutor = this.platform.defaultCallbackExecutor();
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(this.platform.defaultCallAdapterFactories(callbackExecutor));
List<Converter.Factory> convertFactories = new ArrayList<>(
1 + this.converterFactories.size() + this.platform.defaultConverterFactoriesSize());
convertFactories.add(new BuiltInConverters());
convertFactories.addAll(this.converterFactories);
convertFactories.addAll(this.platform.defaultConverterFactories());
return new JianJia(callFactory, this.baseUrl, Collections.unmodifiableList(convertFactories),
Collections.unmodifiableList(callAdapterFactories), callbackExecutor, this.validateEagerly);
}
}
}

View File

@ -0,0 +1,464 @@
package com.net.jianjia;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import java.io.IOException;
/**
* The type Ok http call.
*
* @param <T> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
class OkHttpCall<T> implements Call<T> {
/**
* The Request factory.
*/
private final RequestFactory requestFactory;
/**
* The Args.
*/
private final Object[] args;
/**
* The Call factory.
*/
private final okhttp3.Call.Factory callFactory;
/**
* The Response converter.
*/
private final Converter<ResponseBody, T> responseConverter;
/**
* The Executed.
*/
private boolean executed;
/**
* The Creation failure.
*/
private Throwable creationFailure;
/**
* The Raw call.
*/
private okhttp3.Call rawCall;
/**
* The Canceled.
*/
private volatile boolean canceled;
/**
* Instantiates a new Ok http call.
*
* @param requestFactory the request factory
* @param args the args
* @param callFactory the call factory
* @param responseConverter the response converter
*/
OkHttpCall(RequestFactory requestFactory, Object[] args,
okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory;
this.args = args;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
/**
* Execute response.
*
* @return the response
* @throws IOException the io exception
*/
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) {
throw new IllegalStateException("Already executed.");
}
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
Utils.throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
/**
* Parse response response.
*
* @param rawResponse the raw response
* @return the response
* @throws IOException the io exception
*/
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
/**
* Create raw call okhttp 3 . call.
*
* @return the okhttp 3 . call
* @throws IOException the io exception
*/
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
/**
* Enqueue.
*
* @param callback the callback
*/
@Override
public void enqueue(Callback<T> callback) {
Utils.checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
Utils.throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
Utils.throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
Utils.throwIfFatal(t);
t.printStackTrace();
}
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
Utils.throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
/**
* Is executed boolean.
*
* @return the boolean
*/
@Override
public synchronized boolean isExecuted() {
return executed;
}
/**
* Cancel.
*/
@Override
public void cancel() {
canceled = true;
okhttp3.Call call;
synchronized (this) {
call = rawCall;
}
if (call != null) {
call.cancel();
}
}
/**
* Is canceled boolean.
*
* @return the boolean
*/
@Override
public boolean isCanceled() {
if (canceled) {
return true;
}
synchronized (this) {
return rawCall != null && rawCall.isCanceled();
}
}
/**
* Clone call.
*
* @return the call
*/
@Override
public Call<T> clone() {
return new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
}
/**
* Request request.
*
* @return the request
*/
@Override
public Request request() {
okhttp3.Call call = rawCall;
if (call != null) {
return call.request();
}
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw new RuntimeException("Unable to create request.", creationFailure);
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
try {
return (rawCall = createRawCall()).request();
} catch (RuntimeException | Error e) {
Utils.throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
} catch (IOException e) {
creationFailure = e;
throw new RuntimeException("Unable to create request.", e);
}
}
/**
* The type No content response body.
*/
static final class NoContentResponseBody extends ResponseBody {
/**
* The Content type.
*/
private final MediaType contentType;
/**
* The Content length.
*/
private final long contentLength;
/**
* Instantiates a new No content response body.
*
* @param contentType the content type
* @param contentLength the content length
*/
NoContentResponseBody(MediaType contentType, long contentLength) {
this.contentType = contentType;
this.contentLength = contentLength;
}
/**
* Content type media type.
*
* @return the media type
*/
@Override
public MediaType contentType() {
return contentType;
}
/**
* Content length long.
*
* @return the long
*/
@Override
public long contentLength() {
return contentLength;
}
/**
* Source buffered source.
*
* @return the buffered source
*/
@Override
public BufferedSource source() {
throw new IllegalStateException("Cannot read raw response body of a converted body.");
}
}
/**
* The type Exception catching response body.
*/
static final class ExceptionCatchingResponseBody extends ResponseBody {
/**
* The Delegate.
*/
private final ResponseBody delegate;
/**
* The Delegate source.
*/
private final BufferedSource delegateSource;
/**
* The Thrown exception.
*/
IOException thrownException;
/**
* Instantiates a new Exception catching response body.
*
* @param delegate the delegate
*/
ExceptionCatchingResponseBody(ResponseBody delegate) {
this.delegate = delegate;
this.delegateSource = Okio.buffer(new ForwardingSource(delegate.source()) {
@Override
public long read(Buffer sink, long byteCount) throws IOException {
try {
return super.read(sink, byteCount);
} catch (IOException e) {
thrownException = e;
throw e;
}
}
});
}
/**
* Content type media type.
*
* @return the media type
*/
@Override
public MediaType contentType() {
return delegate.contentType();
}
/**
* Content length long.
*
* @return the long
*/
@Override
public long contentLength() {
return delegate.contentLength();
}
/**
* Source buffered source.
*
* @return the buffered source
*/
@Override
public BufferedSource source() {
return delegateSource;
}
/**
* Close.
*/
@Override
public void close() {
delegate.close();
}
/**
* Throw if caught.
*
* @throws IOException the io exception
*/
void throwIfCaught() throws IOException {
if (thrownException != null) {
throw thrownException;
}
}
}
}

View File

@ -0,0 +1,753 @@
package com.net.jianjia;
import okhttp3.Headers;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Map;
/**
* The type Parameter handler.
*
* @param <T> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
abstract class ParameterHandler<T> {
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
abstract void apply(RequestBuilder builder, T value) throws IOException;
/**
* Iterable parameter handler.
*
* @return the parameter handler
*/
final ParameterHandler<Iterable<T>> iterable() {
return new ParameterHandler<Iterable<T>>() {
@Override
void apply(RequestBuilder builder, Iterable<T> value) throws IOException {
if (value == null) {
return;
}
for (T t : value) {
ParameterHandler.this.apply(builder, t);
}
}
};
}
/**
* Array parameter handler.
*
* @return the parameter handler
*/
final ParameterHandler<Object> array() {
return new ParameterHandler<Object>() {
@Override
void apply(RequestBuilder builder, Object value) throws IOException {
if (value == null) {
return;
}
int size = Array.getLength(value);
for (int i = 0; i < size; i++) {
//noinspection unchecked
ParameterHandler.this.apply(builder, (T) Array.get(value, i));
}
}
};
}
/**
* The type Relative url.
*/
static final class RelativeUrl extends ParameterHandler<Object> {
/**
* The Method.
*/
Method method;
/**
* The P.
*/
int p;
/**
* Instantiates a new Relative url.
*
* @param method the method
* @param p the p
*/
RelativeUrl(Method method, int p) {
this.method = method;
this.p = p;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, Object value) throws IOException {
if (value == null) {
throw Utils.parameterError(method, p, "@Url parameter is null.");
}
builder.setRelativeUrl(value);
}
}
/**
* The type Path.
*
* @param <T> the type parameter
*/
static final class Path<T> extends ParameterHandler<T> {
/**
* The Method.
*/
Method method;
/**
* The P.
*/
int p;
/**
* The Name.
*/
String name;
/**
* The Value converter.
*/
Converter<T, String> valueConverter;
/**
* The Encoded.
*/
boolean encoded;
/**
* Instantiates a new Path.
*
* @param method the method
* @param p the p
* @param name the name
* @param valueConverter the value converter
* @param encoded the encoded
*/
Path(Method method, int p, String name, Converter<T, String> valueConverter, boolean encoded) {
this.method = method;
this.p = p;
this.name = name;
this.valueConverter = valueConverter;
this.encoded = encoded;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, T value) throws IOException {
if (value == null) {
throw Utils.parameterError(method, p,
"Path parameter \"" + name + "\" value must not be null.");
}
builder.addPathParam(name, valueConverter.convert(value), encoded);
}
}
/**
* The type Query.
*
* @param <T> the type parameter
*/
static final class Query<T> extends ParameterHandler<T> {
/**
* The Name.
*/
private final String name;
/**
* The Value converter.
*/
private final Converter<T, String> valueConverter;
/**
* The Encoded.
*/
private final boolean encoded;
/**
* Instantiates a new Query.
*
* @param name the name
* @param valueConverter the value converter
* @param encoded the encoded
*/
Query(String name, Converter<T, String> valueConverter, boolean encoded) {
this.name = Utils.checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, T value) throws IOException {
if (value == null) {
return;
}
String queryValue = valueConverter.convert(value);
if (queryValue == null) {
return;
}
builder.addQueryParam(name, queryValue, encoded);
}
}
/**
* The type Query map.
*
* @param <T> the type parameter
*/
static final class QueryMap<T> extends ParameterHandler<Map<String, T>> {
/**
* The Method.
*/
private final Method method;
/**
* The P.
*/
private final int p;
/**
* The Value converter.
*/
private final Converter<T, String> valueConverter;
/**
* The Encoded.
*/
private final boolean encoded;
/**
* Instantiates a new Query map.
*
* @param method the method
* @param p the p
* @param valueConverter the value converter
* @param encoded the encoded
*/
QueryMap(Method method, int p, Converter<T, String> valueConverter, boolean encoded) {
this.method = method;
this.p = p;
this.valueConverter = valueConverter;
this.encoded = encoded;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, Map<String, T> value) throws IOException {
if (value == null) {
throw Utils.parameterError(method, p, "Query map was null");
}
for (Map.Entry<String, T> entry : value.entrySet()) {
String entryKey = entry.getKey();
if (entryKey == null) {
throw Utils.parameterError(method, p, "Query map contained null key.");
}
T entryValue = entry.getValue();
if (entryValue == null) {
throw Utils.parameterError(method, p,
"Query map contained null value for key '" + entryKey + "'.");
}
String convertedEntryValue = valueConverter.convert(entryValue);
if (convertedEntryValue == null) {
throw Utils.parameterError(method, p, "Query map value '"
+ entryValue
+ "' converted to null by "
+ valueConverter.getClass().getName()
+ " for key '"
+ entryKey
+ "'.");
}
builder.addQueryParam(entryKey, convertedEntryValue, encoded);
}
}
}
/**
* The type Header.
*
* @param <T> the type parameter
*/
static final class Header<T> extends ParameterHandler<T> {
/**
* The Name.
*/
private final String name;
/**
* The Value converter.
*/
private final Converter<T, String> valueConverter;
/**
* Instantiates a new Header.
*
* @param name the name
* @param valueConverter the value converter
*/
Header(String name, Converter<T, String> valueConverter) {
this.name = Utils.checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, T value) throws IOException {
if (value == null) {
return;
}
String queryValue = valueConverter.convert(value);
if (queryValue == null) {
return;
}
builder.addHeader(name, queryValue);
}
}
/**
* The type Header map.
*
* @param <T> the type parameter
*/
static final class HeaderMap<T> extends ParameterHandler<Map<String, T>> {
/**
* The Method.
*/
private final Method method;
/**
* The P.
*/
private final int p;
/**
* The Value converter.
*/
private final Converter<T, String> valueConverter;
/**
* Instantiates a new Header map.
*
* @param method the method
* @param p the p
* @param valueConverter the value converter
*/
HeaderMap(Method method, int p, Converter<T, String> valueConverter) {
this.method = method;
this.p = p;
this.valueConverter = valueConverter;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, Map<String, T> value) throws IOException {
if (value == null) {
throw Utils.parameterError(method, p, "Header map was null");
}
for (Map.Entry<String, T> entry : value.entrySet()) {
String headerName = entry.getKey();
if (headerName == null) {
throw Utils.parameterError(method, p, "Header map contained null key.");
}
T headerValue = entry.getValue();
if (headerValue == null) {
throw Utils.parameterError(method, p,
"Header map contained null value for key '" + headerName + "'.");
}
builder.addHeader(headerName, valueConverter.convert(headerValue));
}
}
}
/**
* The type Field.
*
* @param <T> the type parameter
*/
static final class Field<T> extends ParameterHandler<T> {
/**
* The Name.
*/
private final String name;
/**
* The Value converter.
*/
private final Converter<T, String> valueConverter;
/**
* The Encoded.
*/
private final boolean encoded;
/**
* Instantiates a new Field.
*
* @param name the name
* @param valueConverter the value converter
* @param encoded the encoded
*/
Field(String name, Converter<T, String> valueConverter, boolean encoded) {
this.name = Utils.checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, T value) throws IOException {
if (value == null) {
return;
}
String fieldValue = valueConverter.convert(value);
if (fieldValue == null) {
return;
}
builder.addFormField(name, fieldValue, encoded);
}
}
/**
* The type Field map.
*
* @param <T> the type parameter
*/
static final class FieldMap<T> extends ParameterHandler<Map<String, T>> {
/**
* The Method.
*/
private final Method method;
/**
* The P.
*/
private final int p;
/**
* The Value converter.
*/
private final Converter<T, String> valueConverter;
/**
* The Encoded.
*/
private final boolean encoded;
/**
* Instantiates a new Field map.
*
* @param method the method
* @param p the p
* @param valueConverter the value converter
* @param encoded the encoded
*/
FieldMap(Method method, int p, Converter<T, String> valueConverter, boolean encoded) {
this.method = method;
this.p = p;
this.valueConverter = valueConverter;
this.encoded = encoded;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, Map<String, T> value) throws IOException {
if (value == null) {
throw Utils.parameterError(method, p, "Query map was null");
}
for (Map.Entry<String, T> entry : value.entrySet()) {
String entryKey = entry.getKey();
if (entryKey == null) {
throw Utils.parameterError(method, p, "Query map contained null key.");
}
T entryValue = entry.getValue();
if (entryValue == null) {
throw Utils.parameterError(method, p,
"Query map contained null value for key '" + entryKey + "'.");
}
String fieldEntry = valueConverter.convert(entryValue);
if (fieldEntry == null) {
throw Utils.parameterError(method, p, "Query map value '"
+ entryValue
+ "' converted to null by "
+ valueConverter.getClass().getName()
+ " for key '"
+ entryKey
+ "'.");
}
builder.addFormField(entryKey, fieldEntry, encoded);
}
}
}
/**
* The type Body.
*
* @param <T> the type parameter
*/
static final class Body<T> extends ParameterHandler<T> {
/**
* The Method.
*/
final Method method;
/**
* The P.
*/
final int p;
/**
* The Converter.
*/
final Converter<T, RequestBody> converter;
/**
* Instantiates a new Body.
*
* @param method the method
* @param p the p
* @param converter the converter
*/
Body(Method method, int p, Converter<T, RequestBody> converter) {
this.method = method;
this.p = p;
this.converter = converter;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, T value) throws IOException {
if (value == null) {
throw Utils.parameterError(method, p, "Body parameter value must not be null.");
}
RequestBody body;
try {
body = converter.convert(value);
} catch (IOException e) {
throw Utils.parameterError(method, e, p, "Unable to convert " + value + " to RequestBody");
}
builder.setBody(body);
}
}
/**
* The type Part.
*
* @param <T> the type parameter
*/
static final class Part<T> extends ParameterHandler<T> {
/**
* The Method.
*/
private final Method method;
/**
* The P.
*/
private final int p;
/**
* The Headers.
*/
private final Headers headers;
/**
* The Converter.
*/
private final Converter<T, RequestBody> converter;
/**
* Instantiates a new Part.
*
* @param method the method
* @param p the p
* @param headers the headers
* @param converter the converter
*/
Part(Method method, int p, Headers headers, Converter<T, RequestBody> converter) {
this.method = method;
this.p = p;
this.headers = headers;
this.converter = converter;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
*/
@Override
void apply(RequestBuilder builder, T value) {
if (value == null) return; // Skip null values.
RequestBody body;
try {
body = converter.convert(value);
} catch (IOException e) {
throw Utils.parameterError(method, p, "Unable to convert " + value + " to RequestBody", e);
}
builder.addPart(headers, body);
}
}
/**
* The type Raw part.
*/
static final class RawPart extends ParameterHandler<MultipartBody.Part> {
/**
* The Instance.
*/
static final RawPart INSTANCE = new RawPart();
/**
* Instantiates a new Raw part.
*/
private RawPart() {
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
*/
@Override
void apply(RequestBuilder builder, MultipartBody.Part value) {
if (value != null) { // Skip null values.
builder.addPart(value);
}
}
}
/**
* The type Part map.
*
* @param <T> the type parameter
*/
static final class PartMap<T> extends ParameterHandler<Map<String, T>> {
/**
* The Method.
*/
private final Method method;
/**
* The P.
*/
private final int p;
/**
* The Value converter.
*/
private final Converter<T, RequestBody> valueConverter;
/**
* The Transfer encoding.
*/
private final String transferEncoding;
/**
* Instantiates a new Part map.
*
* @param method the method
* @param p the p
* @param valueConverter the value converter
* @param transferEncoding the transfer encoding
*/
PartMap(Method method, int p,
Converter<T, RequestBody> valueConverter, String transferEncoding) {
this.method = method;
this.p = p;
this.valueConverter = valueConverter;
this.transferEncoding = transferEncoding;
}
/**
* Apply.
*
* @param builder the builder
* @param value the value
* @throws IOException the io exception
*/
@Override
void apply(RequestBuilder builder, Map<String, T> value)
throws IOException {
if (value == null) {
throw Utils.parameterError(method, p, "Part map was null.");
}
for (Map.Entry<String, T> entry : value.entrySet()) {
String entryKey = entry.getKey();
if (entryKey == null) {
throw Utils.parameterError(method, p, "Part map contained null key.");
}
T entryValue = entry.getValue();
if (entryValue == null) {
throw Utils.parameterError(method, p,
"Part map contained null value for key '" + entryKey + "'.");
}
Headers headers = Headers.of(
"Content-Disposition", "form-data; name=\"" + entryKey + "\"",
"Content-Transfer-Encoding", transferEncoding);
builder.addPart(headers, valueConverter.convert(entryValue));
}
}
}
}

View File

@ -0,0 +1,168 @@
package com.net.jianjia;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.system.version.SystemVersion;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import static java.util.Collections.singletonList;
/**
* The type Platform.
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
class Platform {
/**
* The constant PLATFORM.
*/
private static final Platform PLATFORM = findPlatform();
/**
* Get platform.
*
* @return the platform
*/
static Platform get() {
return PLATFORM;
}
/**
* Find platform platform.
*
* @return the platform
*/
private static Platform findPlatform() {
try {
Class.forName("ohos.system.version.SystemVersion");
if (SystemVersion.getApiVersion() != 0) return new Harmony();
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
/**
* Default callback executor executor.
*
* @return the executor
*/
public Executor defaultCallbackExecutor() {
return null;
}
/**
* Default call adapter factories list.
*
* @param callbackExecutor the callback executor
* @return the list
*/
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(Executor callbackExecutor) {
return singletonList(new DefaultCallAdapterFactory(callbackExecutor));
}
/**
* Default converter factories size int.
*
* @return the int
*/
int defaultConverterFactoriesSize() {
return 1;
}
/**
* Default converter factories list.
*
* @return the list
*/
List<? extends Converter.Factory> defaultConverterFactories() {
return Collections.emptyList();
}
/**
* Is default method boolean.
*
* @param method the method
* @return the boolean
*/
boolean isDefaultMethod(Method method) {
return method.isDefault();
}
/**
* Invoke default method object.
*
* @param method the method
* @param declaringClass the declaring class
* @param object the object
* @param args the args
* @return the object
* @throws Throwable the throwable
*/
Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, Object... args)
throws Throwable {
Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
return constructor.newInstance(declaringClass, -1 /* trusted */)
.unreflectSpecial(method, declaringClass)
.bindTo(object)
.invokeWithArguments(args);
}
/**
* The type Harmony.
*/
static class Harmony extends Platform {
/**
* Default callback executor executor.
*
* @return the executor
*/
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutorOnHarmony();
}
/**
* The type Main thread executor on harmony.
*/
static class MainThreadExecutorOnHarmony implements Executor {
/**
* The Event handler.
*/
private final EventHandler eventHandler = new EventHandler(EventRunner.getMainEventRunner());
/**
* Execute.
*
* @param runnable the runnable
*/
@Override
public void execute(Runnable runnable) {
this.eventHandler.postTask(runnable);
}
}
}
/**
* The type Java 8.
*/
private static class Java8 extends Platform {
}
}

View File

@ -0,0 +1,395 @@
package com.net.jianjia;
import okhttp3.*;
import okio.Buffer;
import okio.BufferedSink;
import java.io.IOException;
import java.util.regex.Pattern;
/**
* The type Request builder.
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
class RequestBuilder {
/**
* The constant HEX_DIGITS.
*/
private static final char[] HEX_DIGITS =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* The constant PATH_SEGMENT_ALWAYS_ENCODE_SET.
*/
private static final String PATH_SEGMENT_ALWAYS_ENCODE_SET = " \"<>^`{}|\\?#";
/**
* The constant PATH_TRAVERSAL.
*/
private static final Pattern PATH_TRAVERSAL = Pattern.compile("(.*/)?(\\.|%2e|%2E){1,2}(/.*)?");
/**
* The Method.
*/
private final String method;
/**
* The Base url.
*/
private final HttpUrl baseUrl;
/**
* The New base url.
*/
private final HttpUrl newBaseUrl;
/**
* The Request builder.
*/
private final Request.Builder requestBuilder;
/**
* The Has body.
*/
private final boolean hasBody;
/**
* The Relative url.
*/
private String relativeUrl;
/**
* The Url builder.
*/
private HttpUrl.Builder urlBuilder;
/**
* The Content type.
*/
private MediaType contentType;
/**
* The Multipart builder.
*/
private MultipartBody.Builder multipartBuilder;
/**
* The Form builder.
*/
private FormBody.Builder formBuilder;
/**
* The Body.
*/
private RequestBody body;
/**
* Instantiates a new Request builder.
*
* @param method the method
* @param baseUrl the base url
* @param newBaseUrl the new base url
* @param relativeUrl the relative url
* @param headers the headers
* @param contentType the content type
* @param hasBody the has body
* @param isFormEncoded the is form encoded
* @param isMultipart the is multipart
*/
RequestBuilder(String method, HttpUrl baseUrl, HttpUrl newBaseUrl, String relativeUrl, Headers headers, MediaType contentType,
boolean hasBody, boolean isFormEncoded, boolean isMultipart) {
this.method = method;
this.baseUrl = baseUrl;
this.newBaseUrl = newBaseUrl;
this.relativeUrl = relativeUrl;
this.requestBuilder = new Request.Builder();
this.contentType = contentType;
this.hasBody = hasBody;
if (headers != null) {
this.requestBuilder.headers(headers);
}
if (isFormEncoded) {
formBuilder = new FormBody.Builder();
} else if (isMultipart) {
multipartBuilder = new MultipartBody.Builder();
multipartBuilder.setType(MultipartBody.FORM);
}
}
/**
* Canonicalize for path string.
*
* @param input the input
* @param alreadyEncoded the already encoded
* @return the string
*/
private static String canonicalizeForPath(String input, boolean alreadyEncoded) {
int codePoint;
for (int i = 0, limit = input.length(); i < limit; i += Character.charCount(codePoint)) {
codePoint = input.codePointAt(i);
if (codePoint < 0x20 || codePoint >= 0x7f
|| PATH_SEGMENT_ALWAYS_ENCODE_SET.indexOf(codePoint) != -1
|| (!alreadyEncoded && (codePoint == '/' || codePoint == '%'))) {
// Slow path: the character at i requires encoding!
Buffer out = new Buffer();
out.writeUtf8(input, 0, i);
canonicalizeForPath(out, input, i, limit, alreadyEncoded);
return out.readUtf8();
}
}
// Fast path: no characters required encoding.
return input;
}
/**
* Canonicalize for path.
*
* @param out the out
* @param input the input
* @param pos the pos
* @param limit the limit
* @param alreadyEncoded the already encoded
*/
private static void canonicalizeForPath(Buffer out, String input, int pos, int limit,
boolean alreadyEncoded) {
Buffer utf8Buffer = null; // Lazily allocated.
int codePoint;
for (int i = pos; i < limit; i += Character.charCount(codePoint)) {
codePoint = input.codePointAt(i);
if (alreadyEncoded
&& (codePoint == '\t' || codePoint == '\n' || codePoint == '\f' || codePoint == '\r')) {
// Skip this character.
} else if (codePoint < 0x20 || codePoint >= 0x7f
|| PATH_SEGMENT_ALWAYS_ENCODE_SET.indexOf(codePoint) != -1
|| (!alreadyEncoded && (codePoint == '/' || codePoint == '%'))) {
// Percent encode this character.
if (utf8Buffer == null) {
utf8Buffer = new Buffer();
}
utf8Buffer.writeUtf8CodePoint(codePoint);
while (!utf8Buffer.exhausted()) {
int b = utf8Buffer.readByte() & 0xff;
out.writeByte('%');
out.writeByte(HEX_DIGITS[(b >> 4) & 0xf]);
out.writeByte(HEX_DIGITS[b & 0xf]);
}
} else {
// This character doesn't need encoding. Just copy it over.
out.writeUtf8CodePoint(codePoint);
}
}
}
/**
* Get request . builder.
*
* @return the request . builder
*/
Request.Builder get() {
HttpUrl url;
HttpUrl.Builder urlBuilder = this.urlBuilder;
if (urlBuilder != null) {
url = urlBuilder.build();
} else {
if (newBaseUrl != null) {
url = newBaseUrl.resolve(relativeUrl);
} else {
url = baseUrl.resolve(relativeUrl);
}
if (url == null) {
throw new IllegalArgumentException(
"Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
}
}
RequestBody body = this.body;
if (body == null) {
if (formBuilder != null) {
body = formBuilder.build();
} else if (multipartBuilder != null) {
body = multipartBuilder.build();
} else if (hasBody) {
body = RequestBody.create(null, new byte[0]);
}
}
MediaType contentType = this.contentType;
if (contentType != null) {
if (body != null) {
body = new ContentTypeOverridingRequestBody(body, contentType);
} else {
requestBuilder.addHeader("Content-Type", contentType.toString());
}
}
return requestBuilder.url(url).method(method, body);
}
/**
* Sets body.
*
* @param body the body
*/
void setBody(RequestBody body) {
this.body = body;
}
/**
* Add part.
*
* @param headers the headers
* @param body the body
*/
void addPart(Headers headers, RequestBody body) {
multipartBuilder.addPart(headers, body);
}
/**
* Add part.
*
* @param part the part
*/
@SuppressWarnings("ConstantConditions")
// Only called when isMultipart was true.
void addPart(MultipartBody.Part part) {
multipartBuilder.addPart(part);
}
/**
* Add form field.
*
* @param name the name
* @param value the value
* @param encoded the encoded
*/
void addFormField(String name, String value, boolean encoded) {
if (encoded) {
formBuilder.addEncoded(name, value);
} else {
formBuilder.add(name, value);
}
}
/**
* Add path param.
*
* @param name the name
* @param value the value
* @param encoded the encoded
*/
void addPathParam(String name, String value, boolean encoded) {
if (relativeUrl == null) {
throw new AssertionError();
}
String replacement = canonicalizeForPath(value, encoded);
String newRelativeUrl = relativeUrl.replace("{" + name + "}", replacement);
if (PATH_TRAVERSAL.matcher(newRelativeUrl).matches()) {
throw new IllegalArgumentException(
"@Path parameters shouldn't perform path traversal ('.' or '..'): " + value);
}
relativeUrl = newRelativeUrl;
}
/**
* Add query param.
*
* @param name the name
* @param value the value
* @param encoded the encoded
*/
void addQueryParam(String name, String value, boolean encoded) {
if (relativeUrl != null) {
if (newBaseUrl != null) {
urlBuilder = newBaseUrl.newBuilder(relativeUrl);
} else {
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
if (urlBuilder == null) {
throw new IllegalArgumentException(
"Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
}
relativeUrl = null;
}
if (encoded) {
urlBuilder.addEncodedQueryParameter(name, value);
} else {
urlBuilder.addQueryParameter(name, value);
}
}
/**
* Add header.
*
* @param name the name
* @param value the value
*/
void addHeader(String name, String value) {
if ("Content-Type".equalsIgnoreCase(name)) {
try {
contentType = MediaType.get(value);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Malformed content type: " + value, e);
}
} else {
requestBuilder.addHeader(name, value);
}
}
/**
* Sets relative url.
*
* @param relativeUrl the relative url
*/
void setRelativeUrl(Object relativeUrl) {
this.relativeUrl = relativeUrl.toString();
}
/**
* The type Content type overriding request body.
*/
private static class ContentTypeOverridingRequestBody extends RequestBody {
/**
* The Delegate.
*/
private final RequestBody delegate;
/**
* The Content type.
*/
private final MediaType contentType;
/**
* Instantiates a new Content type overriding request body.
*
* @param delegate the delegate
* @param contentType the content type
*/
ContentTypeOverridingRequestBody(RequestBody delegate, MediaType contentType) {
this.delegate = delegate;
this.contentType = contentType;
}
/**
* Content type media type.
*
* @return the media type
*/
@Override
public MediaType contentType() {
return contentType;
}
/**
* Content length long.
*
* @return the long
* @throws IOException the io exception
*/
@Override
public long contentLength() throws IOException {
return delegate.contentLength();
}
/**
* Write to.
*
* @param sink the sink
* @throws IOException the io exception
*/
@Override
public void writeTo(BufferedSink sink) throws IOException {
delegate.writeTo(sink);
}
}
}

View File

@ -0,0 +1,919 @@
package com.net.jianjia;
import com.net.jianjia.http.*;
import okhttp3.Headers;
import okhttp3.*;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.net.jianjia.Utils.methodError;
import static com.net.jianjia.Utils.parameterError;
/**
* The type Request factory.
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
final class RequestFactory {
/**
* 请求方法
*/
final String httpMethod;
/**
* 相对路径
*/
private final String relativeUrl;
/**
* The Method.
*/
private final Method method;
/**
* 请求的域名如果没有在方法上使用{@link BaseUrl @BaseUrl}注解在请求服务端的时候就会使用这个变量
*/
private final HttpUrl httpUrl;
/**
* 请求的域名如果在方法上使用了{@link BaseUrl @BaseUrl}注解在请求服务端的时候就会使用这个变量
*/
private final HttpUrl newHttpUrl;
/**
* 请求头
*/
private final Headers headers;
/**
* The Content type.
*/
private final MediaType contentType;
/**
* The Has body.
*/
private final boolean hasBody;
/**
* 是否使用了{@link FormUrlEncoded}注解
*/
private final boolean isFormEncoded;
/**
* 是否使用了{@link Multipart}注解
*/
private final boolean isMultipart;
/**
* 用于保存在参数声明的注解
*/
private final ParameterHandler<?>[] parameterHandlers;
/**
* Instantiates a new Request factory.
*
* @param builder the builder
*/
RequestFactory(Builder builder) {
this.method = builder.method;
this.httpUrl = builder.jianJia.baseUrl;
this.newHttpUrl = builder.newBaseUrl;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
/**
* 解析完方法上的注解和参数上的注解后使用构造者模式对变量进行复制
*
* @param jianjia the jianjia
* @param method the method
* @return request factory
*/
static RequestFactory parseAnnotations(JianJia jianjia, Method method) {
return new Builder(jianjia, method).build();
}
/**
* 创建请求对象使用OKHTTP的request对象
*
* @param args the args
* @return okhttp 3 . request
* @throws IOException the io exception
*/
okhttp3.Request create(Object[] args) throws IOException {
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) this.parameterHandlers;
int argumentCount = args.length;
if (argumentCount != handlers.length) throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
RequestBuilder requestBuilder = new RequestBuilder(this.httpMethod, this.httpUrl, this.newHttpUrl, this.relativeUrl, this.headers,
this.contentType, this.hasBody, this.isFormEncoded, this.isMultipart);
List<Object> argumentList = new ArrayList<>(argumentCount);
for (int i = 0; i < argumentCount; i++) {
argumentList.add(args[i]);
handlers[i].apply(requestBuilder, args[i]);
}
return requestBuilder.get()
.tag(Invocation.class, Invocation.of(this.method, argumentList))
.build();
}
/**
* The type Builder.
*/
static final class Builder {
/**
* The constant PARAM.
*/
// 以字符开头的大小写字母数字下划线和连字符
private static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
/**
* The constant PARAM_URL_REGEX.
*/
private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
/**
* The constant PARAM_NAME_REGEX.
*/
private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
/**
* The Jian jia.
*/
final JianJia jianJia;
/**
* The Method.
*/
final Method method;
/**
* 方法上的注解
*/
final Annotation[] methodAnnotations;
/**
* 方法参数上面的注解
*/
final Annotation[][] parameterAnnotationsArray;
/**
* 方法参数的类型
*/
final Type[] parameterTypes;
/**
* The Got field.
*/
boolean gotField;
/**
* The Got part.
*/
boolean gotPart;
/**
* The Got body.
*/
boolean gotBody;
/**
* The Got path.
*/
boolean gotPath;
/**
* The Got query.
*/
boolean gotQuery;
/**
* The Got query name.
*/
boolean gotQueryName;
/**
* The Got query map.
*/
boolean gotQueryMap;
/**
* The Got url.
*/
boolean gotUrl;
/**
* 请求方法
*/
String httpMethod;
/**
* The Has body.
*/
boolean hasBody;
/**
* The Is form encoded.
*/
boolean isFormEncoded;
/**
* The Is multipart.
*/
boolean isMultipart;
/**
* 相对路径
*/
String relativeUrl;
/**
* 相对路径里面会带有参数这个就是参数的集合
*/
Set<String> relativeUrlParamNames;
/**
* 请求头
*/
Headers headers;
/**
* The Content type.
*/
MediaType contentType;
/**
* 用于保存参数的注解
*/
ParameterHandler<?>[] parameterHandlers;
/**
* 如果在方法上使用了{@link BaseUrl @BaseUrl}注解这个参数就不会为空
*/
HttpUrl newBaseUrl;
/**
* Instantiates a new Builder.
*
* @param jianJia the jian jia
* @param method the method
*/
Builder(JianJia jianJia, Method method) {
this.jianJia = jianJia;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
/**
* 假设需要解析这样的相对路径/repos/{owner}/{repo}/contributors
* 这个方法就是将owner和repo放入集合
*
* @param path /repos/{owner}/{repo}/contributors
* @return set set
*/
static Set<String> parsePathParameters(String path) {
Matcher m = PARAM_URL_REGEX.matcher(path);
Set<String> patterns = new LinkedHashSet<>();
while (m.find()) patterns.add(m.group(1));
return patterns;
}
/**
* 判断基本数据类型
*
* @param type the type
* @return class class
*/
private static Class<?> boxIfPrimitive(Class<?> type) {
if (boolean.class == type) return Boolean.class;
if (byte.class == type) return Byte.class;
if (char.class == type) return Character.class;
if (double.class == type) return Double.class;
if (float.class == type) return Float.class;
if (int.class == type) return Integer.class;
if (long.class == type) return Long.class;
if (short.class == type) return Short.class;
return type;
}
/**
* Build request factory.
*
* @return the request factory
*/
RequestFactory build() {
for (Annotation annotation : this.methodAnnotations) this.parseMethodAnnotation(annotation);
// 解析完注解后需要判断是否提供了请求方法
if (this.httpMethod == null)
throw methodError(this.method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
if (!this.hasBody) {
if (this.isMultipart) throw methodError(this.method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
if (this.isFormEncoded)
throw methodError(this.method, "FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
// 参数注解的个数
int parameterCount = this.parameterAnnotationsArray.length;
this.parameterHandlers = new ParameterHandler<?>[parameterCount];
// 解析参数上的注解
for (int p = 0; p < parameterCount; p++)
this.parameterHandlers[p] = this.parseParameter(p, this.parameterTypes[p], this.parameterAnnotationsArray[p]);
if (this.relativeUrl == null && !this.gotUrl)
throw methodError(this.method, "Missing either @%s URL or @Url parameter.", this.httpMethod);
if (!this.isFormEncoded && !this.isMultipart && !this.hasBody && this.gotBody)
throw methodError(this.method, "Non-body HTTP method cannot contain @Body.");
if (this.isFormEncoded && !this.gotField)
throw methodError(this.method, "Form-encoded method must contain at least one @Field.");
if (this.isMultipart && !this.gotPart)
throw methodError(this.method, "Multipart method must contain at least one @Part.");
return new RequestFactory(this);
}
/**
* Parse parameter parameter handler.
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @return the parameter handler
*/
private ParameterHandler<?> parseParameter(int p, Type type, Annotation[] annotations) {
ParameterHandler<?> result = null;
if (annotations != null) for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction =
this.parseParameterAnnotation(p, type, annotations, annotation);
if (annotation == null) continue;
if (result != null) throw parameterError(this.method, p,
"Multiple Retrofit annotations found, only one allowed.");
result = annotationAction;
}
if (result == null) throw parameterError(this.method, p, "No Retrofit annotation found.");
return result;
}
/**
* Parse parameter annotation parameter handler.
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return the parameter handler
*/
private ParameterHandler<?> parseParameterAnnotation(int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Url) return this.parseUrl(p, type, annotations, annotation);
else if (annotation instanceof Path) return this.parsePath(p, type, annotations, annotation);
else if (annotation instanceof Query) return this.parseQuery(p, type, annotations, annotation);
else if (annotation instanceof QueryMap) return this.parseQueryMap(p, type, annotations, annotation);
else if (annotation instanceof Header) return this.parseHeader(p, type, annotations, annotation);
else if (annotation instanceof HeaderMap) return this.parseHeaderMap(p, type, annotations, annotation);
else if (annotation instanceof Field) return this.parseField(p, type, annotations, annotation);
else if (annotation instanceof FieldMap) return this.parseFieldMap(p, type, annotations, annotation);
else if (annotation instanceof Body) return this.parseBody(p, type, annotations, annotation);
else if (annotation instanceof Part) return this.parsePart(p, type, annotations, annotation);
else if (annotation instanceof PartMap) return this.parsePartMap(p, type, annotations, annotation);
return null;
}
/**
* Parse part map parameter handler.
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return the parameter handler
*/
private ParameterHandler<?> parsePartMap(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
if (!this.isMultipart) throw parameterError(this.method, p,
"@PartMap parameters can only be used with multipart encoding.");
this.gotPart = true;
Class<?> rawParameterType = Utils.getRawType(type);
if (!Map.class.isAssignableFrom(rawParameterType))
throw parameterError(this.method, p, "@PartMap parameter type must be Map.");
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
if (!(mapType instanceof ParameterizedType)) throw parameterError(this.method, p,
"Map must include generic types (e.g., Map<String, String>)");
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType)
throw parameterError(this.method, p, "@PartMap keys must be of type String: " + keyType);
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(valueType)))
throw parameterError(this.method, p, "@PartMap values cannot be MultipartBody.Part. "
+ "Use @Part List<Part> or a different value type instead.");
Converter<?, RequestBody> valueConverter =
this.jianJia.requestBodyConverter(valueType, annotations, this.methodAnnotations);
PartMap partMap = (PartMap) annotation;
return new ParameterHandler.PartMap<>(this.method, p, valueConverter, partMap.encoding());
}
/**
* Parse part parameter handler.
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return the parameter handler
*/
private ParameterHandler<?> parsePart(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
if (!this.isMultipart) throw parameterError(this.method, p,
"@Part parameters can only be used with multipart encoding.");
Part part = (Part) annotation;
this.gotPart = true;
String partName = part.value();
Class<?> rawParameterType = Utils.getRawType(type);
if (partName.isEmpty()) if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType))
throw parameterError(this.method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
if (!MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType)))
throw parameterError(this.method, p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
return ParameterHandler.RawPart.INSTANCE.iterable();
} else if (rawParameterType.isArray()) {
Class<?> arrayComponentType = rawParameterType.getComponentType();
if (!MultipartBody.Part.class.isAssignableFrom(arrayComponentType))
throw parameterError(this.method, p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
return ParameterHandler.RawPart.INSTANCE.array();
} else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType))
return ParameterHandler.RawPart.INSTANCE;
else throw parameterError(this.method, p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
else {
Headers headers =
Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
"Content-Transfer-Encoding", part.encoding());
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType))
throw parameterError(this.method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType)))
throw parameterError(this.method, p,
"@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
Converter<?, RequestBody> converter =
this.jianJia.requestBodyConverter(iterableType, annotations, this.methodAnnotations);
return new ParameterHandler.Part<>(this.method, p, headers, converter).iterable();
} else if (rawParameterType.isArray()) {
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
if (MultipartBody.Part.class.isAssignableFrom(arrayComponentType))
throw parameterError(this.method, p,
"@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
Converter<?, RequestBody> converter =
this.jianJia.requestBodyConverter(arrayComponentType, annotations, this.methodAnnotations);
return new ParameterHandler.Part<>(this.method, p, headers, converter).array();
} else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType))
throw parameterError(this.method, p,
"@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
else {
Converter<?, RequestBody> converter =
this.jianJia.requestBodyConverter(type, annotations, this.methodAnnotations);
return new ParameterHandler.Part<>(this.method, p, headers, converter);
}
}
}
/**
* 解析{@link Body}注解内部会把该实体序列化并将序列化后的结果直接作为请求体发送出去
* 如果被body注解修饰的参数的类型是RequestBody对象那调用者可以不添加数据转换器内部会使用默认的数据转换器
* 如果被body注解修饰的参数的类型不是RequestBody对象是一个具体的实体类那调用者需要自定义一个类并且继承{@link Converter.Factory}
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parseBody(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
if (this.isFormEncoded || this.isMultipart) throw parameterError(this.method, p,
"@Body parameters cannot be used with form or multi-part encoding.");
if (this.gotBody) throw parameterError(this.method, p, "Multiple @Body method annotations found.");
Converter<?, RequestBody> converter;
try {
converter = this.jianJia.requestBodyConverter(type, annotations, this.methodAnnotations);
} catch (RuntimeException e) {
throw parameterError(this.method, e, p, "Unable to create @Body converter for %s", type);
}
this.gotBody = true;
return new ParameterHandler.Body<>(this.method, p, converter);
}
/**
* 解析{@link FieldMap}注解{@link FieldMap}注解用于map的形式发送一个表单请求
* 如果被{@link FieldMap}注解修饰的参数不是{@link Map}类型就会抛异常
* 如果{@link Map}的键值对为空也会抛异常
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parseFieldMap(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
if (!this.isFormEncoded) throw parameterError(this.method, p,
"@FieldMap parameters can only be used with form encoding.");
Class<?> rawParameterType = Utils.getRawType(type);
if (!Map.class.isAssignableFrom(rawParameterType))
throw parameterError(this.method, p, "@FieldMap parameter type must be Map.");
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
if (!(mapType instanceof ParameterizedType)) throw parameterError(this.method, p,
"Map must include generic types (e.g., Map<String, String>)");
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType)
throw parameterError(this.method, p, "@FieldMap keys must be of type String: " + keyType);
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
Converter<?, String> valueConverter =
this.jianJia.stringConverter(valueType, annotations);
this.gotField = true;
return new ParameterHandler.FieldMap<>(this.method, p,
valueConverter, ((FieldMap) annotation).encoded());
}
/**
* 解析{@link Field}注解{@link Field}注解用于发送一个表单请求
* {@link Field}注解修饰的参数类型可以是数组集合字符串等
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parseField(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
// Field注解必须与FormUrlEncoded一起使用
if (!this.isFormEncoded)
throw parameterError(this.method, p, "@Field parameters can only be used with form encoding.");
Field field = (Field) annotation;
String name = field.value();
boolean encoded = field.encoded();
Class<?> rawParameterType = Utils.getRawType(type);
this.gotField = true;
if (Iterable.class.isAssignableFrom(rawParameterType)) {
// rawParameterType实现了Iterable接口比如ArrayList就实现了Iterable接口
// 方法的参数类型没有泛型
if (!(type instanceof ParameterizedType))
throw parameterError(this.method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
ParameterizedType parameterizedType = (ParameterizedType) type;
// 获取参数类型的泛型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter<?, String> converter = this.jianJia.stringConverter(iterableType, annotations);
return new ParameterHandler.Field<>(name, converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
// 方法的参数类型是数组
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter<?, String> converter = this.jianJia.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Field<>(name, converter, encoded).array();
} else {
// 方法的参数类型不是集合也不是数组
Converter<?, String> converter = this.jianJia.stringConverter(rawParameterType, annotations);
return new ParameterHandler.Field<>(name, converter, encoded);
}
}
/**
* Parse header map parameter handler.
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return the parameter handler
*/
private ParameterHandler<?> parseHeaderMap(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
Class<?> rawParameterType = Utils.getRawType(type);
if (!Map.class.isAssignableFrom(rawParameterType))
throw parameterError(this.method, p, "@HeaderMap parameter type must be Map.");
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
// map没有泛型
if (!(mapType instanceof ParameterizedType)) throw parameterError(this.method, p,
"Map must include generic types (e.g., Map<String, String>)");
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType)
throw parameterError(this.method, p, "@HeaderMap keys must be of type String: " + keyType);
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
Converter<?, String> converter = this.jianJia.stringConverter(valueType, annotations);
return new ParameterHandler.HeaderMap<>(this.method, p, converter);
}
/**
* 解析{@link Header}注解{@link Header}注解用于添加请求头
* {@link Header}注解修饰的参数类型可以是数组集合字符串等
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parseHeader(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
Header header = (Header) annotation;
String name = header.value();
Class<?> rawParameterType = Utils.getRawType(type);
if (Iterable.class.isAssignableFrom(rawParameterType)) {
// rawParameterType实现了Iterable接口比如ArrayList就实现了Iterable接口
// 方法的参数类型没有泛型
if (!(type instanceof ParameterizedType))
throw parameterError(this.method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
ParameterizedType parameterizedType = (ParameterizedType) type;
// 获取参数类型的泛型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter<?, String> converter = this.jianJia.stringConverter(iterableType, annotations);
return new ParameterHandler.Header<>(name, converter).iterable();
} else if (rawParameterType.isArray()) {
// 方法的参数类型是数组
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter<?, String> converter = this.jianJia.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Header<>(name, converter).array();
} else {
// 方法的参数类型不是集合也不是数组
Converter<?, String> converter = this.jianJia.stringConverter(rawParameterType, annotations);
return new ParameterHandler.Header<>(name, converter);
}
}
/**
* 解析{@link QueryMap}注解{@link QueryMap}注解以{@link Map}的形式添加查询参数
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parseQueryMap(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
Class<?> rawParameterType = Utils.getRawType(type);
this.gotQueryMap = true;
if (!Map.class.isAssignableFrom(rawParameterType))
throw parameterError(this.method, p, "@QueryMap parameter type must be Map.");
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
// map没有泛型
if (!(mapType instanceof ParameterizedType)) throw parameterError(this.method, p,
"Map must include generic types (e.g., Map<String, String>)");
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType)
throw parameterError(this.method, p, "@QueryMap keys must be of type String: " + keyType);
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
Converter<?, String> converter = this.jianJia.stringConverter(valueType, annotations);
return new ParameterHandler.QueryMap<>(this.method, p, converter, ((QueryMap) annotation).encoded());
}
/**
* 解析{@link Query}注解{@link Query}注解用于给get请求添加请求参数
* {@link Query}注解修饰的参数类型可以是数组集合字符串等
*
* @param p the p
* @param type 方法参数的类型
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parseQuery(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
Query query = (Query) annotation;
String name = query.value();
boolean encoded = query.encoded();
Class<?> rawParameterType = Utils.getRawType(type);
this.gotQuery = true;
if (Iterable.class.isAssignableFrom(rawParameterType)) {
// rawParameterType实现了Iterable接口比如ArrayList就实现了Iterable接口
// 方法的参数类型没有泛型
if (!(type instanceof ParameterizedType))
throw parameterError(this.method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
ParameterizedType parameterizedType = (ParameterizedType) type;
// 获取参数类型的泛型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter<?, String> converter = this.jianJia.stringConverter(iterableType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
// 方法的参数类型是数组
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter<?, String> converter = this.jianJia.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).array();
} else {
// 方法的参数类型不是集合也不是数组
Converter<?, String> converter = this.jianJia.stringConverter(rawParameterType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded);
}
}
/**
* 解析{@link Path}注解{@link Path}注解在URL路径段中替换指定的参数值
*
* @param p the p
* @param type 方法参数的类型
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parsePath(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
if (this.gotQuery) throw parameterError(this.method, p, "A @Path parameter must not come after a @Query.");
if (this.gotQueryName)
throw parameterError(this.method, p, "A @Path parameter must not come after a @QueryName.");
if (this.gotQueryMap)
throw parameterError(this.method, p, "A @Path parameter must not come after a @QueryMap.");
if (this.gotUrl) throw parameterError(this.method, p, "@Path parameters may not be used with @Url.");
if (this.relativeUrl == null)
throw parameterError(this.method, p, "@Path can only be used with relative url on @%s",
this.httpMethod);
this.gotPart = true;
Path path = (Path) annotation;
String name = path.value();
this.validatePathName(p, name);
Converter<?, String> converter = this.jianJia.stringConverter(type, annotations);
return new ParameterHandler.Path<>(this.method, p, name, converter, path.encoded());
}
/**
* 解析{@link Url}注解{@link Url}注解用于添加请求的接口地址
* {@link Url}注解修饰的参数类型可以是HttpUrlStringURIohos.utils.net.Uri等
*
* @param p the p
* @param type the type
* @param annotations the annotations
* @param annotation the annotation
* @return parameter handler
*/
private ParameterHandler<?> parseUrl(int p, Type type, Annotation[] annotations, Annotation annotation) {
this.validateResolvableType(p, type);
if (this.gotUrl) throw parameterError(this.method, p, "Multiple @Url method annotations found.");
if (this.gotPath) throw parameterError(this.method, p, "@Path parameters may not be used with @Url.");
if (this.gotQuery) throw parameterError(this.method, p, "A @Url parameter must not come after a @Query.");
if (this.gotQueryName)
throw parameterError(this.method, p, "A @Url parameter must not come after a @QueryName.");
if (this.gotQueryMap)
throw parameterError(this.method, p, "A @Url parameter must not come after a @QueryMap.");
if (this.relativeUrl != null)
throw parameterError(this.method, p, "@Url cannot be used with @%s URL", this.httpMethod);
this.gotUrl = true;
if (type == HttpUrl.class
|| type == String.class
|| type == URI.class
|| (type instanceof Class && "ohos.utils.net.Uri".equals(((Class<?>) type).getName())))
return new ParameterHandler.RelativeUrl(this.method, p);
else throw parameterError(this.method, p,
"@Url must be okhttp3.HttpUrl, String, java.net.URI, or ohos.utils.net.Uri type.");
}
/**
* Validate path name.
*
* @param p the p
* @param name the name
*/
private void validatePathName(int p, String name) {
if (!PARAM_NAME_REGEX.matcher(name).matches())
throw parameterError(this.method, p, "@Path parameter name must match %s. Found: %s",
PARAM_URL_REGEX.pattern(), name);
// 验证URL路径中是否确实存在URL替换名称
if (!this.relativeUrlParamNames.contains(name))
throw parameterError(this.method, p, "URL \"%s\" does not contain \"{%s}\".", this.relativeUrl, name);
}
/**
* Validate resolvable type.
*
* @param p the p
* @param type the type
*/
private void validateResolvableType(int p, Type type) {
if (Utils.hasUnresolvableType(type)) throw parameterError(this.method, p,
"Parameter type must not include a type variable or wildcard: %s", type);
}
/**
* 解析方法上的注解
*
* @param annotation 注解
*/
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE)
this.parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
else if (annotation instanceof GET) this.parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
else if (annotation instanceof HEAD)
this.parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
else if (annotation instanceof PATCH)
this.parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
else if (annotation instanceof POST)
this.parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
else if (annotation instanceof PUT) this.parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
else if (annotation instanceof OPTIONS)
this.parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
else if (annotation instanceof BaseUrl) this.parseBaseUrl(((BaseUrl) annotation).value());
else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
this.parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof com.net.jianjia.http.Headers) {
String[] headersToParse = ((com.net.jianjia.http.Headers) annotation).value();
if (headersToParse.length == 0) throw methodError(this.method, "@Headers annotation is empty.");
this.headers = this.parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (this.isFormEncoded) throw methodError(this.method, "Only one encoding annotation is allowed.");
this.isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (this.isMultipart) throw methodError(this.method, "Only one encoding annotation is allowed.");
this.isFormEncoded = true;
}
}
/**
* Parse base url.
*
* @param value the value
*/
private void parseBaseUrl(String value) {
HttpUrl baseUrl = HttpUrl.get(value);
Utils.checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1)))
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
this.newBaseUrl = baseUrl;
}
/**
* 解析请求头
*
* @param headers the headers
* @return headers headers
* @Headers("Cache-Control: max -age=640000")
* @Headers({ "X-Foo: Bar", "X-Ping: Pong" })
*/
private Headers parseHeaders(String[] headers) {
Headers.Builder builder = new Headers.Builder();
for (String header : headers) {
// 查找冒号的位置
int colon = header.indexOf(":");
if (colon == -1 || colon == 0 || colon == header.length() - 1) throw methodError(this.method,
"@Headers value must be in the form \"Name: Value\". Found: \"%s\"", header);
String headerName = header.substring(0, colon);
String headerValue = header.substring(colon + 1).trim();
if ("Content-Type".equalsIgnoreCase(headerName)) try {
this.contentType = MediaType.get(headerValue);
} catch (IllegalArgumentException e) {
throw methodError(this.method, e, "Malformed content type: %s", headerValue);
}
else builder.add(headerName, headerValue);
}
return builder.build();
}
/**
* 解析请求方法和路径
*
* @param httpMethod 请求方法
* @param value 路径
* @param hasBody 是否有请求头
*/
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null)
throw methodError(this.method, "Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) return;
// 不支持这种格式users?sortby={sortby}
int question = value.indexOf("?");
if (question != -1 && question < value.length() - 1) {
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find())
throw methodError(this.method, "URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
}
}

View File

@ -0,0 +1,210 @@
package com.net.jianjia;
import okhttp3.Headers;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.ResponseBody;
/**
* The type Response.
*
* @param <T> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public class Response<T> {
/**
* The Raw response.
*/
private final okhttp3.Response rawResponse;
/**
* The Body.
*/
private final T body;
/**
* The Error body.
*/
private final ResponseBody errorBody;
/**
* Instantiates a new Response.
*
* @param rawResponse the raw response
* @param body the body
* @param errorBody the error body
*/
private Response(okhttp3.Response rawResponse, T body, ResponseBody errorBody) {
this.rawResponse = rawResponse;
this.body = body;
this.errorBody = errorBody;
}
/**
* Success response.
*
* @param <T> the type parameter
* @param body the body
* @return the response
*/
public static <T> Response<T> success(T body) {
return success(body, new okhttp3.Response.Builder() //
.code(200)
.message("OK")
.protocol(Protocol.HTTP_1_1)
.request(new Request.Builder().url("http://localhost/").build())
.build());
}
/**
* Success response.
*
* @param <T> the type parameter
* @param body the body
* @param rawResponse the raw response
* @return the response
*/
static <T> Response<T> success(T body, okhttp3.Response rawResponse) {
Utils.checkNotNull(rawResponse, "rawResponse == null");
if (!rawResponse.isSuccessful()) throw new IllegalArgumentException("rawResponse must be successful response");
return new Response<>(rawResponse, body, null);
}
/**
* Success response.
*
* @param <T> the type parameter
* @param body the body
* @param headers the headers
* @return the response
*/
public static <T> Response<T> success(T body, Headers headers) {
Utils.checkNotNull(headers, "headers == null");
return success(body, new okhttp3.Response.Builder() //
.code(200)
.message("OK")
.protocol(Protocol.HTTP_1_1)
.headers(headers)
.request(new Request.Builder().url("http://localhost/").build())
.build());
}
/**
* Error response.
*
* @param <T> the type parameter
* @param code the code
* @param body the body
* @return the response
*/
public static <T> Response<T> error(int code, ResponseBody body) {
if (code < 400) throw new IllegalArgumentException("code < 400: " + code);
return error(body, new okhttp3.Response.Builder() //
.code(code)
.message("Response.error()")
.protocol(Protocol.HTTP_1_1)
.request(new Request.Builder().url("http://localhost/").build())
.build());
}
/**
* Error response.
*
* @param <T> the type parameter
* @param body the body
* @param rawResponse the raw response
* @return the response
*/
public static <T> Response<T> error(ResponseBody body, okhttp3.Response rawResponse) {
Utils.checkNotNull(body, "body == null");
Utils.checkNotNull(rawResponse, "rawResponse == null");
if (rawResponse.isSuccessful())
throw new IllegalArgumentException("rawResponse should not be successful response");
return new Response<>(rawResponse, null, body);
}
/**
* Raw okhttp 3 . response.
*
* @return the okhttp 3 . response
*/
public okhttp3.Response raw() {
return this.rawResponse;
}
/**
* Code int.
*
* @return the int
*/
public int code() {
return this.rawResponse.code();
}
/**
* Is successful boolean.
*
* @return the boolean
*/
public boolean isSuccessful() {
return this.rawResponse.isSuccessful();
}
/**
* Message string.
*
* @return the string
*/
public String message() {
return this.rawResponse.message();
}
/**
* Header string.
*
* @param name the name
* @return the string
*/
public String header(String name) {
return this.rawResponse.header(name);
}
/**
* Header string.
*
* @param name the name
* @param defaultValue the default value
* @return the string
*/
public String header(String name, String defaultValue) {
return this.rawResponse.header(name, defaultValue);
}
/**
* Body t.
*
* @return the t
*/
public T body() {
return this.body;
}
/**
* Error body response body.
*
* @return the response body
*/
public ResponseBody errorBody() {
return this.errorBody;
}
/**
* To string string.
*
* @return the string
*/
@Override
public String toString() {
return this.rawResponse.toString();
}
}

View File

@ -0,0 +1,43 @@
package com.net.jianjia;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/**
* The type Service method.
*
* @param <T> the type parameter
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
abstract class ServiceMethod<T> {
/**
* 解析注解
*
* @param <T> the type parameter
* @param jianJia the jian jia
* @param method the method
* @return service method
*/
static <T> ServiceMethod<T> parseAnnotations(JianJia jianJia, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(jianJia, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw Utils.methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw Utils.methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(jianJia, method, requestFactory);
}
/**
* Invoke t.
*
* @param args the args
* @return the t
*/
public abstract T invoke(Object[] args);
}

View File

@ -0,0 +1,708 @@
package com.net.jianjia;
import okhttp3.ResponseBody;
import okio.Buffer;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.NoSuchElementException;
/**
* The type Utils.
*
* @modify&fix 田梓萱
* @date 2022 /2/17
*/
public class Utils {
/**
* The Empty type array.
*/
static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
/**
* Check not null t.
*
* @param <T> the type parameter
* @param object the object
* @param message the message
* @return the t
*/
static <T> T checkNotNull(T object, String message) {
if (object == null) throw new NullPointerException(message);
return object;
}
/**
* Check not primitive.
*
* @param type the type
*/
static void checkNotPrimitive(Type type) {
if (type instanceof Class<?> && ((Class<?>) type).isPrimitive()) throw new IllegalArgumentException();
}
/**
* Validate service interface.
*
* @param <T> the type parameter
* @param service the service
*/
static <T> void validateServiceInterface(Class<T> service) {
// 必须是接口Java内置的动态代理只能代理接口
if (!service.isInterface()) throw new IllegalArgumentException("API declarations must be interfaces.");
// 接口不能继承其它接口
if (service.getInterfaces().length > 0)
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
/**
* Method error runtime exception.
*
* @param method the method
* @param message the message
* @param args the args
* @return the runtime exception
*/
static RuntimeException methodError(Method method, String message, Object... args) {
return methodError(method, null, message, args);
}
/**
* Method error runtime exception.
*
* @param method the method
* @param cause the cause
* @param message the message
* @param args the args
* @return the runtime exception
*/
static RuntimeException methodError(Method method, Throwable cause, String message,
Object... args) {
message = String.format(message, args);
return new IllegalArgumentException(message
+ "\n for method "
+ method.getDeclaringClass().getSimpleName()
+ "."
+ method.getName(), cause);
}
/**
* Has unresolvable type boolean.
*
* @param type the type
* @return the boolean
*/
static boolean hasUnresolvableType(Type type) {
if (type instanceof Class<?>) return false;
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
for (Type typeArgument : parameterizedType.getActualTypeArguments())
if (hasUnresolvableType(typeArgument)) return true;
return false;
}
if (type instanceof GenericArrayType)
return hasUnresolvableType(((GenericArrayType) type).getGenericComponentType());
if (type instanceof TypeVariable) return true;
if (type instanceof WildcardType) return true;
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + className);
}
/**
* Parameter error runtime exception.
*
* @param method the method
* @param cause the cause
* @param p the p
* @param message the message
* @param args the args
* @return the runtime exception
*/
static RuntimeException parameterError(Method method,
Throwable cause, int p, String message, Object... args) {
return methodError(method, cause, message + " (parameter #" + (p + 1) + ")", args);
}
/**
* Parameter error runtime exception.
*
* @param method the method
* @param p the p
* @param message the message
* @param args the args
* @return the runtime exception
*/
static RuntimeException parameterError(Method method, int p, String message, Object... args) {
return methodError(method, message + " (parameter #" + (p + 1) + ")", args);
}
/**
* Gets raw type.
*
* @param type the type
* @return the raw type
*/
static Class<?> getRawType(Type type) {
checkNotNull(type, "type == null");
// Type is a normal class.
if (type instanceof Class<?>) return (Class<?>) type;
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
// suspects some pathological case related to nested classes exists.
Type rawType = parameterizedType.getRawType();
if (!(rawType instanceof Class)) throw new IllegalArgumentException();
return (Class<?>) rawType;
}
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
}
// We could use the variable's bounds, but that won't work if there are multiple. Having a raw
// type that's more general than necessary is okay.
if (type instanceof TypeVariable) return Object.class;
if (type instanceof WildcardType) return getRawType(((WildcardType) type).getUpperBounds()[0]);
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
}
/**
* Gets parameter upper bound.
*
* @param index the index
* @param type the type
* @return the parameter upper bound
*/
static Type getParameterUpperBound(int index, ParameterizedType type) {
Type[] types = type.getActualTypeArguments();
if (index < 0 || index >= types.length) throw new IllegalArgumentException(
"Index " + index + " not in range [0," + types.length + ") for " + type);
Type paramType = types[index];
if (paramType instanceof WildcardType) return ((WildcardType) paramType).getUpperBounds()[0];
return paramType;
}
/**
* Equals boolean.
*
* @param a the a
* @param b the b
* @return the boolean
*/
static boolean equals(Type a, Type b) {
if (a == b) return true; // Also handles (a == null && b == null).
else if (a instanceof Class) return a.equals(b); // Class already specifies equals().
else if (a instanceof ParameterizedType) {
if (!(b instanceof ParameterizedType)) return false;
ParameterizedType pa = (ParameterizedType) a;
ParameterizedType pb = (ParameterizedType) b;
Object ownerA = pa.getOwnerType();
Object ownerB = pb.getOwnerType();
return (ownerA == ownerB || (ownerA != null && ownerA.equals(ownerB)))
&& pa.getRawType().equals(pb.getRawType())
&& Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments());
} else if (a instanceof GenericArrayType) {
if (!(b instanceof GenericArrayType)) return false;
GenericArrayType ga = (GenericArrayType) a;
GenericArrayType gb = (GenericArrayType) b;
return equals(ga.getGenericComponentType(), gb.getGenericComponentType());
} else if (a instanceof WildcardType) {
if (!(b instanceof WildcardType)) return false;
WildcardType wa = (WildcardType) a;
WildcardType wb = (WildcardType) b;
return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())
&& Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds());
} else if (a instanceof TypeVariable) {
if (!(b instanceof TypeVariable)) return false;
TypeVariable<?> va = (TypeVariable<?>) a;
TypeVariable<?> vb = (TypeVariable<?>) b;
return va.getGenericDeclaration() == vb.getGenericDeclaration()
&& va.getName().equals(vb.getName());
} else return false; // This isn't a type we support!
}
/**
* Is annotation present boolean.
*
* @param annotations the annotations
* @param cls the cls
* @return the boolean
*/
static boolean isAnnotationPresent(Annotation[] annotations,
Class<? extends Annotation> cls) {
for (Annotation annotation : annotations) if (cls.isInstance(annotation)) return true;
return false;
}
/**
* Buffer response body.
*
* @param body the body
* @return the response body
* @throws IOException the io exception
*/
static ResponseBody buffer(ResponseBody body) throws IOException {
Buffer buffer = new Buffer();
body.source().readAll(buffer);
return ResponseBody.create(body.contentType(), body.contentLength(), buffer);
}
/**
* Type to string string.
*
* @param type the type
* @return the string
*/
static String typeToString(Type type) {
return type instanceof Class ? ((Class<?>) type).getName() : type.toString();
}
/**
* Resolve type variable type.
*
* @param context the context
* @param contextRawType the context raw type
* @param unknown the unknown
* @return the type
*/
private static Type resolveTypeVariable(
Type context, Class<?> contextRawType, TypeVariable<?> unknown) {
Class<?> declaredByRaw = declaringClassOf(unknown);
// We can't reduce this further.
if (declaredByRaw == null) return unknown;
Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw);
if (declaredBy instanceof ParameterizedType) {
int index = indexOf(declaredByRaw.getTypeParameters(), unknown);
return ((ParameterizedType) declaredBy).getActualTypeArguments()[index];
}
return unknown;
}
/**
* Index of int.
*
* @param array the array
* @param toFind the to find
* @return the int
*/
private static int indexOf(Object[] array, Object toFind) {
for (int i = 0; i < array.length; i++) if (toFind.equals(array[i])) return i;
throw new NoSuchElementException();
}
/**
* Declaring class of class.
*
* @param typeVariable the type variable
* @return the class
*/
private static Class<?> declaringClassOf(TypeVariable<?> typeVariable) {
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
return genericDeclaration instanceof Class ? (Class<?>) genericDeclaration : null;
}
/**
* Gets supertype.
*
* @param context the context
* @param contextRawType the context raw type
* @param supertype the supertype
* @return the supertype
*/
static Type getSupertype(Type context, Class<?> contextRawType, Class<?> supertype) {
if (!supertype.isAssignableFrom(contextRawType)) throw new IllegalArgumentException();
return resolve(context, contextRawType,
getGenericSupertype(context, contextRawType, supertype));
}
/**
* Resolve type.
*
* @param context the context
* @param contextRawType the context raw type
* @param toResolve the to resolve
* @return the type
*/
private static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
// This implementation is made a little more complicated in an attempt to avoid object-creation.
while (true) if (toResolve instanceof TypeVariable) {
TypeVariable<?> typeVariable = (TypeVariable<?>) toResolve;
toResolve = resolveTypeVariable(context, contextRawType, typeVariable);
if (toResolve == typeVariable) return toResolve;
} else if (toResolve instanceof Class && ((Class<?>) toResolve).isArray()) {
Class<?> original = (Class<?>) toResolve;
Type componentType = original.getComponentType();
Type newComponentType = resolve(context, contextRawType, componentType);
return componentType == newComponentType ? original : new GenericArrayTypeImpl(
newComponentType);
} else if (toResolve instanceof GenericArrayType) {
GenericArrayType original = (GenericArrayType) toResolve;
Type componentType = original.getGenericComponentType();
Type newComponentType = resolve(context, contextRawType, componentType);
return componentType == newComponentType ? original : new GenericArrayTypeImpl(
newComponentType);
} else if (toResolve instanceof ParameterizedType) {
ParameterizedType original = (ParameterizedType) toResolve;
Type ownerType = original.getOwnerType();
Type newOwnerType = resolve(context, contextRawType, ownerType);
boolean changed = newOwnerType != ownerType;
Type[] args = original.getActualTypeArguments();
for (int t = 0, length = args.length; t < length; t++) {
Type resolvedTypeArgument = resolve(context, contextRawType, args[t]);
if (resolvedTypeArgument != args[t]) {
if (!changed) {
args = args.clone();
changed = true;
}
args[t] = resolvedTypeArgument;
}
}
return changed
? new ParameterizedTypeImpl(newOwnerType, original.getRawType(), args)
: original;
} else if (toResolve instanceof WildcardType) {
WildcardType original = (WildcardType) toResolve;
Type[] originalLowerBound = original.getLowerBounds();
Type[] originalUpperBound = original.getUpperBounds();
if (originalLowerBound.length == 1) {
Type lowerBound = resolve(context, contextRawType, originalLowerBound[0]);
if (lowerBound != originalLowerBound[0])
return new WildcardTypeImpl(new Type[]{Object.class}, new Type[]{lowerBound});
} else if (originalUpperBound.length == 1) {
Type upperBound = resolve(context, contextRawType, originalUpperBound[0]);
if (upperBound != originalUpperBound[0])
return new WildcardTypeImpl(new Type[]{upperBound}, EMPTY_TYPE_ARRAY);
}
return original;
} else return toResolve;
}
/**
* Gets generic supertype.
*
* @param context the context
* @param rawType the raw type
* @param toResolve the to resolve
* @return the generic supertype
*/
private static Type getGenericSupertype(Type context, Class<?> rawType, Class<?> toResolve) {
if (toResolve == rawType) return context;
// We skip searching through interfaces if unknown is an interface.
if (toResolve.isInterface()) {
Class<?>[] interfaces = rawType.getInterfaces();
for (int i = 0, length = interfaces.length; i < length; i++)
if (interfaces[i] == toResolve) return rawType.getGenericInterfaces()[i];
else if (toResolve.isAssignableFrom(interfaces[i]))
return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);
}
// Check our supertypes.
if (!rawType.isInterface()) while (rawType != Object.class) {
Class<?> rawSupertype = rawType.getSuperclass();
if (rawSupertype == toResolve) return rawType.getGenericSuperclass();
else if (toResolve.isAssignableFrom(rawSupertype))
return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);
rawType = rawSupertype;
}
// We can't resolve this further.
return toResolve;
}
/**
* Throw if fatal.
*
* @param t the t
*/
static void throwIfFatal(Throwable t) {
if (t instanceof VirtualMachineError) throw (VirtualMachineError) t;
else if (t instanceof ThreadDeath) throw (ThreadDeath) t;
else if (t instanceof LinkageError) throw (LinkageError) t;
}
/**
* The type Parameterized type.
*/
static final class ParameterizedTypeImpl implements ParameterizedType {
/**
* The Owner type.
*/
private final Type ownerType;
/**
* The Raw type.
*/
private final Type rawType;
/**
* The Type arguments.
*/
private final Type[] typeArguments;
/**
* Instantiates a new Parameterized type.
*
* @param ownerType the owner type
* @param rawType the raw type
* @param typeArguments the type arguments
*/
ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) {
// Require an owner type if the raw type needs it.
if (rawType instanceof Class<?>
&& (ownerType == null) != (((Class<?>) rawType).getEnclosingClass() == null))
throw new IllegalArgumentException();
for (Type typeArgument : typeArguments) {
Utils.checkNotNull(typeArgument, "typeArgument == null");
Utils.checkNotPrimitive(typeArgument);
}
this.ownerType = ownerType;
this.rawType = rawType;
this.typeArguments = typeArguments.clone();
}
/**
* Get actual type arguments type [ ].
*
* @return the type [ ]
*/
@Override
public Type[] getActualTypeArguments() {
return this.typeArguments.clone();
}
/**
* Gets raw type.
*
* @return the raw type
*/
@Override
public Type getRawType() {
return this.rawType;
}
/**
* Gets owner type.
*
* @return the owner type
*/
@Override
public Type getOwnerType() {
return this.ownerType;
}
/**
* Equals boolean.
*
* @param other the other
* @return the boolean
*/
@Override
public boolean equals(Object other) {
return other instanceof ParameterizedType && Utils.equals(this, (ParameterizedType) other);
}
/**
* Hash code int.
*
* @return the int
*/
@Override
public int hashCode() {
return Arrays.hashCode(this.typeArguments)
^ this.rawType.hashCode()
^ (this.ownerType != null ? this.ownerType.hashCode() : 0);
}
/**
* To string string.
*
* @return the string
*/
@Override
public String toString() {
if (this.typeArguments.length == 0) return Utils.typeToString(this.rawType);
StringBuilder result = new StringBuilder(30 * (this.typeArguments.length + 1));
result.append(Utils.typeToString(this.rawType));
result.append("<").append(Utils.typeToString(this.typeArguments[0]));
for (int i = 1; i < this.typeArguments.length; i++)
result.append(", ").append(Utils.typeToString(this.typeArguments[i]));
return result.append(">").toString();
}
}
/**
* The type Generic array type.
*/
private static final class GenericArrayTypeImpl implements GenericArrayType {
/**
* The Component type.
*/
private final Type componentType;
/**
* Instantiates a new Generic array type.
*
* @param componentType the component type
*/
GenericArrayTypeImpl(Type componentType) {
this.componentType = componentType;
}
/**
* Gets generic component type.
*
* @return the generic component type
*/
@Override
public Type getGenericComponentType() {
return this.componentType;
}
/**
* Equals boolean.
*
* @param o the o
* @return the boolean
*/
@Override
public boolean equals(Object o) {
return o instanceof GenericArrayType
&& Utils.equals(this, (GenericArrayType) o);
}
/**
* Hash code int.
*
* @return the int
*/
@Override
public int hashCode() {
return this.componentType.hashCode();
}
/**
* To string string.
*
* @return the string
*/
@Override
public String toString() {
return Utils.typeToString(this.componentType) + "[]";
}
}
/**
* The type Wildcard type.
*/
private static final class WildcardTypeImpl implements WildcardType {
/**
* The Upper bound.
*/
private final Type upperBound;
/**
* The Lower bound.
*/
private final Type lowerBound;
/**
* Instantiates a new Wildcard type.
*
* @param upperBounds the upper bounds
* @param lowerBounds the lower bounds
*/
WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
if (lowerBounds.length > 1) throw new IllegalArgumentException();
if (upperBounds.length != 1) throw new IllegalArgumentException();
if (lowerBounds.length == 1) {
if (lowerBounds[0] == null) throw new NullPointerException();
Utils.checkNotPrimitive(lowerBounds[0]);
if (upperBounds[0] != Object.class) throw new IllegalArgumentException();
this.lowerBound = lowerBounds[0];
this.upperBound = Object.class;
} else {
if (upperBounds[0] == null) throw new NullPointerException();
Utils.checkNotPrimitive(upperBounds[0]);
this.lowerBound = null;
this.upperBound = upperBounds[0];
}
}
/**
* Get upper bounds type [ ].
*
* @return the type [ ]
*/
@Override
public Type[] getUpperBounds() {
return new Type[]{this.upperBound};
}
/**
* Get lower bounds type [ ].
*
* @return the type [ ]
*/
@Override
public Type[] getLowerBounds() {
return this.lowerBound != null ? new Type[]{this.lowerBound} : Utils.EMPTY_TYPE_ARRAY;
}
/**
* Equals boolean.
*
* @param other the other
* @return the boolean
*/
@Override
public boolean equals(Object other) {
return other instanceof WildcardType && Utils.equals(this, (WildcardType) other);
}
/**
* Hash code int.
*
* @return the int
*/
@Override
public int hashCode() {
// This equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds()).
return (this.lowerBound != null ? 31 + this.lowerBound.hashCode() : 1) ^ (31 + this.upperBound.hashCode());
}
/**
* To string string.
*
* @return the string
*/
@Override
public String toString() {
if (this.lowerBound != null) return "? super " + Utils.typeToString(this.lowerBound);
if (this.upperBound == Object.class) return "?";
return "? extends " + Utils.typeToString(this.upperBound);
}
}
}

View File

@ -0,0 +1,42 @@
package com.net.jianjia.conventer;
import com.net.jianjia.Converter;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import java.io.IOException;
/**
* The type Scalar request body converter.
*
* @param <T> the type parameter
*/
final class ScalarRequestBodyConverter<T> implements Converter<T, RequestBody> {
/**
* The Instance.
*/
static final ScalarRequestBodyConverter<Object> INSTANCE = new ScalarRequestBodyConverter<>();
/**
* The constant MEDIA_TYPE.
*/
private static final MediaType MEDIA_TYPE = MediaType.get("text/plain; charset=UTF-8");
/**
* Instantiates a new Scalar request body converter.
*/
private ScalarRequestBodyConverter() {
}
/**
* Convert request body.
*
* @param value the value
* @return the request body
* @throws IOException the io exception
*/
@Override
public RequestBody convert(T value) throws IOException {
return RequestBody.create(MEDIA_TYPE, String.valueOf(value));
}
}

View File

@ -0,0 +1,220 @@
package com.net.jianjia.conventer;
import com.net.jianjia.Converter;
import okhttp3.ResponseBody;
import java.io.IOException;
/**
* The type Scalar response body converters.
*/
final class ScalarResponseBodyConverters {
/**
* Instantiates a new Scalar response body converters.
*/
private ScalarResponseBodyConverters() {
}
/**
* The type String response body converter.
*/
static final class StringResponseBodyConverter implements Converter<ResponseBody, String> {
/**
* The Instance.
*/
static final StringResponseBodyConverter INSTANCE = new StringResponseBodyConverter();
/**
* Convert string.
*
* @param value the value
* @return the string
* @throws IOException the io exception
*/
@Override
public String convert(ResponseBody value) throws IOException {
return value.string();
}
}
/**
* The type Boolean response body converter.
*/
static final class BooleanResponseBodyConverter implements Converter<ResponseBody, Boolean> {
/**
* The Instance.
*/
static final BooleanResponseBodyConverter INSTANCE = new BooleanResponseBodyConverter();
/**
* Convert boolean.
*
* @param value the value
* @return the boolean
* @throws IOException the io exception
*/
@Override
public Boolean convert(ResponseBody value) throws IOException {
return Boolean.valueOf(value.string());
}
}
/**
* The type Byte response body converter.
*/
static final class ByteResponseBodyConverter implements Converter<ResponseBody, Byte> {
/**
* The Instance.
*/
static final ByteResponseBodyConverter INSTANCE = new ByteResponseBodyConverter();
/**
* Convert byte.
*
* @param value the value
* @return the byte
* @throws IOException the io exception
*/
@Override
public Byte convert(ResponseBody value) throws IOException {
return Byte.valueOf(value.string());
}
}
/**
* The type Character response body converter.
*/
static final class CharacterResponseBodyConverter implements Converter<ResponseBody, Character> {
/**
* The Instance.
*/
static final CharacterResponseBodyConverter INSTANCE = new CharacterResponseBodyConverter();
/**
* Convert character.
*
* @param value the value
* @return the character
* @throws IOException the io exception
*/
@Override
public Character convert(ResponseBody value) throws IOException {
String body = value.string();
if (body.length() != 1) {
throw new IOException(
"Expected body of length 1 for Character conversion but was " + body.length());
}
return body.charAt(0);
}
}
/**
* The type Double response body converter.
*/
static final class DoubleResponseBodyConverter implements Converter<ResponseBody, Double> {
/**
* The Instance.
*/
static final DoubleResponseBodyConverter INSTANCE = new DoubleResponseBodyConverter();
/**
* Convert double.
*
* @param value the value
* @return the double
* @throws IOException the io exception
*/
@Override
public Double convert(ResponseBody value) throws IOException {
return Double.valueOf(value.string());
}
}
/**
* The type Float response body converter.
*/
static final class FloatResponseBodyConverter implements Converter<ResponseBody, Float> {
/**
* The Instance.
*/
static final FloatResponseBodyConverter INSTANCE = new FloatResponseBodyConverter();
/**
* Convert float.
*
* @param value the value
* @return the float
* @throws IOException the io exception
*/
@Override
public Float convert(ResponseBody value) throws IOException {
return Float.valueOf(value.string());
}
}
/**
* The type Integer response body converter.
*/
static final class IntegerResponseBodyConverter implements Converter<ResponseBody, Integer> {
/**
* The Instance.
*/
static final IntegerResponseBodyConverter INSTANCE = new IntegerResponseBodyConverter();
/**
* Convert integer.
*
* @param value the value
* @return the integer
* @throws IOException the io exception
*/
@Override
public Integer convert(ResponseBody value) throws IOException {
return Integer.valueOf(value.string());
}
}
/**
* The type Long response body converter.
*/
static final class LongResponseBodyConverter implements Converter<ResponseBody, Long> {
/**
* The Instance.
*/
static final LongResponseBodyConverter INSTANCE = new LongResponseBodyConverter();
/**
* Convert long.
*
* @param value the value
* @return the long
* @throws IOException the io exception
*/
@Override
public Long convert(ResponseBody value) throws IOException {
return Long.valueOf(value.string());
}
}
/**
* The type Short response body converter.
*/
static final class ShortResponseBodyConverter implements Converter<ResponseBody, Short> {
/**
* The Instance.
*/
static final ShortResponseBodyConverter INSTANCE = new ShortResponseBodyConverter();
/**
* Convert short.
*
* @param value the value
* @return the short
* @throws IOException the io exception
*/
@Override
public Short convert(ResponseBody value) throws IOException {
return Short.valueOf(value.string());
}
}
}

View File

@ -0,0 +1,105 @@
package com.net.jianjia.conventer;
import com.net.jianjia.Converter;
import com.net.jianjia.JianJia;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* A {@linkplain Converter.Factory converter} for strings and both primitives and their boxed types
* to {@code text/plain} bodies.
*/
public final class ScalarsConverterFactory extends Converter.Factory {
/**
* Instantiates a new Scalars converter factory.
*/
private ScalarsConverterFactory() {
}
/**
* Create scalars converter factory.
*
* @return the scalars converter factory
*/
public static ScalarsConverterFactory create() {
return new ScalarsConverterFactory();
}
/**
* Request body converter converter.
*
* @param type the type
* @param parameterAnnotations the parameter annotations
* @param methodAnnotations the method annotations
* @param jianJia the jian jia
* @return the converter
*/
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, JianJia jianJia) {
if (type == String.class
|| type == boolean.class
|| type == Boolean.class
|| type == byte.class
|| type == Byte.class
|| type == char.class
|| type == Character.class
|| type == double.class
|| type == Double.class
|| type == float.class
|| type == Float.class
|| type == int.class
|| type == Integer.class
|| type == long.class
|| type == Long.class
|| type == short.class
|| type == Short.class) {
return ScalarRequestBodyConverter.INSTANCE;
}
return null;
}
/**
* Response body converter converter.
*
* @param type the type
* @param annotations the annotations
* @param jianJia the jian jia
* @return the converter
*/
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, JianJia jianJia) {
if (type == String.class) {
return ScalarResponseBodyConverters.StringResponseBodyConverter.INSTANCE;
}
if (type == Boolean.class || type == boolean.class) {
return ScalarResponseBodyConverters.BooleanResponseBodyConverter.INSTANCE;
}
if (type == Byte.class || type == byte.class) {
return ScalarResponseBodyConverters.ByteResponseBodyConverter.INSTANCE;
}
if (type == Character.class || type == char.class) {
return ScalarResponseBodyConverters.CharacterResponseBodyConverter.INSTANCE;
}
if (type == Double.class || type == double.class) {
return ScalarResponseBodyConverters.DoubleResponseBodyConverter.INSTANCE;
}
if (type == Float.class || type == float.class) {
return ScalarResponseBodyConverters.FloatResponseBodyConverter.INSTANCE;
}
if (type == Integer.class || type == int.class) {
return ScalarResponseBodyConverters.IntegerResponseBodyConverter.INSTANCE;
}
if (type == Long.class || type == long.class) {
return ScalarResponseBodyConverters.LongResponseBodyConverter.INSTANCE;
}
if (type == Short.class || type == short.class) {
return ScalarResponseBodyConverters.ShortResponseBodyConverter.INSTANCE;
}
return null;
}
}

View File

@ -0,0 +1,84 @@
package com.net.jianjia.gson;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.net.jianjia.Converter;
import com.net.jianjia.JianJia;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* The type Gson converter factory.
*
* @author 裴云飞
* @date 2021 /1/26
*/
public final class GsonConverterFactory extends Converter.Factory {
/**
* The Gson.
*/
private final Gson gson;
/**
* Instantiates a new Gson converter factory.
*
* @param gson the gson
*/
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
/**
* Create gson converter factory.
*
* @return the gson converter factory
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create gson converter factory.
*
* @param gson the gson
* @return the gson converter factory
*/
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
/**
* Request body converter converter.
*
* @param type the type
* @param parameterAnnotations the parameter annotations
* @param methodAnnotations the method annotations
* @param jianJia the jian jia
* @return the converter
*/
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, JianJia jianJia) {
TypeAdapter<?> adapter = this.gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(this.gson, adapter);
}
/**
* Response body converter converter.
*
* @param type the type
* @param annotations the annotations
* @param jianJia the jian jia
* @return the converter
*/
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, JianJia jianJia) {
TypeAdapter<?> adapter = this.gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(this.gson, adapter);
}
}

View File

@ -0,0 +1,71 @@
package com.net.jianjia.gson;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonWriter;
import com.net.jianjia.Converter;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* The type Gson request body converter.
*
* @param <T> the type parameter
* @author 裴云飞
* @date 2021 /1/26
*/
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
/**
* The constant MEDIA_TYPE.
*/
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
/**
* The constant UTF_8.
*/
private static final Charset UTF_8 = StandardCharsets.UTF_8;
/**
* The Gson.
*/
private final Gson gson;
/**
* The Adapter.
*/
private final TypeAdapter<T> adapter;
/**
* Instantiates a new Gson request body converter.
*
* @param gson the gson
* @param adapter the adapter
*/
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
/**
* Convert request body.
*
* @param value the value
* @return the request body
* @throws IOException the io exception
*/
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = this.gson.newJsonWriter(writer);
this.adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}

View File

@ -0,0 +1,62 @@
package com.net.jianjia.gson;
import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.net.jianjia.Converter;
import okhttp3.ResponseBody;
import java.io.IOException;
/**
* The type Gson response body converter.
*
* @param <T> the type parameter
* @author 裴云飞
* @date 2021 /1/26
*/
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
/**
* The Gson.
*/
private final Gson gson;
/**
* The Adapter.
*/
private final TypeAdapter<T> adapter;
/**
* Instantiates a new Gson response body converter.
*
* @param gson the gson
* @param adapter the adapter
*/
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
/**
* Convert t.
*
* @param value the value
* @return the t
* @throws IOException the io exception
*/
@Override
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}

View File

@ -0,0 +1,25 @@
package com.net.jianjia.http;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 动态更换接口域名一个应用的域名可能有多个如果接口的域名与默认指定的域名不相同
* 那就可以使用该注解在方法上指定接口的域名
*
* @author 裴云飞
* @date 2021 /1/24
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BaseUrl {
/**
* Value string.
*
* @return the string
*/
String value();
}

View File

@ -0,0 +1,17 @@
package com.net.jianjia.http;
import java.lang.annotation.*;
/**
* 当你发送一个post或put请求但是又不想作为请求参数或表单的方式发送请求时
* 使用该注解定义的参数可以直接传入一个实体类内部会把该实体序列化并将序列化后的结果直接作为请求体发送出去
*
* @author 裴云飞
* @date 2021 /1/26
*/
@Documented
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Body {
}

View File

@ -0,0 +1,23 @@
package com.net.jianjia.http;
import java.lang.annotation.*;
/**
* delete请求声明在方法上的注解在运行时有效
*
* @author 裴云飞
* @date 2021 /1/18
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DELETE {
/**
* DELETE注解一般必须添加相对路径或绝对路径或者全路径如果不想在DELETE注解后添加请求路径
* 则可以在方法的第一个参数中用{@link com.net.jianjia.http.Url @Url}注解添加请求路径
*
* @return string string
*/
String value() default "";
}

View File

@ -0,0 +1,34 @@
package com.net.jianjia.http;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 用于发送一个表单请求
*
* @author 裴云飞
* @date 2021 /1/18
*/
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Field {
/**
* Value string.
*
* @return the string
*/
String value();
/**
* Encoded boolean.
*
* @return the boolean
*/
boolean encoded() default false;
}

View File

@ -0,0 +1,22 @@
package com.net.jianjia.http;
import java.lang.annotation.*;
/**
* 以map的形式发送一个表单请求
*
* @author 裴云飞
* @date 2021 /1/25
*/
@Documented
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldMap {
/**
* Encoded boolean.
*
* @return the boolean
*/
boolean encoded() default false;
}

View File

@ -0,0 +1,20 @@
package com.net.jianjia.http;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 用于发送一个表单请求使用该注解必须在方法的参数添加{@link Field @Field}注解
*
* @author 裴云飞
* @date 2021 /1/18
*/
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface FormUrlEncoded {
}

View File

@ -0,0 +1,23 @@
package com.net.jianjia.http;
import java.lang.annotation.*;
/**
* get请求声明在方法上的注解在运行时有效
*
* @author 裴云飞
* @date 2021 /1/18
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GET {
/**
* GET注解一般必须添加相对路径或绝对路径或者全路径如果不想在GET注解后添加请求路径
* 则可以在方法的第一个参数中用{@link Url @Url}注解添加请求路径
*
* @return string string
*/
String value() default "";
}

View File

@ -0,0 +1,23 @@
package com.net.jianjia.http;
import java.lang.annotation.*;
/**
* head请求声明在方法上的注解在运行时有效
*
* @author 裴云飞
* @date 2021 /1/18
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HEAD {
/**
* HEAD注解一般必须添加相对路径或绝对路径或者全路径如果不想在HEAD注解后添加请求路径
* 则可以在方法的第一个参数中用{@link com.net.jianjia.http.Url @Url}注解添加请求路径
*
* @return string string
*/
String value() default "";
}

View File

@ -0,0 +1,50 @@
package com.net.jianjia.http;
import java.lang.annotation.*;
/**
* 用于发送一个自定义的HTTP请求声明在方法上的注解在运行时有效
* <pre><code>
* interface Service {
* &#064;HTTP(method = "CUSTOM", path = "custom/endpoint/")
* Call&lt;ResponseBody&gt; customEndpoint();
* }
* </code></pre>
* 发送一个{@code DELETE}请求
* <pre><code>
* interface Service {
* &#064;HTTP(method = "DELETE", path = "remove/", hasBody = true)
* Call&lt;ResponseBody&gt; deleteObject(@Body RequestBody object);
* }
* </code></pre>
*
* @author 裴云飞
* @date 2021 /1/18
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HTTP {
/**
* Method string.
*
* @return the string
*/
String method();
/**
* Has body boolean.
*
* @return the boolean
*/
boolean hasBody() default false;
/**
* PUT注解一般必须添加相对路径或绝对路径或者全路径如果不想在PUT注解后添加请求路径
* 则可以在方法的第一个参数中用{@link com.net.jianjia.http.Url @Url}注解添加请求路径
*
* @return string string
*/
String path() default "";
}

Some files were not shown because too many files have changed in this diff Show More