Browse Source

init

developer
lh 8 years ago
commit
73478f0b1f
88 changed files with 4378 additions and 0 deletions
  1. +9
    -0
      .gitignore
  2. +22
    -0
      .idea/compiler.xml
  3. +3
    -0
      .idea/copyright/profiles_settings.xml
  4. +19
    -0
      .idea/gradle.xml
  5. +46
    -0
      .idea/misc.xml
  6. +10
    -0
      .idea/modules.xml
  7. +12
    -0
      .idea/runConfigurations.xml
  8. +1
    -0
      app/.gitignore
  9. +43
    -0
      app/build.gradle
  10. +25
    -0
      app/proguard-rules.pro
  11. +26
    -0
      app/src/androidTest/java/com/qhclh/ytzh/ExampleInstrumentedTest.java
  12. +29
    -0
      app/src/main/AndroidManifest.xml
  13. +9
    -0
      app/src/main/assets/litepal.xml
  14. +99
    -0
      app/src/main/java/com/qhclh/ytzh/base/BaseActivity.java
  15. +31
    -0
      app/src/main/java/com/qhclh/ytzh/configs/ConfigBase.java
  16. +29
    -0
      app/src/main/java/com/qhclh/ytzh/configs/ConfigUtil.java
  17. +32
    -0
      app/src/main/java/com/qhclh/ytzh/configs/LastLoginInfo.java
  18. +31
    -0
      app/src/main/java/com/qhclh/ytzh/configs/LoginUserConfig.java
  19. +93
    -0
      app/src/main/java/com/qhclh/ytzh/configs/ServerConfig.java
  20. +43
    -0
      app/src/main/java/com/qhclh/ytzh/home/MainActivity.java
  21. +61
    -0
      app/src/main/java/com/qhclh/ytzh/home/MyApplication.java
  22. +11
    -0
      app/src/main/java/com/qhclh/ytzh/home/RpcUrl.java
  23. +7
    -0
      app/src/main/java/com/qhclh/ytzh/interfaces/OnPromptListener.java
  24. +66
    -0
      app/src/main/java/com/qhclh/ytzh/splash/SplashActivity.java
  25. +115
    -0
      app/src/main/java/com/qhclh/ytzh/tasks/CallableTask.java
  26. +39
    -0
      app/src/main/java/com/qhclh/ytzh/tasks/ViewOnClickTask.java
  27. +36
    -0
      app/src/main/java/com/qhclh/ytzh/utils/ActivityCollector.java
  28. +72
    -0
      app/src/main/java/com/qhclh/ytzh/utils/DateTimeUtil.java
  29. +189
    -0
      app/src/main/java/com/qhclh/ytzh/utils/DialogUtil.java
  30. +30
    -0
      app/src/main/java/com/qhclh/ytzh/utils/StringUtil.java
  31. +9
    -0
      app/src/main/res/anim/anim_in_left.xml
  32. +9
    -0
      app/src/main/res/anim/anim_in_right.xml
  33. +9
    -0
      app/src/main/res/anim/anim_out_left.xml
  34. +9
    -0
      app/src/main/res/anim/anim_out_right.xml
  35. BIN
      app/src/main/res/drawable-xhdpi/back.png
  36. +12
    -0
      app/src/main/res/layout/act_main.xml
  37. +9
    -0
      app/src/main/res/layout/act_splash.xml
  38. +6
    -0
      app/src/main/res/layout/include_line.xml
  39. +45
    -0
      app/src/main/res/layout/include_tab_bar.xml
  40. +17
    -0
      app/src/main/res/layout/include_tool_bar.xml
  41. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  42. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  43. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  44. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  45. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  46. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  47. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  48. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  49. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  50. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  51. +24
    -0
      app/src/main/res/values/colors.xml
  52. +174
    -0
      app/src/main/res/values/dimens.xml
  53. +3
    -0
      app/src/main/res/values/strings.xml
  54. +54
    -0
      app/src/main/res/values/styles.xml
  55. +17
    -0
      app/src/test/java/com/qhclh/ytzh/ExampleUnitTest.java
  56. +23
    -0
      build.gradle
  57. +17
    -0
      gradle.properties
  58. BIN
      gradle/wrapper/gradle-wrapper.jar
  59. +6
    -0
      gradle/wrapper/gradle-wrapper.properties
  60. +160
    -0
      gradlew
  61. +90
    -0
      gradlew.bat
  62. +1
    -0
      jsonrpc/.gitignore
  63. +27
    -0
      jsonrpc/build.gradle
  64. +17
    -0
      jsonrpc/proguard-rules.pro
  65. +13
    -0
      jsonrpc/src/androidTest/java/org/forks/jsonrpc/ApplicationTest.java
  66. +11
    -0
      jsonrpc/src/main/AndroidManifest.xml
  67. +38
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/DFDataTable.java
  68. +76
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/Helper.java
  69. +84
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/HttpJsonRpcClient.java
  70. +23
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/InvalidPropertyValueException.java
  71. +69
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/IterHelper.java
  72. +93
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcClient.java
  73. +51
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcException.java
  74. +179
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcResult.java
  75. +22
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcRuntimeException.java
  76. +199
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/ManyList.java
  77. +66
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/NamedValue.java
  78. +84
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/NamedValueMeta.java
  79. +22
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/NoSuchRpcPropertyException.java
  80. +269
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/RpcFacade.java
  81. +386
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/RpcObject.java
  82. +75
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/RpcObjectMeta.java
  83. +61
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/RpcPropertyMeta.java
  84. +5
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/RpcType.java
  85. +557
    -0
      jsonrpc/src/main/java/org/forks/jsonrpc/RpcTypeParser.java
  86. +3
    -0
      jsonrpc/src/main/res/values/strings.xml
  87. +15
    -0
      jsonrpc/src/test/java/org/forks/jsonrpc/ExampleUnitTest.java
  88. +1
    -0
      settings.gradle

+ 9
- 0
.gitignore View File

@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild

+ 22
- 0
.idea/compiler.xml View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

+ 3
- 0
.idea/copyright/profiles_settings.xml View File

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

+ 19
- 0
.idea/gradle.xml View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/jsonrpc" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

+ 46
- 0
.idea/misc.xml View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8 (1)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

+ 10
- 0
.idea/modules.xml View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Ytzh.iml" filepath="$PROJECT_DIR$/Ytzh.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/jsonrpc/jsonrpc.iml" filepath="$PROJECT_DIR$/jsonrpc/jsonrpc.iml" />
</modules>
</component>
</project>

+ 12
- 0
.idea/runConfigurations.xml View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

+ 1
- 0
app/.gitignore View File

@ -0,0 +1 @@
/build

+ 43
- 0
app/build.gradle View File

@ -0,0 +1,43 @@
apply plugin: 'com.android.application'
apply plugin: 'android-apt'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.qhclh.ytzh"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
testCompile 'junit:junit:4.12'
compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.support:support-v4:26.0.0-alpha1'
compile 'com.android.support:design:26.0.0-alpha1'
compile 'org.greenrobot:eventbus:3.0.0'
compile 'com.umeng.analytics:analytics:latest.integration'
compile 'pub.devrel:easypermissions:0.2.1'
compile 'com.google.code.gson:gson:2.8.1'
compile 'org.litepal.android:core:1.3.0'
compile 'com.journeyapps:zxing-android-embedded:3.5.0'
compile 'com.google.zxing:core:3.3.0'
compile project(':jsonrpc')
}

+ 25
- 0
app/proguard-rules.pro View File

@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in F:\SDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

+ 26
- 0
app/src/androidTest/java/com/qhclh/ytzh/ExampleInstrumentedTest.java View File

@ -0,0 +1,26 @@
package com.qhclh.ytzh;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumentation test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.qhclh.ytzh", appContext.getPackageName());
}
}

+ 29
- 0
app/src/main/AndroidManifest.xml View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.qhclh.ytzh">
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".home.MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".splash.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".home.MainActivity"/>
</application>
</manifest>

+ 9
- 0
app/src/main/assets/litepal.xml View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BWP_ytzh.db"></dbname>
<version value="1"></version>
<list>
<!--<mapping class="com.bwpsoft.bwp_khorchinmall.model.RegisterInputModel"></mapping>-->
</list>
</litepal>

+ 99
- 0
app/src/main/java/com/qhclh/ytzh/base/BaseActivity.java View File

@ -0,0 +1,99 @@
package com.qhclh.ytzh.base;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.qhclh.ytzh.R;
import com.qhclh.ytzh.utils.ActivityCollector;
import com.umeng.analytics.MobclickAgent;
import butterknife.ButterKnife;
/**
* Created by 青花瓷 on 2017/7/19.
*/
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(setLayoutId());
ButterKnife.bind(this);
ActivityCollector.addActivity(this);
initView();
initData();
initOper();
}
protected abstract int setLayoutId();
protected abstract void initView();
protected abstract void initData();
protected abstract void initOper();
///< toolbar设置
public void initToolbar(Toolbar toolbar, String title, View.OnClickListener listener) {
if (toolbar == null) {
return;
}
TextView tvTitle = findById(toolbar, R.id.tv_toolbar_title);
if (tvTitle != null) {
tvTitle.setText(title == null ? "" : title);
}
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
}
if (listener != null) {
toolbar.setNavigationIcon(R.drawable.back);
toolbar.setNavigationOnClickListener(listener);
}
}
@Override
protected void onResume() {
super.onResume();
try {
MobclickAgent.onResume(this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onPause() {
super.onPause();
try {
MobclickAgent.onPause(this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
public void finishAll(){ActivityCollector.finishAll();}
public void showToast(String str) {
Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
}
protected <T extends View> T findById(@NonNull View view, @IdRes int resId) {
return ButterKnife.findById(view, resId);
}
}

+ 31
- 0
app/src/main/java/com/qhclh/ytzh/configs/ConfigBase.java View File

@ -0,0 +1,31 @@
package com.qhclh.ytzh.configs;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.qhclh.ytzh.utils.StringUtil;
public abstract class ConfigBase {
String mName;
Context mContext;
public ConfigBase(Context context, String name) {
mName = name;
mContext = context;
}
public SharedPreferences getStore() {
if (StringUtil.IsNullOrEmpty(mName)) {
return PreferenceManager.getDefaultSharedPreferences(mContext);
} else {
return mContext.getSharedPreferences(mName, Context.MODE_PRIVATE);
}
}
public abstract void GetValues(SharedPreferences store);
public abstract void SetValues(SharedPreferences.Editor store);
}

+ 29
- 0
app/src/main/java/com/qhclh/ytzh/configs/ConfigUtil.java View File

@ -0,0 +1,29 @@
package com.qhclh.ytzh.configs;
import android.content.Context;
import android.content.SharedPreferences;
public class ConfigUtil {
public static <T extends ConfigBase> void Fill(T config) {
SharedPreferences store = config.getStore();
config.GetValues(store);
}
public static <T extends ConfigBase> void Save(T config) {
SharedPreferences store = config.getStore();
SharedPreferences.Editor editor = store.edit();
editor.clear();
config.SetValues(editor);
editor.commit();
}
public static String getServerUri(Context context) {
ServerConfig config = new ServerConfig(context);
Fill(config);
return config.getServerUri();
}
}

+ 32
- 0
app/src/main/java/com/qhclh/ytzh/configs/LastLoginInfo.java View File

@ -0,0 +1,32 @@
package com.qhclh.ytzh.configs;
import android.content.Context;
import android.content.SharedPreferences;
public class LastLoginInfo extends ConfigBase {
public LastLoginInfo(Context context) {
super(context, "LastLoginUserInfo");
// TODO Auto-generated constructor stub
}
@Override
public void GetValues(SharedPreferences store) {
Username = store.getString("Username", "");
Password = store.getString("Password", "");
CurrentTimeMillis = store.getLong("CurrentTimeMillis", 0);
}
@Override
public void SetValues(SharedPreferences.Editor store) {
store.putString("Username", Username);
store.putString("Password", Password);
store.putLong("CurrentTimeMillis", System.currentTimeMillis());
}
public String Username;
public String Password;
public long CurrentTimeMillis;
}

+ 31
- 0
app/src/main/java/com/qhclh/ytzh/configs/LoginUserConfig.java View File

@ -0,0 +1,31 @@
package com.qhclh.ytzh.configs;
import android.content.Context;
import android.content.SharedPreferences;
public class LoginUserConfig extends ConfigBase {
public LoginUserConfig(Context context) {
super(context, "LoginUserConfig");
}
@Override
public void GetValues(SharedPreferences store) {
Username = store.getString("Username", "");
Password = store.getString("Password", "");
DisplayName = store.getString("DisplayName", "");
}
@Override
public void SetValues(SharedPreferences.Editor store) {
store.putString("Username", Username);
store.putString("Password", Password);
store.putString("DisplayName", DisplayName);
}
public String Username;
public String Password;
public String DisplayName;
}

+ 93
- 0
app/src/main/java/com/qhclh/ytzh/configs/ServerConfig.java View File

@ -0,0 +1,93 @@
package com.qhclh.ytzh.configs;
import android.content.Context;
import android.content.SharedPreferences;
import org.forks.jsonrpc.RpcFacade;
public class ServerConfig extends ConfigBase {
String JPUSH_TAG_KEY="jpushtagkey";
String SYSTEMSET_ENABLE_SCAN="systemset_enable_scan";
String ENABLE_Catogray="systemset_enable_catogray";
String ENABLE_MoneyTipe="systemset_enable_moneytipe";
String ENABLE_StoreGoods="systemset_enable_storegoods";
public ServerConfig(Context context) {
super(context, "");
}
@Override
public void GetValues(SharedPreferences store) {
mServerUri = store.getString(RpcFacade.SERVER_URI_PREFKEY, "");
mTag = store.getString(JPUSH_TAG_KEY, "");
mEnableGoodsScan = store.getBoolean(SYSTEMSET_ENABLE_SCAN,false);
mEnableGoodsCatogray = store.getBoolean(ENABLE_Catogray,false);
mEnablMoneyTipe = store.getBoolean(ENABLE_MoneyTipe,false);
mEnablStoreGoods = store.getBoolean(ENABLE_StoreGoods,false);
}
@Override
public void SetValues(SharedPreferences.Editor store) {
store.putString(RpcFacade.SERVER_URI_PREFKEY, getServerUri());
store.putString(JPUSH_TAG_KEY, getTag());
store.putBoolean(SYSTEMSET_ENABLE_SCAN,getEnableGoodsScan());
store.putBoolean(ENABLE_Catogray,getEnableGoodsCatogray());
store.putBoolean(ENABLE_MoneyTipe,getEnableMoneyTipe());
store.putBoolean(ENABLE_StoreGoods,getEnableStoreGoods());
}
private String mServerUri;
private String mTag;
public String getServerUri() {
return mServerUri;
}
public void setServerUri(String value) {
mServerUri = value;
}
public String getTag() {
return mTag;
}
public void setTag(String value) {
mTag = value;
}
private boolean mEnableGoodsScan;
public boolean getEnableGoodsScan() {
return mEnableGoodsScan;
}
public void setEnableGoodsScang(boolean value) {
mEnableGoodsScan = value;
}
private boolean mEnableGoodsCatogray;
public boolean getEnableGoodsCatogray() {
return mEnableGoodsCatogray;
}
public void setEnableGoodsCatogray(boolean value) {
mEnableGoodsCatogray = value;
}
private boolean mEnablMoneyTipe;
public boolean getEnableMoneyTipe() {
return mEnablMoneyTipe;
}
public void setEnableMoneyTipe(boolean value) {
mEnablMoneyTipe = value;
}
private boolean mEnablStoreGoods;
public boolean getEnableStoreGoods() {
return mEnablStoreGoods;
}
public void setEnableStoreGoods(boolean value) {
mEnablStoreGoods = value;
}
}

+ 43
- 0
app/src/main/java/com/qhclh/ytzh/home/MainActivity.java View File

@ -0,0 +1,43 @@
package com.qhclh.ytzh.home;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.TextView;
import com.qhclh.ytzh.R;
import com.qhclh.ytzh.base.BaseActivity;
import butterknife.BindView;
public class MainActivity extends BaseActivity {
@BindView(R.id.textaaa)
TextView textView;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@Override
protected int setLayoutId() {
return R.layout.act_main;
}
@Override
protected void initView() {
initToolbar(mToolbar, "aaaaa", new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
@Override
protected void initData() {
textView.setText("aaaaaaaaaaa");
}
@Override
protected void initOper() {
}
}

+ 61
- 0
app/src/main/java/com/qhclh/ytzh/home/MyApplication.java View File

@ -0,0 +1,61 @@
package com.qhclh.ytzh.home;
import android.app.Activity;
import com.qhclh.ytzh.configs.ConfigUtil;
import com.qhclh.ytzh.configs.LastLoginInfo;
import com.qhclh.ytzh.configs.ServerConfig;
import org.forks.jsonrpc.RpcFacade;
import org.litepal.LitePalApplication;
import java.util.LinkedList;
import java.util.List;
/**
* Created by 青花瓷 on 2017/11/23.
*/
public class MyApplication extends LitePalApplication {
private final String NAME ="ytzh";
static LastLoginInfo mLoginInfo;
private static MyApplication instance;
String url= RpcUrl.BaseAppUrl;
ServerConfig config;
private List<Activity> activityList = new LinkedList<Activity>();
public static MyApplication getInstance(){
if (null == instance) {
instance = new MyApplication();
}
return instance;
}
@Override
public void onCreate() {
super.onCreate();
mLoginInfo = new LastLoginInfo(this);
ConfigUtil.Fill(mLoginInfo);
///< 先暂时必须设置URL
config = new ServerConfig(this);
config.setServerUri(url);
ConfigUtil.Save(config);
RpcFacade.init(this.getApplicationContext(),NAME);
}
public void exit() {
for (Activity activity : activityList) {
activity.finish();
}
System.exit(0);
}
public static void ClearLogin() {
mLoginInfo.Username = "";
ConfigUtil.Save(mLoginInfo);
}
}

+ 11
- 0
app/src/main/java/com/qhclh/ytzh/home/RpcUrl.java View File

@ -0,0 +1,11 @@
package com.qhclh.ytzh.home;
public class RpcUrl {
///< 域名开发
// public static String BaseAppUrl = "http://192.168.1.9/MarketPlace/";
///< 正式服务器地址
public static String BaseAppUrl = "http://47.93.175.172/Marketplace/";
///< 外网测试
// public static String BaseAppUrl = "http://111.198.52.49:81/MarketPlace/";
}

+ 7
- 0
app/src/main/java/com/qhclh/ytzh/interfaces/OnPromptListener.java View File

@ -0,0 +1,7 @@
package com.qhclh.ytzh.interfaces;
public interface OnPromptListener {
public void OnPrompt(String prompt);
}

+ 66
- 0
app/src/main/java/com/qhclh/ytzh/splash/SplashActivity.java View File

@ -0,0 +1,66 @@
package com.qhclh.ytzh.splash;
import android.content.Intent;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.LinearLayout;
import com.qhclh.ytzh.R;
import com.qhclh.ytzh.base.BaseActivity;
import com.qhclh.ytzh.home.MainActivity;
import butterknife.BindView;
/**
* Created by 青花瓷 on 2017/11/23.
*/
public class SplashActivity extends BaseActivity {
@BindView(R.id.ll_splash)
LinearLayout ll_splash;
@Override
protected int setLayoutId() {
return R.layout.act_splash;
}
@Override
protected void initView() {
}
@Override
protected void initData() {
}
@Override
protected void initOper() {
//渐变展示启动屏
AlphaAnimation aa = new AlphaAnimation(0.3f, 1.0f);
aa.setDuration(2000);
ll_splash.startAnimation(aa);
aa.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation arg0) {
redirectTo();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
});
}
private void redirectTo() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
}

+ 115
- 0
app/src/main/java/com/qhclh/ytzh/tasks/CallableTask.java View File

@ -0,0 +1,115 @@
package com.qhclh.ytzh.tasks;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.qhclh.ytzh.utils.DialogUtil;
import java.util.concurrent.Callable;
public abstract class CallableTask implements Callable<Object> {
final String tag = "CallableTask";
Boolean mIsRunning = false;
protected abstract void successUI();
void failUI(Exception e) {
Log.e(tag, e.getMessage(), e);
if(e.getMessage().contains("Unauthorized"))
{
return;
}
if(e.getMessage().contains("Socket"))
{
return;
}
if(e.getMessage().contains("cannot"))
{
return;
}
DialogUtil.AutoHiddenAlert(mContext,e.getMessage());
// DialogUtil.Alert(mContext, e.getMessage());
}
Context mContext;
ProgressDialog mDialog;
String mMessage;
public CallableTask(Context context, String message) {
mContext = context;
mMessage = message;
}
public final void execute() {
if (mIsRunning) {
Log.w(tag, "任务重复执行");
return;
}
new Task().execute();
}
class Task extends AsyncTask<Void, Void, Void> {
Exception mException;
@Override
protected Void doInBackground(Void... params) {
try {
mIsRunning = true;
call();
} catch (Exception ex) {
mException = ex;
cancel(false);
}
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
endExecute();
failUI(mException);
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
endExecute();
successUI();
}
public void endExecute() {
// if (mDialog != null && isValidContext(mContext) && mDialog.isShowing()) {
if (mDialog != null) {
mDialog.dismiss();
}
mIsRunning = false;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
// if (isValidContext(mContext)) {
mDialog = ProgressDialog.show(mContext, "请稍等", mMessage, true);
// }
}
}
// private boolean isValidContext (Context c){
// Activity a = (Activity)c;
// if (a.isDestroyed() || a.isFinishing()){
// return false;
// }else{
// return true;
// }
// }
}

+ 39
- 0
app/src/main/java/com/qhclh/ytzh/tasks/ViewOnClickTask.java View File

@ -0,0 +1,39 @@
package com.qhclh.ytzh.tasks;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
import com.qhclh.ytzh.utils.DialogUtil;
import com.qhclh.ytzh.utils.StringUtil;
public abstract class ViewOnClickTask extends CallableTask implements
View.OnClickListener {
private String mPrompt;
public ViewOnClickTask(Context context, String message) {
super(context, message);
}
public void setPrompt(String prompt) {
mPrompt = prompt;
}
public void onClick(View v) {
if (!StringUtil.IsNullOrEmpty(mPrompt)) {
DialogUtil.Confirm(v.getContext(), mPrompt, "确定", "取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
ViewOnClickTask.this.execute();
}
});
} else {
super.execute();
}
}
}

+ 36
- 0
app/src/main/java/com/qhclh/ytzh/utils/ActivityCollector.java View File

@ -0,0 +1,36 @@
package com.qhclh.ytzh.utils;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jiangxk on 2016/11/29.
*/
public class ActivityCollector {
private ActivityCollector() {
}
private static List<Activity> sActivityList = new ArrayList<>();
public static void addActivity(Activity activity) {
if (!sActivityList.contains(activity)) {
sActivityList.add(activity);
}
}
public static void removeActivity(Activity activity) {
sActivityList.remove(activity);
}
public static void finishAll() {
for (Activity activity : sActivityList) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}

+ 72
- 0
app/src/main/java/com/qhclh/ytzh/utils/DateTimeUtil.java View File

@ -0,0 +1,72 @@
package com.qhclh.ytzh.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public final class DateTimeUtil {
static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
static SimpleDateFormat dateFormatDetail = new SimpleDateFormat("yyyy-MM-dd HH:mm");
public static Date ParseDate(String dateStr) throws ParseException {
return dateFormat.parse(dateStr);
}
public static Date ParseDateDetail(String dateStr) throws ParseException {
return dateFormatDetail.parse(dateStr);
}
public static Date SafeParseDate(String dateStr) {
try {
if (StringUtil.IsNullOrEmpty(dateStr)) {
return new Date();
}
return ParseDate(dateStr);
} catch (ParseException e) {
return new Date();
}
}
public static Date SafeParseDateDetail(String dateStr) {
try {
if (StringUtil.IsNullOrEmpty(dateStr)) {
return new Date();
}
return ParseDateDetail(dateStr);
} catch (ParseException e) {
return new Date();
}
}
public static Calendar SafeParseCalendar(String dateStr) {
Calendar calendar = Calendar.getInstance(Locale.getDefault());
calendar.setTime(SafeParseDate(dateStr));
return calendar;
}
public static String FormatDate(Calendar calendar) {
return dateFormat.format(calendar.getTime());
}
public static String FormatDate(Date date) {
if (date == null) {
return "";
}
return dateFormat.format(date);
}
public static String FormatDateDetail(Date date) {
if (date == null) {
return "";
}
return dateFormatDetail.format(date);
}
public static Date RemoveTime(Date time) {
return SafeParseDate(FormatDate(time));
}
}

+ 189
- 0
app/src/main/java/com/qhclh/ytzh/utils/DialogUtil.java View File

@ -0,0 +1,189 @@
package com.qhclh.ytzh.utils;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.qhclh.ytzh.interfaces.OnPromptListener;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.Callable;
public class DialogUtil {
abstract static class ProgressDialogHelper {
Context mContext;
String mMessage;
Callable<?> mRunnable;
Handler mHandler = new Handler();
Callable<?> mCallableAfterSuccess;
public void setCallableAfterSuccess(Callable<?> callable) {
mCallableAfterSuccess = callable;
}
public ProgressDialogHelper(Context context, String message,
Callable<?> runnable) {
this.mContext = context;
this.mMessage = message;
this.mRunnable = runnable;
}
ProgressDialog mDialog;
public void Start() {
mDialog = ProgressDialog.show(mContext, "请稍等", mMessage, true);
Thread thread = new Thread() {
@Override
public void run() {
try {
mRunnable.call();
} catch (Exception ex) {
ex.printStackTrace();
Runnable runnable = new Runnable() {
public void run() {
DialogUtil.Alert(mContext, mMessage);
}
String mMessage;
public Runnable setMessage(String message) {
mMessage = message;
return this;
}
}.setMessage(ex.getMessage());
mHandler.post(runnable);
} finally {
mDialog.dismiss();
}
}
};
thread.start();
}
}
public static void Progress(Context context, String message,
Callable<?> callable) {
new ProgressDialogHelper(context, message, callable) {
}.Start();
}
public static void Progress(Context context, String message,
Callable<?> callable, Callable<?> callableAfterSuccess) {
ProgressDialogHelper helper = new ProgressDialogHelper(context,
message, callable) {
};
helper.Start();
}
public static void Alert(Context context, String message) {
new AlertDialog.Builder(context).setMessage(message)
.setPositiveButton("确定", null).show();
}
public static void AlertAndFinish(final Activity activity, String message) {
new AlertDialog.Builder(activity).setMessage(message)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
activity.finish();
}
}).show();
}
public static void Alert(View view, String message) {
Alert(view.getContext(), message);
}
public static void AutoHiddenAlert(Context context, String message) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
public static void AutoHiddenAlert(View view, String message) {
AutoHiddenAlert(view.getContext(), message);
}
public interface SetDate {
void setDate(Date date);
}
public static void AddSelectDateDialog(TextView arg0,
final SetDate onsetdate) {
arg0.setOnClickListener(new View.OnClickListener() {
public void onClick(final View view) {
final TextView textView = (TextView) view;
DatePickerDialog.OnDateSetListener onDateSetListener = new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker datePicker, int year,
int month, int day) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day);
textView.setText(DateTimeUtil.FormatDate(calendar));
onsetdate.setDate(calendar.getTime());
}
};
String dateStr = textView.getText().toString();
Calendar calendar = DateTimeUtil.SafeParseCalendar(dateStr);
new DatePickerDialog(view.getContext(), onDateSetListener,
calendar.get(Calendar.YEAR), calendar
.get(Calendar.MONTH), calendar
.get(Calendar.DAY_OF_MONTH)).show();
}
});
}
public static void Prompt(Context context, String title, String message,
String inputValue, int inputType, final OnPromptListener onprompt) {
final EditText input = new EditText(context);
input.setText(inputValue);
input.setInputType(inputType);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title).setMessage(message).setView(input)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
String prompt = input.getText().toString();
onprompt.OnPrompt(prompt);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
}).show();
}
public static void Confirm(Context context, String title,
String trueString, String falseString,
DialogInterface.OnClickListener onConfirm) {
new AlertDialog.Builder(context).setTitle(title)
.setPositiveButton(trueString, onConfirm)
.setNegativeButton(falseString, null).show();
}
}

+ 30
- 0
app/src/main/java/com/qhclh/ytzh/utils/StringUtil.java View File

@ -0,0 +1,30 @@
package com.qhclh.ytzh.utils;
import android.content.Context;
import java.math.BigDecimal;
public class StringUtil {
public static Boolean IsNullOrEmpty(String s) {
return s == null || s.length() == 0;
}
public String GetResource(Context context, int resId) {
return context.getString(resId);
}
public static String ToString(Object object) {
if (object == null) {
return "";
}
return String.format("%s", object);
}
public static BigDecimal ParseMoney(String strValue) {
if (IsNullOrEmpty(strValue)) {
return null;
}
return BigDecimal.valueOf(Double.valueOf(strValue));
}
}

+ 9
- 0
app/src/main/res/anim/anim_in_left.xml View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fillAfter="true"
android:fromXDelta="-100%p"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="0"/>
</set>

+ 9
- 0
app/src/main/res/anim/anim_in_right.xml View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fillAfter="true"
android:fromXDelta="100%p"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="0"/>
</set>

+ 9
- 0
app/src/main/res/anim/anim_out_left.xml View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fillAfter="true"
android:fromXDelta="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="-100%p"/>
</set>

+ 9
- 0
app/src/main/res/anim/anim_out_right.xml View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fillAfter="true"
android:fromXDelta="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="100%p"/>
</set>

BIN
app/src/main/res/drawable-xhdpi/back.png View File

Before After
Width: 58  |  Height: 58  |  Size: 220 KiB

+ 12
- 0
app/src/main/res/layout/act_main.xml View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/include_tool_bar"></include>
<TextView
android:id="@+id/textaaa"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

+ 9
- 0
app/src/main/res/layout/act_splash.xml View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_splash"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/ic_launcher"
android:orientation="vertical">
</LinearLayout>

+ 6
- 0
app/src/main/res/layout/include_line.xml View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/grey_a3a3a3">
</View>

+ 45
- 0
app/src/main/res/layout/include_tab_bar.xml View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/white"
android:orientation="horizontal">
<!-- 底部导航栏-->
<LinearLayout
android:id="@+id/ll_gonghuoshang"
style="@style/TabLayout">
<ImageView
android:id="@+id/iv_gonghuoshang"
style="@style/TabIcon" />
<TextView
android:id="@+id/tv_gonghuoshang"
style="@style/TabText"
android:text="@string/app_name" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_gouwuche"
style="@style/TabLayout">
<ImageView
android:id="@+id/iv_gouwuche"
style="@style/TabIcon" />
<TextView
android:id="@+id/tv_gouwuche"
style="@style/TabText"
android:text="@string/app_name" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_dingdan"
style="@style/TabLayout">
<ImageView
android:id="@+id/iv_dingdan"
style="@style/TabIcon" />
<TextView
android:id="@+id/tv_dingdan"
style="@style/TabText"
android:text="@string/app_name" />
</LinearLayout>
</LinearLayout>

+ 17
- 0
app/src/main/res/layout/include_tool_bar.xml View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- toolbar-->
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
android:elevation="@dimen/dp_2"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<TextView
android:id="@+id/tv_toolbar_title"
style="@style/TextView_18_black_282828"
android:layout_gravity="center"/>
</android.support.v7.widget.Toolbar>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png View File

Before After
Width: 72  |  Height: 72  |  Size: 3.3 KiB

BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png View File

Before After
Width: 72  |  Height: 72  |  Size: 4.1 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png View File

Before After
Width: 48  |  Height: 48  |  Size: 2.2 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png View File

Before After
Width: 48  |  Height: 48  |  Size: 2.5 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png View File

Before After
Width: 96  |  Height: 96  |  Size: 4.7 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png View File

Before After
Width: 96  |  Height: 96  |  Size: 6.0 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png View File

Before After
Width: 144  |  Height: 144  |  Size: 7.5 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png View File

Before After
Width: 144  |  Height: 144  |  Size: 9.8 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png View File

Before After
Width: 192  |  Height: 192  |  Size: 10 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png View File

Before After
Width: 192  |  Height: 192  |  Size: 14 KiB

+ 24
- 0
app/src/main/res/values/colors.xml View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--标题栏 -->
<color name="colorPrimary">#E3383B</color>
<!-- 状态栏-->
<color name="colorPrimaryDark">#E3383B</color>
<!-- 各种控件默认选中颜色-->
<color name="colorAccent">#E3383B</color>
<color name="grey999">#999999</color>
<color name="greyeee">#EEEEEE</color>
<color name="red">#E3383B</color>
<color name="red_e6">#E6E3383B</color>
<color name="red_ee">#eeee4242</color>
<color name="white">#ffffff</color>
<color name="black">#000000</color>
<color name="grey_767c82">#767c82</color>
<color name="black_282828">#282828</color>
<color name="tran">#00000000</color>
<color name="grey_a3a3a3">#a3a3a3</color>
</resources>

+ 174
- 0
app/src/main/res/values/dimens.xml View File

@ -0,0 +1,174 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<!--text大小-->
<dimen name="text_size_6">6sp</dimen>
<dimen name="text_size_10">10sp</dimen>
<dimen name="text_size_12">12sp</dimen>
<dimen name="text_size_14">14sp</dimen>
<dimen name="text_size_16">16sp</dimen>
<dimen name="text_size_18">18sp</dimen>
<dimen name="text_size_20">20sp</dimen>
<dimen name="text_size_22">22sp</dimen>
<dimen name="text_size_24">24sp</dimen>
<dimen name="text_size_26">26sp</dimen>
<dimen name="text_size_30">30sp</dimen>
<dimen name="text_size_32">32sp</dimen>
<dimen name="text_size_34">34sp</dimen>
<dimen name="text_size_38">38sp</dimen>
<dimen name="text_size_48">48sp</dimen>
<dimen name="dp_0">0dp</dimen>
<dimen name="dp_0.1">0.1dp</dimen>
<dimen name="dp_0.2">0.2dp</dimen>
<dimen name="dp_0.4">0.4dp</dimen>
<dimen name="dp_0.5">0.5dp</dimen>
<dimen name="dp_1">1dp</dimen>
<dimen name="dp_2">2dp</dimen>
<dimen name="dp_3">3dp</dimen>
<dimen name="dp_5">5dp</dimen>
<dimen name="dp_6">6dp</dimen>
<dimen name="dp_7">7dp</dimen>
<dimen name="dp_8">8dp</dimen>
<dimen name="dp_10">10dp</dimen>
<dimen name="dp_11">11dp</dimen>
<dimen name="dp_12">12dp</dimen>
<dimen name="dp_13">13dp</dimen>
<dimen name="dp_14">14dp</dimen>
<dimen name="dp_15">15dp</dimen>
<dimen name="dp_16">16dp</dimen>
<dimen name="dp_18">18dp</dimen>
<dimen name="dp_20">20dp</dimen>
<dimen name="dp_22">22dp</dimen>
<dimen name="dp_24">24dp</dimen>
<dimen name="dp_25">25dp</dimen>
<dimen name="dp_26">26dp</dimen>
<dimen name="dp_28">28dp</dimen>
<dimen name="dp_30">30dp</dimen>
<dimen name="dp_32">32dp</dimen>
<dimen name="dp_34">34dp</dimen>
<dimen name="dp_35">35dp</dimen>
<dimen name="dp_36">36dp</dimen>
<dimen name="dp_38">38dp</dimen>
<dimen name="dp_40">40dp</dimen>
<dimen name="dp_42">42dp</dimen>
<dimen name="dp_44">44dp</dimen>
<dimen name="dp_46">46dp</dimen>
<dimen name="dp_48">48dp</dimen>
<dimen name="dp_50">50dp</dimen>
<dimen name="dp_52">52dp</dimen>
<dimen name="dp_53">53dp</dimen>
<dimen name="dp_54">54dp</dimen>
<dimen name="dp_55">55dp</dimen>
<dimen name="dp_56">56dp</dimen>
<dimen name="dp_59">59dp</dimen>
<dimen name="dp_60">60dp</dimen>
<dimen name="dp_62">62dp</dimen>
<dimen name="dp_64">64dp</dimen>
<dimen name="dp_65">65dp</dimen>
<dimen name="dp_66">66dp</dimen>
<dimen name="dp_68">68dp</dimen>
<dimen name="dp_69">69dp</dimen>
<dimen name="dp_70">70dp</dimen>
<dimen name="dp_72">72dp</dimen>
<dimen name="dp_74">74dp</dimen>
<dimen name="dp_75">75dp</dimen>
<dimen name="dp_78">78dp</dimen>
<dimen name="dp_80">80dp</dimen>
<dimen name="dp_82">82dp</dimen>
<dimen name="dp_84">84dp</dimen>
<dimen name="dp_85">85dp</dimen>
<dimen name="dp_86">86dp</dimen>
<dimen name="dp_88">88dp</dimen>
<dimen name="dp_90">90dp</dimen>
<dimen name="dp_94">94dp</dimen>
<dimen name="dp_95">95dp</dimen>
<dimen name="dp_96">96dp</dimen>
<dimen name="dp_98">98dp</dimen>
<dimen name="dp_100">100dp</dimen>
<dimen name="dp_102">102dp</dimen>
<dimen name="dp_103">103dp</dimen>
<dimen name="dp_105">105dp</dimen>
<dimen name="dp_106">106dp</dimen>
<dimen name="dp_108">108dp</dimen>
<dimen name="dp_110">110dp</dimen>
<dimen name="dp_112">112dp</dimen>
<dimen name="dp_114">114dp</dimen>
<dimen name="dp_117">117dp</dimen>
<dimen name="dp_120">120dp</dimen>
<dimen name="dp_122">122dp</dimen>
<dimen name="dp_124">124dp</dimen>
<dimen name="dp_129">129dp</dimen>
<dimen name="dp_130">130dp</dimen>
<dimen name="dp_138">138dp</dimen>
<dimen name="dp_150">150dp</dimen>
<dimen name="dp_154">154dp</dimen>
<dimen name="dp_156">156dp</dimen>
<dimen name="dp_157">157dp</dimen>
<dimen name="dp_158">158dp</dimen>
<dimen name="dp_172">172dp</dimen>
<dimen name="dp_175">175dp</dimen>
<dimen name="dp_176">176dp</dimen>
<dimen name="dp_180">180dp</dimen>
<dimen name="dp_188">188dp</dimen>
<dimen name="dp_200">200dp</dimen>
<dimen name="dp_207">207dp</dimen>
<dimen name="dp_218">218dp</dimen>
<dimen name="dp_220">220dp</dimen>
<dimen name="dp_230">230dp</dimen>
<dimen name="dp_240">240dp</dimen>
<dimen name="dp_250">250dp</dimen>
<dimen name="dp_252">252dp</dimen>
<dimen name="dp_274">274dp</dimen>
<dimen name="dp_275">275dp</dimen>
<dimen name="dp_280">280dp</dimen>
<dimen name="dp_300">300dp</dimen>
<dimen name="dp_350">350dp</dimen>
<dimen name="px_1">1px</dimen>
<dimen name="px_8">8px</dimen>
<dimen name="px_20">20px</dimen>
<dimen name="tab_text_size">@dimen/text_size_12</dimen>
<dimen name="tab_icon_height">24dp</dimen>
<dimen name="tab_icon_width">24dp</dimen>
<dimen name="tab_layout_padding">8dp</dimen>
<!-- ************************************************************分割线************************************************************-->
<!-- 所有页面的titlebar高度 -->
<dimen name="titlebar_height">50dp</dimen>
<!-- 所有页面的footerbar高度 -->
<dimen name="footerbar_height">50dp</dimen>
<dimen name="title_size">22dp</dimen>
<!-- 页面title栏title字体大小 -->
<!-- ListView item高度 -->
<dimen name="list_one_item_height">65dp</dimen>
<!-- 普通输入区单行高度 -->
<dimen name="text_one_item_height">50dp</dimen>
<!-- 普通显示区单行高度 -->
<dimen name="showtext_one_item_height">38dp</dimen>
<!-- 页面主字体大小 -->
<dimen name="main_text_size">15dp</dimen>
<!-- 页面按钮上的字体大小 -->
<dimen name="size_in_button">16dp</dimen>
<!-- 带照片的行高 -->
<dimen name="line_height_with_photo">60dp</dimen>
<!-- 照片高 -->
<dimen name="photo_height_in_line">57dp</dimen>
<!-- 页面布局 -->
<dimen name="page_to_left">15dip</dimen>
<dimen name="page_to_top">20dip</dimen>
</resources>

+ 3
- 0
app/src/main/res/values/strings.xml View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">Ytzh</string>
</resources>

+ 54
- 0
app/src/main/res/values/styles.xml View File

@ -0,0 +1,54 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
<item name="actionMenuTextColor">@color/colorPrimaryDark</item>
<!-- 设置activity切换动画 -->
<item name="android:windowAnimationStyle">@style/activityAnimation</item>
</style>
<style name="activityAnimation" parent="@android:style/Animation">
<item name="android:activityOpenEnterAnimation">@anim/anim_in_right</item>
<item name="android:activityOpenExitAnimation">@anim/anim_out_left</item>
<item name="android:activityCloseEnterAnimation">@anim/anim_in_left</item>
<item name="android:activityCloseExitAnimation">@anim/anim_out_right</item>
</style>
<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">@android:color/white</item>
</style>
<style name="TextView_18_black_282828">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/text_size_18</item>
</style>
<style name="TabLayout">
<item name="android:padding">@dimen/tab_layout_padding</item>
<item name="android:layout_height">match_parent</item>
<!--<item name="android:background">@drawable/selector_white2gray</item>-->
<item name="android:layout_width">0dp</item>
<item name="android:layout_weight">1</item>
<item name="android:gravity">center</item>
<item name="android:orientation">vertical</item>
</style>
<style name="TabIcon">
<item name="android:layout_height">@dimen/tab_icon_height</item>
<item name="android:layout_width">@dimen/tab_icon_width</item>
</style>
<style name="TabText">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:textColor">@color/grey_767c82</item>
<item name="android:textSize">@dimen/tab_text_size</item>
</style>
</resources>

+ 17
- 0
app/src/test/java/com/qhclh/ytzh/ExampleUnitTest.java View File

@ -0,0 +1,17 @@
package com.qhclh.ytzh;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}

+ 23
- 0
build.gradle View File

@ -0,0 +1,23 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

+ 17
- 0
gradle.properties View File

@ -0,0 +1,17 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

BIN
gradle/wrapper/gradle-wrapper.jar View File


+ 6
- 0
gradle/wrapper/gradle-wrapper.properties View File

@ -0,0 +1,6 @@
#Thu Nov 23 10:54:26 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

+ 160
- 0
gradlew View File

@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# 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
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# 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
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" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

+ 90
- 0
gradlew.bat View File

@ -0,0 +1,90 @@
@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
@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=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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 Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_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=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
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

+ 1
- 0
jsonrpc/.gitignore View File

@ -0,0 +1 @@
/build

+ 27
- 0
jsonrpc/build.gradle View File

@ -0,0 +1,27 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion '25.0.0'
defaultConfig {
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2'
}

+ 17
- 0
jsonrpc/proguard-rules.pro View File

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /opt/android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

+ 13
- 0
jsonrpc/src/androidTest/java/org/forks/jsonrpc/ApplicationTest.java View File

@ -0,0 +1,13 @@
package org.forks.jsonrpc;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

+ 11
- 0
jsonrpc/src/main/AndroidManifest.xml View File

@ -0,0 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.forks.jsonrpc">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>

+ 38
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/DFDataTable.java View File

@ -0,0 +1,38 @@
package org.forks.jsonrpc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class DFDataTable {
private Map<String, RpcPropertyMeta> mColumns;
private List<RpcObject> mRows;
private RpcObject mSumRow;
DFDataTable() {
this(new HashMap<String, RpcPropertyMeta>(),
new ArrayList<RpcObject>(), null);
}
DFDataTable(Map<String, RpcPropertyMeta> columns, List<RpcObject> rows,
RpcObject sumRow) {
super();
mColumns = columns;
mRows = rows;
mSumRow = sumRow;
}
public Map<String, RpcPropertyMeta> getColumns() {
return mColumns;
}
public List<RpcObject> getRows() {
return mRows;
}
public RpcObject getSumRow() {
return mSumRow;
}
}

+ 76
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/Helper.java View File

@ -0,0 +1,76 @@
package org.forks.jsonrpc;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
final class Helper {
static String getString(JSONObject obj, String name)
throws JsonRpcException {
try {
return obj.getString(name);
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
static int getInt(JSONObject obj, String name) throws JsonRpcException {
try {
return obj.getInt(name);
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
static JSONObject parseJsonObject(String json) throws JsonRpcException {
try {
return (JSONObject) new JSONTokener(json).nextValue();
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
static JSONArray getJsonArray(JSONObject obj, String name)
throws JsonRpcException {
try {
return obj.getJSONArray(name);
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
public static JSONArray getJsonArray(JSONArray array, int i)
throws JsonRpcException {
try {
return array.getJSONArray(i);
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
static JSONObject getJsonObject(JSONArray arr, int idx)
throws JsonRpcException {
try {
return arr.getJSONObject(idx);
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
static Object get(JSONObject obj, String name) throws JsonRpcException {
try {
return obj.get(name);
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
public static Object get(JSONArray array, int idx) throws JsonRpcException {
try {
return array.get(idx);
} catch (JSONException e) {
throw new JsonRpcException(e);
}
}
}

+ 84
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/HttpJsonRpcClient.java View File

@ -0,0 +1,84 @@
package org.forks.jsonrpc;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;
public final class HttpJsonRpcClient extends JsonRpcClient {
private final String mRequestUri;
final static CookieStore sCookieStore = new BasicCookieStore();
private static DefaultHttpClient sHttpClient;
private static String sAppName = "[android] ";
static {
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpConnectionParams.setSoTimeout(params, 45 * 1000);
sHttpClient = new DefaultHttpClient(params);
sHttpClient.setCookieStore(sCookieStore);
}
public HttpJsonRpcClient(String requestUri, String method) {
super(method);
mRequestUri = requestUri;
}
@Override
protected String doRequest(String json) throws JsonRpcException {
HttpPost request = new HttpPost(mRequestUri);
request.setEntity(newStringEntity(json));
request.setHeader("User-Agent", sAppName);
HttpResponse response = getResponse(request);
return getResponseString(response);
}
static void sSetClientAppName(String appName) {
sAppName = "[android] " + appName;
}
private static String getResponseString(HttpResponse response)
throws JsonRpcException {
HttpEntity back = response.getEntity();
try {
return EntityUtils.toString(back);
} catch (IOException e) {
throw new JsonRpcException(e);
}
}
private static StringEntity newStringEntity(String json)
throws JsonRpcException {
try {
return new StringEntity(json, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new JsonRpcException(e);
}
}
private static HttpResponse getResponse(HttpPost request)
throws JsonRpcException {
try {
return sHttpClient.execute(request);
} catch (ClientProtocolException e) {
throw new JsonRpcException(e);
} catch (IOException e) {
throw new JsonRpcException(e);
}
}
}

+ 23
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/InvalidPropertyValueException.java View File

@ -0,0 +1,23 @@
package org.forks.jsonrpc;
@SuppressWarnings("serial")
public final class InvalidPropertyValueException extends
JsonRpcRuntimeException {
public InvalidPropertyValueException() {
}
public InvalidPropertyValueException(String detailMessage) {
super(detailMessage);
}
public InvalidPropertyValueException(Throwable throwable) {
super(throwable);
}
public InvalidPropertyValueException(String detailMessage,
Throwable throwable) {
super(detailMessage, throwable);
}
}

+ 69
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/IterHelper.java View File

@ -0,0 +1,69 @@
package org.forks.jsonrpc;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
final class IterHelper {
private IterHelper() {
}
public static <T> ArrayList<T> toList(Iterable<T> iter) {
ArrayList<T> result = new ArrayList<T>();
for (T item : iter) {
result.add(item);
}
return result;
}
public static <T> ArrayList<T> toList(T... items) {
ArrayList<T> result = new ArrayList<T>(items.length);
for (T item : items) {
result.add(item);
}
return result;
}
public static <T> int count(Iterable<T> iter) {
int result = 0;
for (@SuppressWarnings("unused")
T item : iter) {
result++;
}
return result;
}
public static <T> Iterable<T> skip(final int n, final Iterable<T> iter) {
return new Iterable<T>() {
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<T> mIter = iter.iterator();
{
try {
for (int i = 0; i < n; i++) {
mIter.next();
}
} catch (NoSuchElementException e) {
}
}
public boolean hasNext() {
return mIter.hasNext();
}
public T next() {
return mIter.next();
}
public void remove() {
mIter.remove();
}
};
}
};
}
}

+ 93
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcClient.java View File

@ -0,0 +1,93 @@
package org.forks.jsonrpc;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public abstract class JsonRpcClient {
private final String mMethod;
private final static String LOG_TAG = "JsonRpcClient";
private long requestTime;
protected JsonRpcClient(String method) {
mMethod = method;
}
public final JsonRpcResult call(Object... args) throws JsonRpcException {
try {
JSONObject req = newRequest(args);
JSONObject res = request(req);
checkResponseId(req, res);
checkError(res);
return new JsonRpcResult(res.get("result"));
} catch (JSONException e) {
Log.w(LOG_TAG, "", e);
throw new JsonRpcException(e);
}
catch (JsonRpcException e){
throw e;
}
catch (Exception e){
throw new JsonRpcException(JsonRpcException.NETWORK_ERROR_CODE,e.getMessage());
}
}
private static void checkResponseId(JSONObject req, JSONObject res)
throws JSONException, JsonRpcException {
int reqId = req.getInt("id");
int resId = res.getInt("id");
if (reqId != resId) {
throw new JsonRpcException(String.format(
"response id (%d) does not match to request id (%d)",
reqId, resId));
}
}
private static void checkError(JSONObject res) throws JSONException,
JsonRpcException {
JSONObject err = res.optJSONObject("error");
if (err != null) {
int code = err.getInt("code");
String msg = err.getString("message");
String trace = err.optString("detail");
throw new JsonRpcException(code, msg, trace);
}
}
private JSONObject request(JSONObject req) throws JsonRpcException {
String json = req.toString();
log_request(json);
String jsonBack = doRequest(json);
log_response(jsonBack);
return Helper.parseJsonObject(jsonBack);
}
private void log_response(String jsonBack) {
long duration = System.currentTimeMillis() - requestTime;
Log.i(LOG_TAG, String.format("get response using %d ms, response: %s",
duration, jsonBack));
}
private void log_request(String reqJson) {
requestTime = System.currentTimeMillis();
Log.v(LOG_TAG, "start request: " + reqJson);
}
protected abstract String doRequest(String json) throws JsonRpcException;
private JSONObject newRequest(Object[] args) throws JSONException {
Object params = RpcTypeParser.toJson(args);
return newRequest(params);
}
private static int mIdSeed;
private JSONObject newRequest(Object params) throws JSONException {
JSONObject result = new JSONObject();
result.put("id", mIdSeed++);
result.put("method", mMethod);
result.put("params", params);
return result;
}
}

+ 51
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcException.java View File

@ -0,0 +1,51 @@
package org.forks.jsonrpc;
public final class JsonRpcException extends Exception {
public boolean isNetworkError(){
return mCode == NETWORK_ERROR_CODE;
}
static int NETWORK_ERROR_CODE = -1;
private static final long serialVersionUID = -3409287525569584913L;
private int mCode = 0;
private String mTrace;
public JsonRpcException() {
super();
}
public JsonRpcException(String message, Throwable throwable) {
super(message, throwable);
}
public JsonRpcException(String message) {
super(message);
}
public JsonRpcException(Throwable throwable) {
super(throwable);
}
public JsonRpcException(int code, String message) {
this(code, message, null);
}
public JsonRpcException(int code, String message, String trace) {
super(message);
mCode = code;
mTrace = trace;
}
public int getCode() {
return mCode;
}
public boolean is5xxError() {
return mCode >= 500 && mCode < 600;
}
public String getDetailMessage() {
return mTrace;
}
}

+ 179
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcResult.java View File

@ -0,0 +1,179 @@
package org.forks.jsonrpc;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
public final class JsonRpcResult {
private final Object mResult;
JsonRpcResult(Object result) {
super();
mResult = result;
}
public Object getRaw() {
return mResult;
}
public Integer getInt() {
return (Integer) RpcTypeParser.sInt.fromJson(mResult);
}
public String getString() {
return (String) RpcTypeParser.sString.fromJson(mResult);
}
public Short getShort() {
return (Short) RpcTypeParser.sShort.fromJson(mResult);
}
public Long getLong() {
return (Long) RpcTypeParser.sLong.fromJson(mResult);
}
public Short getByte() {
return (Short) RpcTypeParser.sByte.fromJson(mResult);
}
public Double getDouble() {
return (Double) RpcTypeParser.sDouble.fromJson(mResult);
}
public Boolean getBoolean() {
return (Boolean) RpcTypeParser.sBoolean.fromJson(mResult);
}
public BigDecimal getDecimal() {
return (BigDecimal) RpcTypeParser.sDecimal.fromJson(mResult);
}
public BigDecimal getMoney() {
return getDecimal();
}
public boolean isNull() {
return mResult == JSONObject.NULL;
}
public Date getDate() {
return (Date) RpcTypeParser.sDate.fromJson(mResult);
}
public RpcObject getRpcObject(String objPath) throws JsonRpcException {
return (RpcObject) RpcTypeParser.fromJson(mResult, objPath);
}
public DFDataTable getTable() {
return (DFDataTable) RpcTypeParser.sTable.fromJson(mResult);
}
public ManyList getManyList(String objPath) throws JsonRpcException {
return getByType("onetomany(" + objPath + ")");
}
public List<Integer> getIntList() throws JsonRpcException {
return getByType("[int]");
}
public List<Short> getShortList() throws JsonRpcException {
return getByType("[short]");
}
public List<Short> getByteList() throws JsonRpcException {
return getByType("[byte]");
}
public List<Long> getLongList() throws JsonRpcException {
return getByType("[long]");
}
public List<Boolean> getBooleanList() throws JsonRpcException {
return getByType("[bool]");
}
public List<Double> getDoubleList() throws JsonRpcException {
return getByType("[double]");
}
public List<String> getStringList() throws JsonRpcException {
return getByType("[str]");
}
public List<Date> getDateList() throws JsonRpcException {
return getByType("[datetime]");
}
public List<BigDecimal> getDecimalList() throws JsonRpcException {
return getByType("[decimal]");
}
public List<BigDecimal> getMoneyList() throws JsonRpcException {
return getByType("[money]");
}
public List<RpcObject> getRpcObjectList(String objPath)
throws JsonRpcException {
return getByType("[" + objPath + "]");
}
public Map<String, Integer> getIntMap() throws JsonRpcException {
return getByType("{str:int}");
}
public Map<String, Short> getByteMap() throws JsonRpcException {
return getByType("{str:byte}");
}
public Map<String, Short> getShortMap() throws JsonRpcException {
return getByType("{str:short}");
}
public Map<String, Long> getLongMap() throws JsonRpcException {
return getByType("{str:long}");
}
public Map<String, Boolean> getBooleanMap() throws JsonRpcException {
return getByType("{str:bool}");
}
public Map<String, Double> getDoubleMap() throws JsonRpcException {
return getByType("{str:double}");
}
public Map<String, String> getStringMap() throws JsonRpcException {
return getByType("{str:str}");
}
public Map<String, Date> getDateMap() throws JsonRpcException {
return getByType("{str:datetime}");
}
public Map<String, BigDecimal> getDecimalMap() throws JsonRpcException {
return getByType("{str:decimal}");
}
public Map<String, BigDecimal> getMoneyMap() throws JsonRpcException {
return getByType("{str:money}");
}
public Map<String, RpcObject> getRpcObjectMap(String objPath)
throws JsonRpcException {
return getByType("{str:" + objPath + "}");
}
private <T> T getByType(String rpcType) throws JsonRpcException {
RpcType type = RpcTypeParser.parse(rpcType);
return (T) type.fromJson(mResult);
}
JSONObject getJsonObject() {
if (isNull()) {
return null;
}
return (JSONObject) mResult;
}
}

+ 22
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcRuntimeException.java View File

@ -0,0 +1,22 @@
package org.forks.jsonrpc;
public class JsonRpcRuntimeException extends RuntimeException {
private static final long serialVersionUID = 4017156582402768366L;
public JsonRpcRuntimeException() {
}
public JsonRpcRuntimeException(String detailMessage) {
super(detailMessage);
}
public JsonRpcRuntimeException(Throwable throwable) {
super(throwable);
}
public JsonRpcRuntimeException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
}

+ 199
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/ManyList.java View File

@ -0,0 +1,199 @@
package org.forks.jsonrpc;
import java.util.ArrayList;
import java.util.Collection;
import android.util.Pair;
import org.json.JSONException;
import org.json.JSONObject;
@SuppressWarnings("serial")
public final class ManyList extends ArrayList<RpcObject> {
private final RpcObjectMeta mItemMeta;
private final ArrayList<RpcObject> mNewItems = new ArrayList<RpcObject>();
private final ArrayList<RpcObject> mDeletedItems = new ArrayList<RpcObject>();
public ManyList(RpcObjectMeta itemMeta) {
mItemMeta = itemMeta;
}
public static ManyList create(String itemObjectPath)
throws JsonRpcException {
return new ManyList(RpcObjectMeta.get(itemObjectPath));
}
@Override
public void add(int index, RpcObject object) {
checkMetaType(object);
addNew(object);
super.add(index, object);
}
@Override
public boolean add(RpcObject object) {
checkMetaType(object);
addNew(object);
return super.add(object);
}
@Override
public boolean addAll(Collection<? extends RpcObject> collection) {
checkMetaTypes(collection);
addNewObjects(collection);
return super.addAll(collection);
}
@Override
public boolean addAll(int location,
Collection<? extends RpcObject> collection) {
checkMetaTypes(collection);
addNewObjects(collection);
return super.addAll(location, collection);
}
@Override
public void clear() {
for (RpcObject item : this) {
addDeleted(item);
}
super.clear();
}
@Override
public RpcObject remove(int index) {
RpcObject result = super.remove(index);
addDeleted(result);
return result;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
for (int i = fromIndex; i < toIndex; i++) {
addDeleted(get(i));
}
super.removeRange(fromIndex, toIndex);
}
@Override
public boolean removeAll(Collection<?> collection) {
// it is too complex to test modify track, and rarely used
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> collection) {
// it is too complex to test modify track, and rarely used
throw new UnsupportedOperationException();
}
@Override
public RpcObject set(int index, RpcObject object) {
RpcObject result = super.set(index, object);
addDeleted(result);
addNew(object);
return result;
}
private void addNewObjects(Collection<? extends RpcObject> collection) {
for (RpcObject item : collection) {
addNew(item);
}
}
private void addNew(RpcObject object) {
if (!mDeletedItems.remove(object)) {
mNewItems.add(object);
}
}
private void addDeleted(RpcObject object) {
if (!mNewItems.remove(object)) {
mDeletedItems.add(object);
}
}
JSONObject toJson() throws JSONException {
JSONObject result = new JSONObject();
Pair<Collection<RpcObject>, Collection<RpcObject>> changedUnChanged = getChangedUnChangedItems();
putArrayField(result, "_data", changedUnChanged.second);
putArrayField(result, "_new", getNewItems());
putArrayField(result, "_deleted", getDeletedItems());
putArrayField(result, "_modified", changedUnChanged.first);
return result;
}
private static void putArrayField(JSONObject result, String fieldName,
Collection<RpcObject> list) throws JSONException {
if (!list.isEmpty()) {
result.put(fieldName, RpcTypeParser.toJson(list));
}
}
private void checkMetaTypes(Collection<? extends RpcObject> collection) {
if (!RpcFacade.sDebug) {
return;
}
for (RpcObject rpcObject : collection) {
checkMetaType(rpcObject);
}
}
private void checkMetaType(RpcObject object) {
if (!RpcFacade.sDebug) {
return;
}
RpcObjectMeta objMeta = object.getMeta();
if (objMeta != mItemMeta) {
throwMetaMisMatchError(objMeta);
}
}
private void throwMetaMisMatchError(RpcObjectMeta objMeta) {
String msg = "RpcObject %s can not add to %s ManyList";
msg = String.format(msg, objMeta.getName(), mItemMeta.getName());
throw new IllegalArgumentException(msg);
}
Collection<RpcObject> getNewItems() {
return mNewItems;
}
Collection<RpcObject> getDeletedItems() {
return mDeletedItems;
}
Pair<Collection<RpcObject>, Collection<RpcObject>>
getChangedUnChangedItems() {
ArrayList<RpcObject> changed = new ArrayList<RpcObject>();
ArrayList<RpcObject> unchanged = new ArrayList<RpcObject>();
for (RpcObject item : this) {
if (!isNewObject(item)) {
if (!item.isModified()) {
unchanged.add(item);
} else {
changed.add(item);
}
}
}
return new Pair<Collection<RpcObject>, Collection<RpcObject>>(changed,
unchanged);
}
void acceptChanges() {
mNewItems.clear();
mDeletedItems.clear();
for (RpcObject obj : this) {
obj.acceptChanges();
}
}
private boolean isNewObject(RpcObject item) {
return mNewItems.contains(item);
}
}

+ 66
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/NamedValue.java View File

@ -0,0 +1,66 @@
package org.forks.jsonrpc;
import java.util.HashMap;
import android.util.SparseArray;
public final class NamedValue {
private final short mValue;
private final String mName;
private NamedValue(short value, String name) {
super();
mValue = value;
mName = name;
}
public short getValue() {
return mValue;
}
public String getName() {
return mName;
}
@Override
public String toString() {
return getName();
}
private static final HashMap<String, SparseArray<NamedValue>> sInstancePool = new HashMap<String, SparseArray<NamedValue>>();
public static synchronized NamedValue create(String idtype, short val) {
SparseArray<NamedValue> array = sInstancePool.get(idtype);
if (array == null) {
array = createArray(idtype);
sInstancePool.put(idtype, array);
}
NamedValue result = array.get(val);
if (result == null) {
result = new NamedValue(val, Short.toString(val));
array.put(val, result);
}
return result;
}
private static SparseArray<NamedValue> createArray(String idtype) {
try {
SparseArray<String> pairs = NamedValueMeta.get(idtype);
SparseArray<NamedValue> result = new SparseArray<NamedValue>(
pairs.size());
for (int i = 0; i < pairs.size(); i++) {
int key = pairs.keyAt(i);
NamedValue v = new NamedValue((short) key, pairs.valueAt(i));
result.append(key, v);
}
return result;
} catch (JsonRpcException e) {
throw new JsonRpcRuntimeException(e);
}
}
static void reset() {
sInstancePool.clear();
}
}

+ 84
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/NamedValueMeta.java View File

@ -0,0 +1,84 @@
package org.forks.jsonrpc;
import java.util.HashMap;
import java.util.List;
import android.util.SparseArray;
import static org.forks.jsonrpc.RpcFacade.toFullErtPathByPrefixedErt;
public final class NamedValueMeta {
private static final String NAMED_VALUE_PAIR = "/sbin/NamedValuePair";
private static final String METHOD = "/sbin/NamedValue/GetDefinition";
private static final HashMap<String, SparseArray<String>> sCache = new HashMap<String, SparseArray<String>>();
public static final class Pair {
public final int Value;
public final String Name;
Pair(int value, String name) {
super();
Value = value;
Name = name;
}
}
public static final SparseArray<String> get(String idType)
throws JsonRpcException {
synchronized (sCache) {
SparseArray<String> result = sCache.get(idType);
if (result != null) {
return result;
}
}
SparseArray<String> result = doGet(idType);
synchronized (sCache) {
sCache.put(idType, result);
}
return result;
}
private static SparseArray<String> doGet(String idType)
throws JsonRpcException {
String methodPath = toFullErtPathByPrefixedErt(idType, METHOD);
String rpcPath = toFullErtPathByPrefixedErt(idType, NAMED_VALUE_PAIR);
JsonRpcResult res = RpcFacade.rpcCall(methodPath, idType);
List<RpcObject> pairs = res.getRpcObjectList(rpcPath);
return toNamedValueMap(pairs);
}
private static SparseArray<String> toNamedValueMap(List<RpcObject> pairs) {
SparseArray<String> result = new SparseArray<String>(pairs.size());
for (RpcObject pair : pairs) {
Integer key = pair.getInt("Value");
String value = pair.getString("Name");
result.put(key, value);
}
return result;
}
static void reset() {
sCache.clear();
}
static void register(String idType, SparseArray<String> names) {
sCache.put(idType, names);
}
public static String toName(Short val, String namedValueType)
throws JsonRpcException {
if (val == null) {
return "";
}
String idType = RpcTypeParser.getNamedValueTidType(namedValueType);
SparseArray<String> names = get(idType);
String result = names.get(val);
if (result == null) {
result = val.toString();
}
return result;
}
}

+ 22
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/NoSuchRpcPropertyException.java View File

@ -0,0 +1,22 @@
package org.forks.jsonrpc;
@SuppressWarnings("serial")
public final class NoSuchRpcPropertyException extends JsonRpcRuntimeException {
NoSuchRpcPropertyException() {
super();
}
NoSuchRpcPropertyException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
NoSuchRpcPropertyException(String detailMessage) {
super(detailMessage);
}
NoSuchRpcPropertyException(Throwable throwable) {
super(throwable);
}
}

+ 269
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/RpcFacade.java View File

@ -0,0 +1,269 @@
package org.forks.jsonrpc;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Build;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import org.apache.http.cookie.Cookie;
public final class RpcFacade {
private static final PreferenceMonitor PREFERENCE_MONITOR = new PreferenceMonitor();
public static final String SERVER_URI_PREFKEY = "ServerUri";
private static final String DEBUG_PREFKEY = "Debug";
private static final String TAG = "RpcFacade";
private static final String REST_URI = "";
private static String sRestUri = REST_URI;
private static Context sContext;
private static String sUsername = "";
private static String sPasswd;
private static final String LOGOUT_METHOD = "/MainSystem/MainSystem/Auth/Logout";
private static final String LOGIN_METHOD = "/MainSystem/MainSystem/Auth/Login";
static boolean sDebug = true;
// keep reference
@SuppressWarnings("unused")
private static KeepSession sKeepSession;
private RpcFacade() {
}
public static void syncCookie(WebView webView){
CookieSyncManager.createInstance(webView.getContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeAllCookie();
for(Cookie cookie:HttpJsonRpcClient.sCookieStore.getCookies()){
if(cookie.getName().equals("EasyAuth")) {
String cookieString = cookie.getName() + "=" + cookie.getValue() + "; path=" + cookie.getPath();
cookieManager.setCookie(RpcFacade.getServerUri(), cookieString);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.flush();
}
CookieSyncManager.getInstance().sync();
}
public static void init(Context context, String appName) {
Context appContext = context.getApplicationContext();
if (sContext == null) {
Log.v(TAG, "init RpcFacade, appname: " + appName);
sContext = appContext;
sKeepSession = new KeepSession();
HttpJsonRpcClient.sSetClientAppName(appName);
initPreference();
} else if (sContext != appContext) {
Log.v(TAG, "invalid reinit RpcFacade");
String message = "RpcFacade is inited, can not init again";
throw new JsonRpcRuntimeException(message);
}
}
public static void setServerUri(String uri){
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(sContext);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(SERVER_URI_PREFKEY,uri);
editor.commit();
}
public static boolean isInited() {
return sContext != null;
}
private static void initPreference() {
Log.d(TAG,
"restore settings from preference, monitor preference change");
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(sContext);
restoreDebugFromPref(prefs);
restoreServerUriFromPref(prefs);
// OnSharedPreferenceChangeListener is a weeked event,
// we must keep the event listener instance ourself
prefs.registerOnSharedPreferenceChangeListener(PREFERENCE_MONITOR);
}
public static JsonRpcResult rpcCall(String method, Object... args)
throws JsonRpcException {
try {
return doRpcCall(method, args);
} catch (JsonRpcException e) {
if (e.getCode() == 401 && isLogedIn()) {
autoLogin();
return doRpcCall(method, args);
}
throw e;
}
}
public static String getUsername() {
return sUsername;
}
public static void login(String user, String passwd)
throws JsonRpcException {
Log.i(TAG, "Start login: " + user);
callLogin(user, passwd);
sUsername = user;
sPasswd = passwd;
}
public static void restoreLogined(String username,String password){
sUsername = username;
sPasswd = password;
}
public static void logout() {
try {
if (isLogedIn()) {
Log.i(TAG, "logout user: " + sUsername);
sUsername = "";
doRpcCall(LOGOUT_METHOD);
}
} catch (JsonRpcException e) {
}
}
private static void autoLogin() throws JsonRpcException {
String user = sUsername;
String pwd = sPasswd;
if (user.length() > 0) {
callLogin(user, pwd);
}
}
private static JsonRpcResult doRpcCall(String method, Object... args)
throws JsonRpcException {
JsonRpcClient client = new HttpJsonRpcClient(getRestUri(method), method);
return client.call(args);
}
private static void callLogin(String user, String passwd)
throws JsonRpcException {
doRpcCall(LOGIN_METHOD, user, passwd);
}
private static String getRestUri(String method) {
StringBuilder sb = new StringBuilder();
appendServerUri(sb);
String subSystem = getSystem(method);
if (!IsMainSystem(subSystem)) {
appendSubSystem(sb, subSystem);
}
sb.append("Rest.aspx");
return sb.toString();
}
private static boolean IsMainSystem(String subSystem) {
return subSystem.equals("MainSystem");
}
private static void appendSubSystem(StringBuilder sb, String subSystem) {
sb.append("O/");
sb.append(subSystem);
sb.append('/');
}
private static void appendServerUri(StringBuilder sb) {
String serverUri = getServerUri();
if (serverUri.charAt(serverUri.length() - 1) != '/') {
sb.append('/');
}
sb.append(serverUri);
}
public static String getServerUri() {
return sRestUri;
}
static String getSystem(String method) {
int endIdx = method.indexOf('/', 1);
return method.substring(1, endIdx);
}
public static String toFullErtPathByPrefixedErt(String objPath,
String subMethodPath) {
String subSystem = getSystem(objPath);
return "/" + subSystem + subMethodPath;
}
public static boolean isLogedIn() {
return sUsername.length() > 0;
}
private static void restoreServerUriFromPref(SharedPreferences pref) {
sRestUri = pref.getString(SERVER_URI_PREFKEY, REST_URI);
Log.d(TAG, "get serverUri from preference: " + sRestUri);
}
private static void restoreDebugFromPref(SharedPreferences pref) {
sDebug = pref.getBoolean(DEBUG_PREFKEY, true);
Log.d(TAG, "get debug mode from preference: " + sDebug);
}
private static class KeepSession implements Runnable {
private static Handler handler;
public KeepSession() {
if (handler != null) {
throw new RuntimeException("More than one instance?");
}
handler = new Handler();
startAgain();
}
public void run() {
if (isLogedIn()) {
Log.i(TAG, "connecting to server to maintain session");
try {
heartBeat();
} catch (Exception e) {
Log.w(TAG, e.toString());
}
} else {
Log.i(TAG, "no need to connect server, not logged in");
}
startAgain();
}
private static void heartBeat() throws JsonRpcException {
// use auto login, because the cell phone maybe just awake after
// sleep, and server is kick the user out because of not activity
// in 2 minutes.
rpcCall("/MainSystem/MainSystem/Auth/Ping");
}
private void startAgain() {
handler.postDelayed(this, 60 * 1000);
}
}
private static final class PreferenceMonitor implements
OnSharedPreferenceChangeListener {
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "preference changed, key: " + key);
if (key.equals(DEBUG_PREFKEY)) {
restoreDebugFromPref(sharedPreferences);
} else if (key.equals(SERVER_URI_PREFKEY)) {
restoreServerUriFromPref(sharedPreferences);
}
}
}
}

+ 386
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/RpcObject.java View File

@ -0,0 +1,386 @@
package org.forks.jsonrpc;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@SuppressWarnings("serial")
public final class RpcObject extends HashMap<String, Object> {
private final RpcObjectMeta mMeta;
private HashMap<String, Object> mBackup;
RpcObject(RpcObjectMeta meta) throws JsonRpcException {
super();
mMeta = meta;
initValueStore(mMeta.getProps());
acceptChanges();
}
public final static RpcObject create(String objPath)
throws JsonRpcException {
return new RpcObject(RpcObjectMeta.get(objPath));
}
public RpcObjectMeta getMeta() {
return mMeta;
}
public Short getByte(String propName) {
return (Short) get(propName, RpcTypeParser.BYTE);
}
public void setByte(String propName, Short value) {
set(propName, value, RpcTypeParser.BYTE);
}
public Integer getInt(String propName) {
return (Integer) get(propName, RpcTypeParser.INT);
}
public void setInt(String propName, Integer value) {
set(propName, value, RpcTypeParser.INT);
}
public Short getShort(String propName) {
return (Short) get(propName, RpcTypeParser.SHORT);
}
public void setShort(String propName, Short value) {
set(propName, value, RpcTypeParser.SHORT);
}
public Long getLong(String propName) {
return (Long) get(propName, RpcTypeParser.LONG);
}
public void setLong(String propName, Long value) {
set(propName, value, RpcTypeParser.LONG);
}
public Double getDouble(String propName) {
return (Double) get(propName, RpcTypeParser.DOUBLE);
}
public void setDouble(String propName, Double value) {
set(propName, value, RpcTypeParser.DOUBLE);
}
public BigDecimal getDecimal(String propName) {
return (BigDecimal) get(propName, RpcTypeParser.DECIMAL);
}
public void setDecimal(String propName, BigDecimal value) {
set(propName, value, RpcTypeParser.DECIMAL);
}
public BigDecimal getMoney(String propName) {
return (BigDecimal) get(propName, RpcTypeParser.MONEY);
}
public void setMoney(String propName, BigDecimal value) {
set(propName, value, RpcTypeParser.MONEY);
}
public Date getDate(String propName) {
return (Date) get(propName, RpcTypeParser.DATE);
}
public void setDate(String propName, Date value) {
set(propName, value, RpcTypeParser.DATE);
}
public String getString(String propName) {
return (String) get(propName, RpcTypeParser.STRING);
}
public String getGuid(String propName){
return (String)get(propName,RpcTypeParser.GUID);
}
public void setString(String propName, String value) {
set(propName, value, RpcTypeParser.STRING);
}
public Integer getLookupValue(String propName) {
return (Integer) get(propName, RpcTypeParser.LOOKUPVALUE);
}
public void setLookupValue(String propName, Integer value) {
set(propName, value, RpcTypeParser.LOOKUPVALUE);
}
public NamedValue getNamedValue(String propName) {
checkNamedValueProp(propName);
return (NamedValue) get(propName);
}
public void setNamedValue(String propName, Short value) {
NamedValue val = toNamedValue(propName, value);
setNamedValue(propName, val);
}
private NamedValue toNamedValue(String propName, Short value) {
if (value == null) {
return null;
}
RpcPropertyMeta prop = getPropertyMeta(propName);
String idtype = RpcTypeParser.getNamedValueTidType(prop.getType());
return NamedValue.create(idtype, value);
}
public void setNamedValue(String propName, NamedValue value) {
checkNamedValueProp(propName);
put(propName, value);
}
public Long getEntityKey(String propName) {
return (Long) get(propName, RpcTypeParser.ENTITYKEY);
}
public void setEntityKey(String propName, Long value) {
set(propName, value, RpcTypeParser.ENTITYKEY);
}
private void initValueStore(Map<String, RpcPropertyMeta> props)
throws JsonRpcException {
for (RpcPropertyMeta prop : props.values()) {
put(prop.getName(), createDefaultValue(prop));
}
}
private static Object createDefaultValue(RpcPropertyMeta prop)
throws JsonRpcException {
if (RpcTypeParser.isManyList(prop.getType())) {
return createManyList(prop);
} else if (RpcTypeParser.isList(prop.getType())) {
return new ArrayList<Object>();
} else if (RpcTypeParser.isMap(prop.getType())) {
return new HashMap<Object, Object>();
}
return prop.getDefaultValue();
}
private static ManyList createManyList(RpcPropertyMeta prop)
throws JsonRpcException {
return ManyList
.create(RpcTypeParser.getManyListItemType(prop.getType()));
}
private void set(String propName, Object value, String type) {
isPropDefined(propName, type);
put(propName, value);
}
private Object get(String propName, String type) {
isPropDefined(propName, type);
return get(propName);
}
private void isPropDefined(String propName, String type) {
if (RpcFacade.sDebug) {
RpcPropertyMeta prop = getPropertyMeta(propName);
checkPropertyType(type, prop);
}
}
private RpcPropertyMeta getPropertyMeta(String propName) {
RpcPropertyMeta prop = mMeta.getProps().get(propName);
if (prop == null) {
throw new NoSuchRpcPropertyException(propName);
}
return prop;
}
public Boolean getBoolean(String propName) {
return (Boolean) get(propName, RpcTypeParser.BOOL);
}
public void setBoolean(String propName, Boolean value) {
set(propName, value, RpcTypeParser.BOOL);
}
public ManyList getManyList(String propName) {
if (RpcFacade.sDebug) {
checkManyListProp(propName);
}
return (ManyList) get(propName);
}
public <T> List<T> getList(String propName) {
if (RpcFacade.sDebug) {
checkListProp(propName);
}
return (List<T>) get(propName);
}
public <K, V> Map<K, V> getMap(String propName) {
if (RpcFacade.sDebug) {
checkMapProp(propName);
}
return (Map<K, V>) get(propName);
}
public RpcObject getRpcObject(String propName) throws JsonRpcException {
checkRpcObjectType(propName, null);
return (RpcObject) get(propName);
}
public void setRpcObject(String propName, RpcObject value)
throws JsonRpcException {
checkRpcObjectType(propName, value);
put(propName, value);
}
private void checkPropertyType(String type, RpcPropertyMeta prop) {
if (!prop.getType().equals(type)) {
String msg = String.format(
"Type: %s, prop: %s, prop type: %s, access type: %s",
mMeta.getName(), prop.getName(), prop.getType(), type);
throw new InvalidPropertyValueException(msg);
}
}
private void checkListProp(String propName) {
RpcPropertyMeta propMeta = getPropertyMeta(propName);
if (!RpcTypeParser.isList(propMeta.getType())) {
String pattern = "Property '%s' is '%s', not List";
String message = String.format(pattern, propName,
propMeta.getType());
throw new InvalidPropertyValueException(message);
}
}
private void checkMapProp(String propName) {
RpcPropertyMeta propMeta = getPropertyMeta(propName);
if (!RpcTypeParser.isMap(propMeta.getType())) {
String pattern = "Property '%s' is '%s', not Map";
String message = String.format(pattern, propName,
propMeta.getType());
throw new InvalidPropertyValueException(message);
}
}
private void checkManyListProp(String propName) {
RpcPropertyMeta propMeta = getPropertyMeta(propName);
if (!RpcTypeParser.isManyList(propMeta.getType())) {
String pattern = "Property '%s' is '%s', not ManyList";
String message = String.format(pattern, propName,
propMeta.getType());
throw new InvalidPropertyValueException(message);
}
}
private void checkRpcObjectType(String propName, RpcObject value)
throws JsonRpcException {
if (!RpcFacade.sDebug) {
return;
}
RpcPropertyMeta prop = getPropertyMeta(propName);
String propPath = prop.getType();
if (!RpcTypeParser.isRpcObject(propPath)) {
String pattern = "Property '%s' is '%s', not rpc object";
String message = String.format(pattern, propName, propPath);
throw new InvalidPropertyValueException(message);
}
RpcObjectMeta propMeta = RpcObjectMeta.get(propPath);
if (value != null && propMeta != value.mMeta) {
String pattern = "Property '%s' only accept object '%s'";
String message = String.format(pattern, propName, propPath);
throw new InvalidPropertyValueException(message);
}
}
private void checkNamedValueProp(String propName) {
RpcPropertyMeta prop = getPropertyMeta(propName);
if (!RpcTypeParser.isNamedValue(prop.getType())) {
String msg = String.format(
"Type: %s, prop: %s, prop type: %s, is not namedvalue",
mMeta.getName(), prop.getName(), prop.getType());
throw new InvalidPropertyValueException(msg);
}
}
static RpcObject create(RpcObjectMeta meta, JSONArray tableRow)
throws JsonRpcException {
RpcObject result = new RpcObject(meta);
// must be LinkedHashMap<> because we rely on the value order
LinkedHashMap<String, RpcPropertyMeta> props = (LinkedHashMap<String, RpcPropertyMeta>) meta
.getProps();
int i = 0;
for (RpcPropertyMeta prop : props.values()) {
String name = prop.getName();
Object value = Helper.get(tableRow, i);
if (value != null) {
value = RpcTypeParser.fromJson(value, prop.getType());
}
result.put(name, value);
i++;
}
result.acceptChanges();
return result;
}
JSONObject toJson() throws JSONException {
JSONObject result = new JSONObject();
for (Entry<String, Object> entry : entrySet()) {
RpcPropertyMeta prop = mMeta.getProps().get(entry.getKey());
Object value = entry.getValue();
if (!equalToDefaultValue(prop, value)) {
value = RpcTypeParser.toJson(value);
result.put(entry.getKey(), value);
}
}
return result;
}
void acceptChanges() {
mBackup = new HashMap<String, Object>(this);
for (RpcPropertyMeta prop : mMeta.getProps().values()) {
if (RpcTypeParser.isManyList(prop.getType())) {
getManyList(prop.getName()).acceptChanges();
}
}
}
boolean isModified() {
return !super.equals(mBackup);
}
@Override
public boolean equals(Object object) {
return object == this;
}
@Override
public int hashCode() {
return super.hashCode();
}
private static boolean equalToDefaultValue(RpcPropertyMeta prop,
Object value) {
Object defaultValue = prop.getDefaultValue();
if (defaultValue == value) {
return true;
}
if (defaultValue != null) {
return defaultValue.equals(value);
}
return false;
}
}

+ 75
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/RpcObjectMeta.java View File

@ -0,0 +1,75 @@
package org.forks.jsonrpc;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONObject;
import static org.forks.jsonrpc.Helper.*;
import static org.forks.jsonrpc.RpcFacade.rpcCall;
public final class RpcObjectMeta {
private final String mName;
private final Map<String, RpcPropertyMeta> mProps;
public RpcObjectMeta(String name, Map<String, RpcPropertyMeta> props) {
super();
mName = name;
mProps = props;
}
public String getName() {
return mName;
}
public Map<String, RpcPropertyMeta> getProps() {
return mProps;
}
public static RpcObjectMeta parse(JSONObject jsonObj)
throws JsonRpcException {
String name = getString(jsonObj, "name");
JSONArray propsJson = getJsonArray(jsonObj, "props");
Map<String, RpcPropertyMeta> props = RpcPropertyMeta.parse(propsJson);
return new RpcObjectMeta(name, props);
}
private static Map<String, RpcObjectMeta> sCache = new HashMap<String, RpcObjectMeta>();
public static RpcObjectMeta get(String objPath) throws JsonRpcException {
RpcObjectMeta result;
synchronized (sCache) {
result = sCache.get(objPath);
if (result != null) {
return result;
}
}
result = getFromServer(objPath);
synchronized (sCache) {
sCache.put(objPath, result);
}
return result;
}
private static RpcObjectMeta getFromServer(String objPath)
throws JsonRpcException {
String getMethod = "/sbin/ObjectMeta/Get";
String method = RpcFacade.toFullErtPathByPrefixedErt(objPath, getMethod);
JsonRpcResult result = rpcCall(method, objPath);
return parse(result.getJsonObject());
}
// only used in unit test
static void registerMeta(String objPath, RpcObjectMeta meta) {
if (sCache.put(objPath, meta) != null) {
throw new JsonRpcRuntimeException(objPath);
}
}
static void reset() {
sCache.clear();
}
}

+ 61
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/RpcPropertyMeta.java View File

@ -0,0 +1,61 @@
package org.forks.jsonrpc;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONObject;
import static org.forks.jsonrpc.Helper.*;
public final class RpcPropertyMeta {
private final String mName;
private final String mType;
private final Object mDefaultValue;
public RpcPropertyMeta(String name, String type, Object defaultValue) {
super();
mName = name;
mType = type;
mDefaultValue = defaultValue;
}
public String getName() {
return mName;
}
public String getType() {
return mType;
}
public Object getDefaultValue() {
return mDefaultValue;
}
static Map<String, RpcPropertyMeta> parse(JSONArray arr)
throws JsonRpcException {
Map<String, RpcPropertyMeta> result = new HashMap<String, RpcPropertyMeta>(
arr.length());
return parse(result, arr);
}
static Map<String, RpcPropertyMeta> parse(
Map<String, RpcPropertyMeta> result, JSONArray arr)
throws JsonRpcException {
for (int i = 0; i < arr.length(); i++) {
JSONObject item = getJsonObject(arr, i);
RpcPropertyMeta prop = parse(item);
result.put(prop.getName(), prop);
}
return result;
}
private static RpcPropertyMeta parse(JSONObject json)
throws JsonRpcException {
String name = getString(json, "name");
String type = getString(json, "type");
Object defaultValue = json.opt("defaultvalue");
defaultValue = RpcTypeParser.fromJson(defaultValue, type);
return new RpcPropertyMeta(name, type, defaultValue);
}
}

+ 5
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/RpcType.java View File

@ -0,0 +1,5 @@
package org.forks.jsonrpc;
interface RpcType {
Object fromJson(Object jsonValue);
}

+ 557
- 0
jsonrpc/src/main/java/org/forks/jsonrpc/RpcTypeParser.java View File

@ -0,0 +1,557 @@
package org.forks.jsonrpc;
import static org.forks.jsonrpc.Helper.getJsonObject;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public final class RpcTypeParser {
static final String BYTE = "byte";
static final String SHORT = "short";
static final String INT = "int";
static final String LONG = "long";
static final String BOOL = "bool";
static final String DOUBLE = "double";
static final String SINGLE = "single";
static final String DECIMAL = "decimal";
static final String DATE = "datetime";
static final String STRING = "str";
static final String GUID = "guid";
static final String BIN = "bin";
static final String MONEY = "money";
static final String LOOKUPVALUE = "lookup";
static final String ENTITYKEY = "entitykey";
static final String TABLE = "table";
public static boolean isManyList(String rpcType) {
return rpcType.startsWith("onetomany(") && rpcType.endsWith(")");
}
public static String getManyListItemType(String rpcType) {
return rpcType.substring("onetomany(".length(), rpcType.indexOf(')'));
}
public static boolean isList(String rpcType) {
return startWith(rpcType, '[');
}
public static boolean isMap(String rpcType) {
return startWith(rpcType, '{');
}
public static boolean isRpcObject(String rpcType) {
return startWith(rpcType, '/');
}
public static boolean isNamedValue(String rpcType) {
return rpcType.startsWith("namedvalue(") && rpcType.endsWith(")");
}
public static String getNamedValueTidType(String rpcType) {
return rpcType.substring("namedvalue(".length(), rpcType.length() - 1);
}
private static boolean startWith(String s, char ch) {
return s.length() != 0 && s.charAt(0) == ch;
}
public static String getMapValueType(String rpcType) {
int start = rpcType.indexOf(':');
return rpcType.substring(start + 1, rpcType.length() - 1);
}
public static String getListItemType(String rpcType) {
return rpcType.substring(1, rpcType.length() - 1);
}
public static Object fromJson(Object jsonValue, String rpcType)
throws JsonRpcException {
if (isNull(jsonValue)) {
return null;
}
RpcType type = parse(rpcType);
return type.fromJson(jsonValue);
}
public static Object toJson(Object value) throws JSONException {
if (value == null) {
return JSONObject.NULL;
} else if (value instanceof Date) {
return dateToJson((Date) value);
} else if (value instanceof RpcObject) {
return ((RpcObject) value).toJson();
} else if (value instanceof ManyList) {
return ((ManyList) value).toJson();
} else if (value instanceof List<?>) {
return listToJson((List<?>) value);
} else if (value.getClass().isArray()) {
return arrayToJson(value);
} else if (value instanceof Map<?, ?>) {
return mapToJson((Map<?, ?>) value);
} else if (value instanceof NamedValue) {
return namedValueToJson((NamedValue) value);
} else {
return value;
}
}
private static Object namedValueToJson(NamedValue value) {
return value.getValue();
}
private static Object mapToJson(Map<?, ?> map) throws JSONException {
JSONObject result = new JSONObject();
for (Entry<?, ?> entry : map.entrySet()) {
Object value = entry.getValue();
value = toJson(value);
result.put((String) entry.getKey(), value);
}
return result;
}
private static Object listToJson(List<?> coll) throws JSONException {
JSONArray result = new JSONArray();
for (Object item : coll) {
item = toJson(item);
result.put(item);
}
return result;
}
private static Object arrayToJson(Object array) throws JSONException {
JSONArray result = new JSONArray();
int len = Array.getLength(array);
for (int i = 0; i < len; i++) {
Object item = Array.get(array, i);
item = toJson(item);
result.put(item);
}
return result;
}
private static Object dateToJson(Date val) {
return String.format("/Date(%tQ+0800)/", val);
}
synchronized static final RpcType parse(String rpcType)
throws JsonRpcException {
RpcType result = sRpcTypeCache.get(rpcType);
if (result == null) {
result = doParse(rpcType);
sRpcTypeCache.put(rpcType, result);
}
return result;
}
static final boolean isNull(Object jsonObj) {
return jsonObj == null || jsonObj == JSONObject.NULL;
}
private static final Map<String, RpcType> sRpcTypeCache = new HashMap<String, RpcType>();
private static RpcType doParse(String rpcType) throws JsonRpcException {
if (rpcType.equals(BOOL)) {
return sBoolean;
} else if (rpcType.equals(BYTE)) {
return sByte;
} else if (rpcType.equals(SHORT)) {
return sShort;
} else if (rpcType.equals(INT)) {
return sInt;
} else if (rpcType.equals(LONG)) {
return sLong;
} else if (rpcType.equals(SINGLE)) {
return sDouble;
} else if (rpcType.equals(DOUBLE)) {
return sDouble;
} else if (rpcType.equals(STRING)) {
return sString;
} else if(rpcType.equals(GUID)){
return sString;
} else if (rpcType.equals(BIN)){
return sString;
}
else if (rpcType.equals(DECIMAL)) {
return sDecimal;
} else if (rpcType.equals(DATE)) {
return sDate;
} else if (rpcType.equals(MONEY)) {
return sDecimal;
} else if (rpcType.equals(LOOKUPVALUE)) {
return sInt;
} else if (isNamedValue(rpcType)) {
return new RpcTypeNullWrap(new NamedValueRpcType(rpcType));
} else if (rpcType.equals(ENTITYKEY)) {
return sLong;
} else if (isList(rpcType)) {
return new RpcTypeNullWrap(new ListRpcType(rpcType));
} else if (isRpcObject(rpcType)) {
RpcObjectMeta meta = RpcObjectMeta.get(rpcType);
return new RpcTypeNullWrap(new RpcObjectRpcType(meta));
} else if (isMap(rpcType)) {
return new RpcTypeNullWrap(new MapRpcType(rpcType));
} else if (isManyList(rpcType)) {
return new RpcTypeNullWrap(new ManyListRpcType(rpcType));
} else if (rpcType.equals(TABLE)) {
return sTable;
} else {
throw new JsonRpcException("Unknown rpc type '" + rpcType + "'");
}
}
private static final RpcType sDirect = new RpcTypeNullWrap(
new DirectRpcType());
static final RpcType sInt = sDirect;
static final RpcType sBoolean = sDirect;
static final RpcType sShort = new RpcTypeNullWrap(new ShortRpcType());
static final RpcType sByte = new RpcTypeNullWrap(new ByteRpcType());
static final RpcType sLong = new RpcTypeNullWrap(new LongRpcType());
static final RpcType sDouble = new RpcTypeNullWrap(new DoubleRpcType());
static final RpcType sString = sDirect;
static final RpcType sDecimal = new RpcTypeNullWrap(new DecimalRpcType());
static final RpcType sDate = new RpcTypeNullWrap(new DateRpcType());
static final RpcType sTable = new RpcTypeNullWrap(new TableRpcType());
static final void reset() {
sRpcTypeCache.clear();
}
private static final class NamedValueRpcType implements RpcType {
private final String mIdtype;
public NamedValueRpcType(String rpcType) {
mIdtype = getNamedValueTidType(rpcType);
}
public Object fromJson(Object jsonValue) {
Short val = (Short) sShort.fromJson(jsonValue);
return NamedValue.create(mIdtype, val);
}
}
private static final class TableRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
try {
JSONObject obj = (JSONObject) jsonValue;
Map<String, RpcPropertyMeta> cols = getTableColumns(obj);
RpcObjectMeta meta = new RpcObjectMeta("table", cols);
ArrayList<RpcObject> rows = getTableRows(obj, meta);
RpcObject sumRow = getTableSumRow(obj, meta);
return new DFDataTable(cols, rows, sumRow);
} catch (JsonRpcException e) {
throw new JsonRpcRuntimeException(e);
}
}
private static Map<String, RpcPropertyMeta> getTableColumns(
JSONObject obj) throws JsonRpcException {
Map<String, RpcPropertyMeta> cols;
JSONArray meta = obj.optJSONArray("_meta");
if (meta != null) {
cols = parseTableCols(meta);
} else {
cols = new HashMap<String, RpcPropertyMeta>();
}
return cols;
}
private static ArrayList<RpcObject> getTableRows(JSONObject obj,
RpcObjectMeta rpcObjectMeta) throws JsonRpcException {
ArrayList<RpcObject> rows;
JSONArray rowsJson = obj.optJSONArray("rows");
if (rowsJson == null) {
rows = new ArrayList<RpcObject>();
} else {
rows = doGetTableRows(rowsJson, rpcObjectMeta);
}
return rows;
}
private static RpcObject getTableSumRow(JSONObject obj,
RpcObjectMeta meta) throws JsonRpcException {
RpcObject sumRow = null;
JSONArray sumRowJson = obj.optJSONArray("sumrow");
if (sumRowJson != null) {
sumRow = RpcObject.create(meta, sumRowJson);
}
return sumRow;
}
private static ArrayList<RpcObject> doGetTableRows(JSONArray rows,
RpcObjectMeta meta) throws JsonRpcException {
ArrayList<RpcObject> result = new ArrayList<RpcObject>(
rows.length());
for (int i = 0; i < rows.length(); i++) {
result.add(RpcObject.create(meta, Helper.getJsonArray(rows, i)));
}
return result;
}
private static Map<String, RpcPropertyMeta> parseTableCols(
JSONArray _meta) throws JsonRpcException {
// use LinkedHashMap to maintain column order
Map<String, RpcPropertyMeta> result = new LinkedHashMap<String, RpcPropertyMeta>(
_meta.length());
return RpcPropertyMeta.parse(result, _meta);
}
}
private static final class MapRpcType implements RpcType {
private final RpcType mValueType;
public MapRpcType(String rpcType) throws JsonRpcException {
checkMapKeyType(rpcType);
String valueType = getMapValueType(rpcType);
mValueType = parse(valueType);
}
public Object fromJson(Object jsonValue) {
JSONObject obj = (JSONObject) jsonValue;
Map<Object, Object> result = new HashMap<Object, Object>(
obj.length());
Iterator<String> iter = obj.keys();
while (iter.hasNext()) {
String key = iter.next();
Object value;
try {
value = Helper.get(obj, key);
} catch (JsonRpcException e) {
throw new JsonRpcRuntimeException(e);
}
if (RpcTypeParser.isNull(value)) {
result.put(key, null);
} else {
result.put(key, mValueType.fromJson(value));
}
}
return result;
}
private static void checkMapKeyType(String rpcType) {
String keyType = getMapKeyType(rpcType);
if (!keyType.equals(STRING)) {
String message = "jsonrpc android client only support `str' map key. "
+ rpcType;
throw new JsonRpcRuntimeException(message);
}
}
private static String getMapKeyType(String rpcType) {
int end = rpcType.indexOf(':');
return rpcType.substring(1, end);
}
}
private static final class RpcTypeNullWrap implements RpcType {
private final RpcType mInner;
public RpcTypeNullWrap(RpcType inner) {
mInner = inner;
}
public Object fromJson(Object jsonValue) {
if (jsonValue == JSONObject.NULL) {
return null;
}
return mInner.fromJson(jsonValue);
}
}
private static final class ManyListRpcType implements RpcType {
private final RpcObjectMeta mItemMeta;
private final RpcType mItemType;
public ManyListRpcType(String rpcType) throws JsonRpcException {
String itemRpcType = getManyListItemType(rpcType);
mItemType = parse(itemRpcType);
mItemMeta = RpcObjectMeta.get(itemRpcType);
}
public Object fromJson(Object jsonValue) {
try {
ManyList result = new ManyList(mItemMeta);
restoreFromJson((JSONObject) jsonValue, result);
return result;
} catch (JsonRpcException e) {
throw new JsonRpcRuntimeException(e);
}
}
private void restoreFromJson(JSONObject json, ManyList result)
throws JsonRpcException {
JSONArray _data = json.optJSONArray("_data");
if (_data != null && _data.length() != 0) {
fromJson(result, _data);
}
}
private void fromJson(ManyList result, JSONArray _data)
throws JsonRpcException {
for (int i = 0; i < _data.length(); i++) {
JSONObject itemJson = getJsonObject(_data, i);
RpcObject item = (RpcObject) mItemType.fromJson(itemJson);
result.add(item);
}
result.acceptChanges();
}
}
private static final class DirectRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
return jsonValue;
}
}
private static final class LongRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
if (jsonValue instanceof Long) {
return jsonValue;
}
return ((Integer) jsonValue).longValue();
}
}
private static final class ShortRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
return ((Integer) jsonValue).shortValue();
}
}
private static final class ByteRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
short result = ((Integer) jsonValue).shortValue();
if (result > 255 || result < 0) {
throw new JsonRpcRuntimeException("can not cast value "
+ result + " to dotnet byte type");
}
return result;
}
}
private static final class DoubleRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
if (jsonValue instanceof Double) {
return jsonValue;
}
return ((Number) jsonValue).doubleValue();
}
}
private static final class DecimalRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
return new BigDecimal(jsonValue.toString());
}
}
private static final class ListRpcType implements RpcType {
private final RpcType mItemType;
public ListRpcType(String rpcType) throws JsonRpcException {
String itemRpcType = getListItemType(rpcType);
mItemType = parse(itemRpcType);
}
public Object fromJson(Object jsonValue) {
JSONArray json = (JSONArray) jsonValue;
List<Object> result = new ArrayList<Object>(json.length());
for (int i = 0; i < json.length(); i++) {
Object itemJson;
try {
itemJson = Helper.get(json, i);
} catch (JsonRpcException e) {
throw new JsonRpcRuntimeException(e);
}
result.add(mItemType.fromJson(itemJson));
}
return result;
}
}
private static final class RpcObjectRpcType implements RpcType {
private final RpcObjectMeta mMeta;
public RpcObjectRpcType(RpcObjectMeta meta) {
mMeta = meta;
}
public Object fromJson(Object jsonValue) {
try {
JSONObject json = (JSONObject) jsonValue;
RpcObject result = new RpcObject(mMeta);
for (RpcPropertyMeta prop : mMeta.getProps().values()) {
String name = prop.getName();
Object value = json.opt(name);
if (value != null) {
result.put(name,
RpcTypeParser.fromJson(value, prop.getType()));
} else if (json.has(name)) {
result.put(name, null);
}
}
result.acceptChanges();
return result;
} catch (JsonRpcException e) {
throw new JsonRpcRuntimeException(e);
}
}
}
private static final class DateRpcType implements RpcType {
public Object fromJson(Object jsonValue) {
String s = (String) jsonValue;
if (!RpcFacade.sDebug || isDateString(s)) {
return new Date(parseMillsSinceEpoch(s));
}
String message = "can not convert '" + s + "' to Date";
throw new JsonRpcRuntimeException(message);
}
private static boolean isDateString(String s) {
return s.startsWith("/Date(") && s.endsWith("+0800)/");
}
private static final long parseMillsSinceEpoch(String s) {
int endIdx = s.indexOf('+');
String numStr = s.substring(6, endIdx);
return Long.parseLong(numStr);
}
}
}

+ 3
- 0
jsonrpc/src/main/res/values/strings.xml View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">jsonrpc</string>
</resources>

+ 15
- 0
jsonrpc/src/test/java/org/forks/jsonrpc/ExampleUnitTest.java View File

@ -0,0 +1,15 @@
package org.forks.jsonrpc;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}

+ 1
- 0
settings.gradle View File

@ -0,0 +1 @@
include ':app', ':jsonrpc'

Loading…
Cancel
Save