diff --git a/README.md b/README.md index bb8ddbf..f96be62 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is a demo app to control the ESP device which run [BluFi](https://github.co - See [doc](doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__en.md) ## Release APKS -- See [releases](https://github.com/EspressifApp/EspRelease/tree/master/EspBlufi) +- See [releases](https://github.com/EspressifApp/EspBlufiForAndroid/releases) ## Update Log - See [Log](log/updatelog-en.md) diff --git a/app/build.gradle b/app/build.gradle index 3087a09..a8213e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,14 +1,14 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "com.espressif.espblufi" minSdkVersion 18 - targetSdkVersion 28 - versionCode 19 - versionName "1.4.2" + targetSdkVersion 29 + versionCode 20 + versionName "1.4.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -26,13 +26,15 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' + implementation 'androidx.preference:preference:1.1.0' - implementation 'io.reactivex.rxjava2:rxjava:2.2.8' + implementation 'io.reactivex.rxjava2:rxjava:2.2.12' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' + implementation 'xxj.phiman:xxjtools:1.0.1' + implementation project(':blufilibrary') - implementation project(':apptools') } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b30566d..06f477e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,7 +8,6 @@ - newSet = new HashSet<>(); + for (Object object : set) { + newSet.add((String)object); } - editor.putStringSet(key, (Set)set); + editor.putStringSet(key, newSet); } else { return false; } @@ -101,6 +78,7 @@ public Object settingsGet(String key, Object defaultValue) { } else if (defaultValue instanceof Long) { return mSettingsShared.getLong(key, (Long) defaultValue); } else if (defaultValue instanceof Set) { + //noinspection unchecked return mSettingsShared.getStringSet(key, (Set) defaultValue); } else { return null; diff --git a/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java b/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java index d0b72e6..25bd4e8 100644 --- a/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java +++ b/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java @@ -8,6 +8,7 @@ import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.graphics.Color; +import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -39,13 +40,12 @@ import blufi.espressif.response.BlufiScanResult; import blufi.espressif.response.BlufiStatusResponse; import blufi.espressif.response.BlufiVersionResponse; -import libs.espressif.app.SdkUtil; -import libs.espressif.log.EspLog; +import tools.xxj.phiman.log.XxjLog; public class BlufiActivity extends BaseActivity { private static final int REQUEST_CONFIGURE = 0x20; - private final EspLog mLog = new EspLog(getClass()); + private final XxjLog mLog = new XxjLog(getClass()); private BluetoothDevice mDevice; private BluetoothGatt mGatt; @@ -180,7 +180,7 @@ private void connectGatt() { mGatt.close(); } GattCallback callback = new GattCallback(); - if (SdkUtil.isAtLeastM_23()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mGatt = mDevice.connectGatt(this, false, callback, BluetoothDevice.TRANSPORT_LE); } else { mGatt = mDevice.connectGatt(this, false, callback); @@ -321,7 +321,7 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState if (status == BluetoothGatt.GATT_SUCCESS) { switch (newState) { case BluetoothProfile.STATE_CONNECTED: - if (SdkUtil.isAtLeastL_21()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH); int mtu = (int) BlufiApp.getInstance().settingsGet( SettingsConstants.PREF_SETTINGS_KEY_MTU_LENGTH, BlufiConstants.DEFAULT_MTU_LENGTH); diff --git a/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java b/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java index a9a4944..588bda0 100644 --- a/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java +++ b/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java @@ -39,8 +39,8 @@ import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; -import libs.espressif.log.EspLog; -import libs.espressif.net.NetUtil; +import tools.xxj.phiman.log.XxjLog; +import tools.xxj.phiman.net.XxjNetUtil; public class ConfigureOptionsActivity extends BaseActivity implements AdapterView.OnItemSelectedListener { private static final int OP_MODE_POS_STA = 0; @@ -62,7 +62,7 @@ public class ConfigureOptionsActivity extends BaseActivity implements AdapterVie private static final String PREF_AP = "blufi_conf_aps"; - private EspLog mLog = new EspLog(getClass()); + private XxjLog mLog = new XxjLog(getClass()); private Spinner mDeviceModeSp; @@ -141,7 +141,7 @@ public void afterTextChanged(Editable s) { mStationSsidET.setText(getConnectionSSID()); WifiInfo info = ((WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE)).getConnectionInfo(); if (info != null) { - byte[] ssidBytes = NetUtil.getOriginalSsidBytes(info); + byte[] ssidBytes = XxjNetUtil.getOriginalSsidBytes(info); mStationSsidET.setTag(ssidBytes); } @@ -323,7 +323,7 @@ private void showWifiListDialog() { .setSingleChoiceItems(wifiSSIDs, checkedItem, (dialog, which) -> { mStationSsidET.setText(wifiSSIDs[which]); ScanResult scanResult = mWifiList.get(which); - byte[] ssidBytes = NetUtil.getOriginalSsidBytes(scanResult); + byte[] ssidBytes = XxjNetUtil.getOriginalSsidBytes(scanResult); mStationSsidET.setTag(ssidBytes); dialog.dismiss(); }) @@ -383,7 +383,7 @@ private boolean checkSta(BlufiConfigureParams params) { } } } - if (NetUtil.is5GHz(freq)) { + if (XxjNetUtil.is5GHz(freq)) { mStationSsidET.setError(getString(R.string.configure_station_wifi_5g_error)); new AlertDialog.Builder(this) .setMessage(R.string.configure_station_wifi_5g_dialog_message) diff --git a/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java b/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java index b379b54..fd4caa4 100644 --- a/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java +++ b/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java @@ -3,6 +3,7 @@ import android.Manifest; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.le.ScanResult; import android.content.Intent; import android.location.LocationManager; import android.os.Build; @@ -22,6 +23,7 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.location.LocationManagerCompat; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; @@ -39,10 +41,10 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; -import libs.espressif.app.PermissionHelper; -import libs.espressif.ble.EspBleUtils; -import libs.espressif.ble.ScanListener; -import libs.espressif.log.EspLog; +import tools.xxj.phiman.app.XxjPermissionHelper; +import tools.xxj.phiman.ble.XxjBleScanListener; +import tools.xxj.phiman.ble.XxjBleUtils; +import tools.xxj.phiman.log.XxjLog; public class MainActivity extends AppCompatActivity { private static final long TIMEOUT_SCAN = 4000L; @@ -52,9 +54,9 @@ public class MainActivity extends AppCompatActivity { private static final int MENU_SETTINGS = 0x01; - private final EspLog mLog = new EspLog(getClass()); + private final XxjLog mLog = new XxjLog(getClass()); - private PermissionHelper mPermissionHelper; + private XxjPermissionHelper mPermissionHelper; private SwipeRefreshLayout mRefreshLayout; @@ -91,14 +93,14 @@ protected void onCreate(Bundle savedInstanceState) { mDeviceRssiMap = new HashMap<>(); mScanCallback = new ScanCallback(); - mPermissionHelper = new PermissionHelper(this, REQUEST_PERMISSION); + mPermissionHelper = new XxjPermissionHelper(this, REQUEST_PERMISSION); mPermissionHelper.setOnPermissionsListener((permission, granted) -> { - if (granted && permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)) { + if (granted && permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)) { mRefreshLayout.setRefreshing(true); scan(); } }); - mPermissionHelper.requestAuthorities(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}); + mPermissionHelper.requestAuthorities(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}); } @Override @@ -151,16 +153,12 @@ private void scan() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Check location enable LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); - if (locationManager != null) { - boolean locationGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - boolean locationNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); - if (!locationGPS && !locationNetwork) { - Toast.makeText(this, R.string.main_location_disable_msg, Toast.LENGTH_SHORT).show(); - mRefreshLayout.setRefreshing(false); - return; - } + boolean locationEnable = locationManager != null && LocationManagerCompat.isLocationEnabled(locationManager); + if (!locationEnable) { + Toast.makeText(this, R.string.main_location_disable_msg, Toast.LENGTH_SHORT).show(); + mRefreshLayout.setRefreshing(false); + return; } - } mDeviceRssiMap.clear(); @@ -171,7 +169,7 @@ private void scan() { mScanStartTime = SystemClock.elapsedRealtime(); mLog.d("Start scan ble"); - EspBleUtils.startScanBle(mScanCallback); + XxjBleUtils.startScanBle(mScanCallback); mUpdateFuture = mThreadPool.submit(() -> { while (!Thread.currentThread().isInterrupted()) { try { @@ -189,14 +187,14 @@ private void scan() { onIntervalScanUpdate(false); } - EspBleUtils.stopScanBle(mScanCallback); + XxjBleUtils.stopScanBle(mScanCallback); onIntervalScanUpdate(true); mLog.d("Scan ble thread is interrupted"); }); } private void stopScan() { - EspBleUtils.stopScanBle(mScanCallback); + XxjBleUtils.stopScanBle(mScanCallback); if (mUpdateFuture != null) { mUpdateFuture.cancel(true); } @@ -253,10 +251,10 @@ public void onClick(View v) { } } - private class ScanCallback implements ScanListener { + private class ScanCallback implements XxjBleScanListener { @Override - public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { + public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord, ScanResult scanResult) { String name = device.getName(); if (!TextUtils.isEmpty(mBlufiFilter)) { if (name == null || !name.startsWith(mBlufiFilter)) { @@ -282,7 +280,7 @@ public void onBindViewHolder(@NonNull BleHolder holder, int position) { BluetoothDevice device = mBleList.get(position); holder.device = device; - String name = device.getName() == null ? getString(R.string.string_unknown) : device.getName(); + String name = device.getName() == null ? getString(R.string.string_unknown) : device.getName(); holder.text1.setText(name); SpannableStringBuilder info = new SpannableStringBuilder(); diff --git a/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java b/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java index f59d577..2f037f3 100644 --- a/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java +++ b/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java @@ -6,16 +6,15 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.preference.EditTextPreference; -import android.preference.Preference; -import android.preference.PreferenceCategory; -import android.preference.PreferenceFragment; -import android.preference.PreferenceScreen; import android.text.TextUtils; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; +import androidx.preference.EditTextPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceFragmentCompat; import com.espressif.espblufi.R; import com.espressif.espblufi.app.BaseActivity; @@ -30,7 +29,7 @@ import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; -import libs.espressif.app.AppUtil; +import tools.xxj.phiman.app.XxjAppUtils; public class SettingsActivity extends BaseActivity { @@ -42,10 +41,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { setSupportActionBar(toolbar); setHomeAsUpEnable(true); - getFragmentManager().beginTransaction().replace(R.id.frame, new SettingsFragment()).commit(); + getSupportFragmentManager().beginTransaction().replace(R.id.frame, new SettingsFragment()).commit(); } - public static class SettingsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener { + public static class SettingsFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener { private static final String KEY_MTU_LENGTH = SettingsConstants.PREF_SETTINGS_KEY_MTU_LENGTH; private static final String KEY_BLE_PREFIX = SettingsConstants.PREF_SETTINGS_KEY_BLE_PREFIX; @@ -57,23 +56,25 @@ public static class SettingsFragment extends PreferenceFragment implements Prefe private Preference mVersionCheckPref; private volatile BlufiAppReleaseTask.ReleaseInfo mAppLatestRelease; + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.blufi_settings, rootKey); + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.blufi_settings); - mApp = BlufiApp.getInstance(); findPreference(getString(R.string.settings_version_key)).setSummary(getVersionName()); findPreference(getString(R.string.settings_blufi_version_key)).setSummary(BlufiClient.VERSION); - mMtuPref = (EditTextPreference) findPreference(getString(R.string.settings_mtu_length_key)); + mMtuPref = findPreference(getString(R.string.settings_mtu_length_key)); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - PreferenceCategory blufiCategory = (PreferenceCategory) findPreference(getString(R.string.settings_category_blufi_key)); + PreferenceCategory blufiCategory = findPreference(getString(R.string.settings_category_blufi_key)); blufiCategory.removePreference(mMtuPref); } else { - mMtuPref.getEditText().setHint(getString(R.string.settings_mtu_length_hint, BlufiConstants.MIN_MTU_LENGTH)); int mtuLen = (int) mApp.settingsGet(KEY_MTU_LENGTH, BlufiConstants.DEFAULT_MTU_LENGTH); mMtuPref.setOnPreferenceChangeListener(this); if (mtuLen >= BlufiConstants.MIN_MTU_LENGTH) { @@ -81,7 +82,7 @@ public void onCreate(Bundle savedInstanceState) { } } - mBlePrefixPref = (EditTextPreference) findPreference(getString(R.string.settings_ble_prefix_key)); + mBlePrefixPref = findPreference(getString(R.string.settings_ble_prefix_key)); mBlePrefixPref.setOnPreferenceChangeListener(this); String blePrefix = (String) mApp.settingsGet(KEY_BLE_PREFIX, BlufiConstants.BLUFI_PREFIX); mBlePrefixPref.setSummary(blePrefix); @@ -89,7 +90,7 @@ public void onCreate(Bundle savedInstanceState) { mVersionCheckPref = findPreference(getString(R.string.settings_upgrade_check_key)); } - public String getVersionName() { + private String getVersionName() { String version; try { PackageInfo pi = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0); @@ -102,7 +103,7 @@ public String getVersionName() { } @Override - public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { + public boolean onPreferenceTreeClick(Preference preference) { if (preference == mVersionCheckPref) { if (mAppLatestRelease == null) { mVersionCheckPref.setEnabled(false); @@ -113,7 +114,7 @@ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preferen return true; } - return super.onPreferenceTreeClick(preferenceScreen, preference); + return super.onPreferenceTreeClick(preference); } @Override @@ -158,7 +159,7 @@ private void checkAppLatestRelease() { return; } - long currentVersion = AppUtil.getVersionCode(getActivity()); + long currentVersion = XxjAppUtils.getVersionCode(getActivity()); long latestVersion = latestRelease.getVersionCode(); if (latestVersion > currentVersion) { mVersionCheckPref.setSummary(R.string.settings_upgrade_check_disciver_new); diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 4879d2b..f8de703 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -53,7 +53,7 @@ BluFi settings_key_mtu_length 设置 mtu 长度 - 设置一个大于 %1$d 的数 + 设置一个大于 15 的数 settings_key_ble_prefix BLE 设备过滤 设备名前缀 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3a688e9..fed1d09 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -52,7 +52,7 @@ BluFi settings_key_mtu_length Set mtu length - Enter a number great than %1$d + Enter a number great than 15 settings_key_ble_prefix BLE devices filter Device name start with diff --git a/app/src/main/res/xml/blufi_settings.xml b/app/src/main/res/xml/blufi_settings.xml index eaceb6c..4d5b697 100644 --- a/app/src/main/res/xml/blufi_settings.xml +++ b/app/src/main/res/xml/blufi_settings.xml @@ -1,27 +1,38 @@ - - - + + - + - + app:iconSpaceReserved="false" + app:key="@string/settings_ble_prefix_key" + app:title="@string/settings_ble_prefix_title" /> + - - - - - - + + + + + + diff --git a/apptools/.gitignore b/apptools/.gitignore deleted file mode 100644 index 9841ffe..0000000 --- a/apptools/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/build -/.idea -*.iml -.DS_Store diff --git a/apptools/build.gradle b/apptools/build.gradle deleted file mode 100644 index eed94a9..0000000 --- a/apptools/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 28 - - defaultConfig { - minSdkVersion 18 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - - implementation 'androidx.appcompat:appcompat:1.0.2' -} diff --git a/apptools/gradlew.bat b/apptools/gradlew.bat deleted file mode 100644 index aec9973..0000000 --- a/apptools/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@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 diff --git a/apptools/proguard-rules.pro b/apptools/proguard-rules.pro deleted file mode 100644 index f1b4245..0000000 --- a/apptools/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/apptools/src/main/AndroidManifest.xml b/apptools/src/main/AndroidManifest.xml deleted file mode 100644 index 6458a8f..0000000 --- a/apptools/src/main/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - diff --git a/apptools/src/main/java/libs/espressif/app/AppUtil.java b/apptools/src/main/java/libs/espressif/app/AppUtil.java deleted file mode 100644 index ff1d440..0000000 --- a/apptools/src/main/java/libs/espressif/app/AppUtil.java +++ /dev/null @@ -1,107 +0,0 @@ -package libs.espressif.app; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.Signature; -import android.content.res.Configuration; -import android.net.Uri; - -import androidx.core.content.FileProvider; - -import java.io.File; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import libs.espressif.utils.DataUtil; - -public class AppUtil { - public static byte[] getSignatureMD5Bytes(Context context) { - String packageName = context.getApplicationInfo().packageName; - try { - byte[] signData; - if (SdkUtil.isAtLeastP_28()) { - int flag = PackageManager.GET_SIGNING_CERTIFICATES; - PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, flag); - Signature signature = pi.signingInfo.getApkContentsSigners()[0]; - signData = signature.toByteArray(); - } else { - int flag = PackageManager.GET_SIGNATURES; - PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, flag); - Signature signature = (pi.signatures)[0]; - signData = signature.toByteArray(); - } - - MessageDigest digest = MessageDigest.getInstance("md5"); - digest.update(signData); - return digest.digest(); - } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException | NullPointerException e) { - e.printStackTrace(); - } - - return null; - } - - /** - * Get the MD5 of the apk keystore. - * - * @return MD5 of the apk keystore. - */ - public static String getSignatureMD5Hex(Context context) { - byte[] data = getSignatureMD5Bytes(context); - if (data == null) { - return ""; - } - - return DataUtil.bigEndianBytesToHexString(data); - } - - public static boolean isPad(Context context) { - return (context.getResources().getConfiguration().screenLayout - & Configuration.SCREENLAYOUT_SIZE_MASK) - >= Configuration.SCREENLAYOUT_SIZE_LARGE; - } - - public static boolean supportBLE(Context context) { - return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE); - } - - public static String getVersionName(Context context) { - PackageManager packageManager = context.getPackageManager(); - try { - PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0); - return info.versionName; - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - return "Unknown"; - } - } - - public static long getVersionCode(Context context) { - PackageManager packageManager = context.getPackageManager(); - try { - PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0); - return SdkUtil.isAtLeastP_28() ? info.getLongVersionCode() : info.versionCode; - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - return -1; - } - } - - public static void installApk(Context context, File apk) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - Uri uri; - if (SdkUtil.isAtLeastN_24()) { - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - - String authority = context.getPackageName() + ".fileProvider"; - uri = FileProvider.getUriForFile(context, authority, apk); - } else { - uri = Uri.fromFile(apk); - } - intent.setDataAndType(uri, "application/vnd.android.package-archive"); - context.startActivity(intent); - } -} diff --git a/apptools/src/main/java/libs/espressif/app/CrashHandler.java b/apptools/src/main/java/libs/espressif/app/CrashHandler.java deleted file mode 100644 index 6adf25a..0000000 --- a/apptools/src/main/java/libs/espressif/app/CrashHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -package libs.espressif.app; - -import android.content.Context; -import android.util.Log; - -public class CrashHandler implements Thread.UncaughtExceptionHandler { - private Thread.UncaughtExceptionHandler mDefaultHandler; - - private OnCaughtExceptionListener mOnCaughtExceptionListener; - - public CrashHandler() { - mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); - Thread.setDefaultUncaughtExceptionHandler(this); - } - - @Override - public void uncaughtException(Thread t, Throwable e) { - if (mOnCaughtExceptionListener == null - || !mOnCaughtExceptionListener.onCaughtException(t, e)) { - mDefaultHandler.uncaughtException(t, e); - } - } - - public void setOnCaughtExceptionListener(OnCaughtExceptionListener listener) { - mOnCaughtExceptionListener = listener; - } - - public interface OnCaughtExceptionListener { - boolean onCaughtException(Thread t, Throwable e); - } -} diff --git a/apptools/src/main/java/libs/espressif/app/EspActivity.java b/apptools/src/main/java/libs/espressif/app/EspActivity.java deleted file mode 100644 index d982c94..0000000 --- a/apptools/src/main/java/libs/espressif/app/EspActivity.java +++ /dev/null @@ -1,30 +0,0 @@ -package libs.espressif.app; - -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import android.view.MenuItem; - -public abstract class EspActivity extends AppCompatActivity { - /** - * Show back button on ToolBar - * - * @param show action up button or not - */ - public void setHomeAsUpEnable(boolean show) { - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(show); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - final int itemId = item.getItemId(); - if (itemId == android.R.id.home) { - onBackPressed(); - return true; - } - - return super.onOptionsItemSelected(item); - } -} diff --git a/apptools/src/main/java/libs/espressif/app/PermissionHelper.java b/apptools/src/main/java/libs/espressif/app/PermissionHelper.java deleted file mode 100644 index 01d681b..0000000 --- a/apptools/src/main/java/libs/espressif/app/PermissionHelper.java +++ /dev/null @@ -1,121 +0,0 @@ -package libs.espressif.app; - -import android.app.Activity; -import android.content.Context; -import android.content.pm.PackageManager; - -import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import java.util.ArrayList; -import java.util.List; - -public class PermissionHelper { - private final int mRequestCode; - - private Activity mActivity; - - private OnPermissionsListener mListener; - - public PermissionHelper(@NonNull Activity activity, int requestCode) { - mActivity = activity; - mRequestCode = requestCode; - } - - public int getRequestCode() { - return mRequestCode; - } - - /** - * Call this function in {@link androidx.appcompat.app.AppCompatActivity#onRequestPermissionsResult}. - * - * @param requestCode the request code - * @param permissions the request permissions - * @param grantResults the grant results - */ - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if (requestCode == mRequestCode) { - for (int i = 0; i < permissions.length; i++) { - String permission = permissions[i]; - boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED; - if (mListener != null) { - mListener.onPermissonsChange(permission, granted); - } - } - } - } - - /** - * Requests permissions to be granted to this application. - * - * @param permissions the requested permissions. - */ - public void requestAuthorities(@NonNull String[] permissions) { - if (SdkUtil.isAtLeastM_23()) { - final List requirePermissionList = new ArrayList<>(); - - for (String permission : permissions) { - if (!isPermissionGranted(permission)) { - requirePermissionList.add(permission); - } else { - if (mListener != null) { - mListener.onPermissonsChange(permission, true); - } - } - } - - if (!requirePermissionList.isEmpty()) { - String[] requirePermissionArray = new String[requirePermissionList.size()]; - for (int i = 0; i < requirePermissionList.size(); i++) { - requirePermissionArray[i] = requirePermissionList.get(i); - } - // request permission one by one - ActivityCompat.requestPermissions(mActivity, requirePermissionArray, mRequestCode); - } - } else { - if (mListener != null) { - for (String permission : permissions) { - mListener.onPermissonsChange(permission, true); - } - } - } - } - - /** - * Determine whether user have been granted a particular permission. - * - * @param permission the name of the permission being checked. - * @return granted or not. - */ - public boolean isPermissionGranted(String permission) { - return isPermissionGranted(mActivity, permission); - } - - public static boolean isPermissionGranted(Context context, String permission) { - return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; - } - - /** - * Register a callback to be invoked when a permission changed. - * It will take effect after call #onRequestPermissionsResult in AppCompatActivity. - * - * @param listener the callback that will run - */ - public void setOnPermissionsListener(OnPermissionsListener listener) { - mListener = listener; - } - - /** - * Interface definition for a callback to be invoked when a permission changed. - */ - public interface OnPermissionsListener { - /** - * Call when the permission has changed. - * - * @param permission the changed permission. - * @param granted or not. - */ - void onPermissonsChange(String permission, boolean granted); - } -} diff --git a/apptools/src/main/java/libs/espressif/app/SdkUtil.java b/apptools/src/main/java/libs/espressif/app/SdkUtil.java deleted file mode 100644 index 97bdbb4..0000000 --- a/apptools/src/main/java/libs/espressif/app/SdkUtil.java +++ /dev/null @@ -1,142 +0,0 @@ -package libs.espressif.app; - -import android.os.Build.VERSION_CODES; - -import static android.os.Build.VERSION.SDK_INT; - -public class SdkUtil { - /** - * Check if the device is running on the Android ICE_CREAM_SANDWICH(14) release or newer. - * - * @return true if I APIs are available for use. - */ - public static boolean isAtLeastI_14() { - return SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; - } - - /** - * Check if the device is running on the Android ICE_CREAM_SANDWICH_MR1(15) release or newer. - * - * @return true if I_MR1 APIs are available for use. - */ - public static boolean isAtLeastIMR1_15() { - return SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH_MR1; - } - - /** - * Check if the device is running on the Android JELLY_BEAN(16) release or newer. - * - * @return true if J APIs are available for use. - */ - public static boolean isAtLeastJ_16() { - return SDK_INT >= VERSION_CODES.JELLY_BEAN; - } - - /** - * Check if the device is running on the Android JELLY_BEAN_MR1(17) release or newer. - * - * @return true if J_MR1 APIs are available for use. - */ - public static boolean isAtLeastJMR1_17() { - return SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1; - } - - /** - * Check if the device is running on the Android JELLY_BEAN_MR2(18) release or newer. - * - * @return true if J_MR2 APIs are available for use. - */ - public static boolean isAtLeastJMR2_18() { - return SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2; - } - - /** - * Check if the device is running on the Android KITKAT(19) release or newer. - * - * @return true if K APIs are available for use. - */ - public static boolean isAtLeastK_19() { - return SDK_INT >= VERSION_CODES.KITKAT; - } - - /** - * Check if the device is running on the Android KITKAT_WATCH(20) release or newer. - * - * @return true if K_W APIs are available for use. - */ - public static boolean isAtLeastKW_20() { - return SDK_INT >= VERSION_CODES.KITKAT_WATCH; - } - - /** - * Check if the device is running on the Android LOLLIPOP(21) release or newer. - * - * @return true if L APIs are available for use. - */ - public static boolean isAtLeastL_21() { - return SDK_INT >= VERSION_CODES.LOLLIPOP; - } - - /** - * Check if the device is running on the Android LOLLIPOP_MR1(22) release or newer. - * - * @return true if L_MR1 APIs are available for use. - */ - public static boolean isAtLeastLMR1_22() { - return SDK_INT >= VERSION_CODES.LOLLIPOP_MR1; - } - - /** - * Check if the device is running on the Android M(23) release or newer. - * - * @return true if M APIs are available for use. - */ - public static boolean isAtLeastM_23() { - return SDK_INT >= VERSION_CODES.M; - } - - /** - * Check if the device is running on the Android N(24) release or newer. - * - * @return true if N APIs are available for use. - */ - public static boolean isAtLeastN_24() { - return SDK_INT >= VERSION_CODES.N; - } - - /** - * Check if the device is running on the Android N(25) release or newer. - * - * @return true if N_MR1 APIs are available for use. - */ - public static boolean isAtLeastNMR1_25() { - return SDK_INT >= VERSION_CODES.N_MR1; - } - - /** - * Check if the device is running on the Android O(26) release or newer. - * - * @return true if O APIs are available for use. - */ - public static boolean isAtLeastO_26() { - return SDK_INT >= VERSION_CODES.O; - } - - /** - * Check if the device is running on the Android O(27) release or newer. - * - * @return true if O APIs are available for use. - */ - public static boolean isAtLeastOMR1_27() { - return SDK_INT >= VERSION_CODES.O_MR1; - } - - /** - * Check if the device is running on the Android P(28) release or newer. - * - * @return true if P APIs are available for use. - */ - public static boolean isAtLeastP_28() { - return SDK_INT >= 28; - } -} diff --git a/apptools/src/main/java/libs/espressif/ble/BleAdvData.java b/apptools/src/main/java/libs/espressif/ble/BleAdvData.java deleted file mode 100644 index 9249484..0000000 --- a/apptools/src/main/java/libs/espressif/ble/BleAdvData.java +++ /dev/null @@ -1,29 +0,0 @@ -package libs.espressif.ble; - -import libs.espressif.utils.DataUtil; - -public class BleAdvData { - private int mType; - private byte[] mData; - - public void setType(int type) { - mType = type; - } - - public int getType() { - return mType; - } - - public void setData(byte[] data) { - mData = data; - } - - public byte[] getData() { - return mData; - } - - @Override - public String toString() { - return String.format("Adv type=%02x, data=%s", mType, (mData == null ? null : DataUtil.bigEndianBytesToHexString(mData))); - } -} diff --git a/apptools/src/main/java/libs/espressif/ble/EspBleUtils.java b/apptools/src/main/java/libs/espressif/ble/EspBleUtils.java deleted file mode 100644 index 2ee5aa3..0000000 --- a/apptools/src/main/java/libs/espressif/ble/EspBleUtils.java +++ /dev/null @@ -1,194 +0,0 @@ -package libs.espressif.ble; - -import android.annotation.TargetApi; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.content.Context; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import libs.espressif.app.SdkUtil; -import libs.espressif.utils.DataUtil; - -public class EspBleUtils { - private static final String UUID_INDICATION_DESCRIPTOR = "00002902-0000-1000-8000-00805f9b34fb"; - private static final String BASE_UUID_FORMAT = "0000%s-0000-1000-8000-00805f9b34fb"; - - private static final Map mScanListenerMap = new HashMap<>(); - - public static UUID newUUID(String address) { - String string = String.format(BASE_UUID_FORMAT, address); - return UUID.fromString(string); - } - - /** - * Starts a scan for Bluetooth LE devices. - * - * @param listener the callback LE scan results are delivered. - * @return true, if the scan was started successfully. - */ - public static boolean startScanBle(@NonNull final ScanListener listener) { - // This listener scanning has started. - if (mScanListenerMap.get(listener) != null) { - return false; - } - - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - BleScanCallback scanCallback = new BleScanCallback(listener); - mScanListenerMap.put(listener, scanCallback); - BluetoothLeScanner scanner = adapter.getBluetoothLeScanner(); - ScanSettings settings = new ScanSettings.Builder() - .setScanMode(ScanSettings.SCAN_MODE_BALANCED) - .build(); - scanner.startScan(null, settings, scanCallback); - return true; - } else { - BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() { - @Override - public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { - if (mScanListenerMap.get(listener) != null) { - listener.onLeScan(device, rssi, scanRecord); - } - } - }; - mScanListenerMap.put(listener, callback); - //noinspection deprecation - return adapter.startLeScan(callback); - } - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private static class BleScanCallback extends ScanCallback { - ScanListener mScanListener; - - BleScanCallback(ScanListener scanListener) { - mScanListener = scanListener; - } - - void onScanDevice(ScanResult result) { - BluetoothDevice device = result.getDevice(); - int rssi = result.getRssi(); - byte[] scanRecord = result.getScanRecord() == null ? null : result.getScanRecord().getBytes(); - if (mScanListenerMap.get(mScanListener) != null) { - mScanListener.onLeScan(device, rssi, scanRecord); - } - } - - @Override - public void onScanResult(int callbackType, ScanResult result) { - onScanDevice(result); - } - - @Override - public void onBatchScanResults(List results) { - for (ScanResult result : results) { - onScanDevice(result); - } - } - } - - /** - * Stops an ongoing Bluetooth LE device scan. - * - * @param listener callback used to identify which scan to stop - * must be the same handle used to start the scan - */ - public static void stopScanBle(@NonNull ScanListener listener) { - Object callback = mScanListenerMap.remove(listener); - if (callback == null) { - return; - } - - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (callback instanceof ScanCallback) { - adapter.getBluetoothLeScanner().stopScan((ScanCallback) callback); - } else { - //noinspection deprecation - adapter.stopLeScan((BluetoothAdapter.LeScanCallback) callback); - } - - } else { - //noinspection deprecation - adapter.stopLeScan((BluetoothAdapter.LeScanCallback) callback); - } - } - - public static UUID newUUID(byte[] bytes) { - String address = String.format("%02x%02x", bytes[0], bytes[1]); - return newUUID(address); - } - - public static UUID getIndicationDescriptorUUID() { - return UUID.fromString(UUID_INDICATION_DESCRIPTOR); - } - - public static BluetoothGatt connectGatt(BluetoothDevice device, Context context, BluetoothGattCallback callback) { - if (SdkUtil.isAtLeastM_23()) { - return device.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE); - } else { - return device.connectGatt(context, false, callback); - } - } - - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - public static String getDeviceName(ScanResult sr) { - String name = sr.getDevice().getName();; - if (name == null) { - ScanRecord record = sr.getScanRecord(); - if (record != null) { - name = record.getDeviceName(); - } - } - - return name; - } - - public static List resolveScanRecord(byte[] record) { - if (record == null) { - return Collections.emptyList(); - } - - List result = new ArrayList<>(); - - int offset = 0; - - do { - int len = record[offset] & 0xff; - if (len == 0) { - break; - } - if (offset + 1 + len >= record.length) { - break; - } - - int type = record[offset + 1] & 0xff; - byte[] data = DataUtil.subBytes(record, offset + 2, len - 1); - - BleAdvData advData = new BleAdvData(); - advData.setType(type); - advData.setData(data); - result.add(advData); - - offset += (len + 1); - } while (offset < record.length); - - return result; - } -} diff --git a/apptools/src/main/java/libs/espressif/ble/ScanListener.java b/apptools/src/main/java/libs/espressif/ble/ScanListener.java deleted file mode 100644 index 62234fd..0000000 --- a/apptools/src/main/java/libs/espressif/ble/ScanListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package libs.espressif.ble; - -import android.bluetooth.BluetoothDevice; - -public interface ScanListener { - void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord); -} diff --git a/apptools/src/main/java/libs/espressif/language/HanziToPinyin.java b/apptools/src/main/java/libs/espressif/language/HanziToPinyin.java deleted file mode 100644 index 90444cb..0000000 --- a/apptools/src/main/java/libs/espressif/language/HanziToPinyin.java +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package libs.espressif.language; - -import android.text.TextUtils; -import android.util.Log; - -import java.text.Collator; -import java.util.ArrayList; -import java.util.Locale; - -/** - * An object to convert Chinese character to its corresponding pinyin string. For characters with - * multiple possible pinyin string, only one is selected according to collator. Polyphone is not - * supported in this implementation. This class is implemented to achieve the best runtime - * performance and minimum runtime resources with tolerable sacrifice of accuracy. This - * implementation highly depends on zh_CN ICU collation data and must be always synchronized with - * ICU. - * - * Currently this file is aligned to zh.txt in ICU 4.6 - */ -public class HanziToPinyin { - private static final String TAG = "HanziToPinyin"; - - // Turn on this flag when we want to check internal data structure. - private static final boolean DEBUG = false; - - /** - * Unihans array. - * - * Each unihans is the first one within same pinyin when collator is zh_CN. - */ - public static final char[] UNIHANS = { - '\u963f', '\u54ce', '\u5b89', '\u80ae', '\u51f9', '\u516b', - '\u6300', '\u6273', '\u90a6', '\u52f9', '\u9642', '\u5954', - '\u4f3b', '\u5c44', '\u8fb9', '\u706c', '\u618b', '\u6c43', - '\u51ab', '\u7676', '\u5cec', '\u5693', '\u5072', '\u53c2', - '\u4ed3', '\u64a1', '\u518a', '\u5d7e', '\u66fd', '\u66fe', - '\u5c64', '\u53c9', '\u8286', '\u8fbf', '\u4f25', '\u6284', - '\u8f66', '\u62bb', '\u6c88', '\u6c89', '\u9637', '\u5403', - '\u5145', '\u62bd', '\u51fa', '\u6b3b', '\u63e3', '\u5ddb', - '\u5205', '\u5439', '\u65fe', '\u9034', '\u5472', '\u5306', - '\u51d1', '\u7c97', '\u6c46', '\u5d14', '\u90a8', '\u6413', - '\u5491', '\u5446', '\u4e39', '\u5f53', '\u5200', '\u561a', - '\u6265', '\u706f', '\u6c10', '\u55f2', '\u7538', '\u5201', - '\u7239', '\u4e01', '\u4e1f', '\u4e1c', '\u543a', '\u53be', - '\u8011', '\u8968', '\u5428', '\u591a', '\u59b8', '\u8bf6', - '\u5940', '\u97a5', '\u513f', '\u53d1', '\u5e06', '\u531a', - '\u98de', '\u5206', '\u4e30', '\u8985', '\u4ecf', '\u7d11', - '\u4f15', '\u65ee', '\u4f85', '\u7518', '\u5188', '\u768b', - '\u6208', '\u7ed9', '\u6839', '\u522f', '\u5de5', '\u52fe', - '\u4f30', '\u74dc', '\u4e56', '\u5173', '\u5149', '\u5f52', - '\u4e28', '\u5459', '\u54c8', '\u548d', '\u4f44', '\u592f', - '\u8320', '\u8bc3', '\u9ed2', '\u62eb', '\u4ea8', '\u5677', - '\u53ff', '\u9f41', '\u4e6f', '\u82b1', '\u6000', '\u72bf', - '\u5ddf', '\u7070', '\u660f', '\u5419', '\u4e0c', '\u52a0', - '\u620b', '\u6c5f', '\u827d', '\u9636', '\u5dfe', '\u5755', - '\u5182', '\u4e29', '\u51e5', '\u59e2', '\u5658', '\u519b', - '\u5494', '\u5f00', '\u520a', '\u5ffc', '\u5c3b', '\u533c', - '\u808e', '\u52a5', '\u7a7a', '\u62a0', '\u625d', '\u5938', - '\u84af', '\u5bbd', '\u5321', '\u4e8f', '\u5764', '\u6269', - '\u5783', '\u6765', '\u5170', '\u5577', '\u635e', '\u808b', - '\u52d2', '\u5d1a', '\u5215', '\u4fe9', '\u5941', '\u826f', - '\u64a9', '\u5217', '\u62ce', '\u5222', '\u6e9c', '\u56d6', - '\u9f99', '\u779c', '\u565c', '\u5a08', '\u7567', '\u62a1', - '\u7f57', '\u5463', '\u5988', '\u57cb', '\u5ada', '\u7264', - '\u732b', '\u4e48', '\u5445', '\u95e8', '\u753f', '\u54aa', - '\u5b80', '\u55b5', '\u4e5c', '\u6c11', '\u540d', '\u8c2c', - '\u6478', '\u54de', '\u6bea', '\u55ef', '\u62cf', '\u8149', - '\u56e1', '\u56d4', '\u5b6c', '\u7592', '\u5a1e', '\u6041', - '\u80fd', '\u59ae', '\u62c8', '\u5b22', '\u9e1f', '\u634f', - '\u56dc', '\u5b81', '\u599e', '\u519c', '\u7fba', '\u5974', - '\u597b', '\u759f', '\u9ec1', '\u90cd', '\u5594', '\u8bb4', - '\u5991', '\u62cd', '\u7705', '\u4e53', '\u629b', '\u5478', - '\u55b7', '\u5309', '\u4e15', '\u56e8', '\u527d', '\u6c15', - '\u59d8', '\u4e52', '\u948b', '\u5256', '\u4ec6', '\u4e03', - '\u6390', '\u5343', '\u545b', '\u6084', '\u767f', '\u4eb2', - '\u72c5', '\u828e', '\u4e18', '\u533a', '\u5cd1', '\u7f3a', - '\u590b', '\u5465', '\u7a63', '\u5a06', '\u60f9', '\u4eba', - '\u6254', '\u65e5', '\u8338', '\u53b9', '\u909a', '\u633c', - '\u5827', '\u5a51', '\u77a4', '\u637c', '\u4ee8', '\u6be2', - '\u4e09', '\u6852', '\u63bb', '\u95aa', '\u68ee', '\u50e7', - '\u6740', '\u7b5b', '\u5c71', '\u4f24', '\u5f30', '\u5962', - '\u7533', '\u8398', '\u6552', '\u5347', '\u5c38', '\u53ce', - '\u4e66', '\u5237', '\u8870', '\u95e9', '\u53cc', '\u8c01', - '\u542e', '\u8bf4', '\u53b6', '\u5fea', '\u635c', '\u82cf', - '\u72fb', '\u590a', '\u5b59', '\u5506', '\u4ed6', '\u56fc', - '\u574d', '\u6c64', '\u5932', '\u5fd1', '\u71a5', '\u5254', - '\u5929', '\u65eb', '\u5e16', '\u5385', '\u56f2', '\u5077', - '\u51f8', '\u6e4d', '\u63a8', '\u541e', '\u4e47', '\u7a75', - '\u6b6a', '\u5f2f', '\u5c23', '\u5371', '\u6637', '\u7fc1', - '\u631d', '\u4e4c', '\u5915', '\u8672', '\u4eda', '\u4e61', - '\u7071', '\u4e9b', '\u5fc3', '\u661f', '\u51f6', '\u4f11', - '\u5401', '\u5405', '\u524a', '\u5743', '\u4e2b', '\u6079', - '\u592e', '\u5e7a', '\u503b', '\u4e00', '\u56d9', '\u5e94', - '\u54df', '\u4f63', '\u4f18', '\u625c', '\u56e6', '\u66f0', - '\u6655', '\u7b60', '\u7b7c', '\u5e00', '\u707d', '\u5142', - '\u5328', '\u50ae', '\u5219', '\u8d3c', '\u600e', '\u5897', - '\u624e', '\u635a', '\u6cbe', '\u5f20', '\u957f', '\u9577', - '\u4f4b', '\u8707', '\u8d1e', '\u4e89', '\u4e4b', '\u5cd9', - '\u5ea2', '\u4e2d', '\u5dde', '\u6731', '\u6293', '\u62fd', - '\u4e13', '\u5986', '\u96b9', '\u5b92', '\u5353', '\u4e72', - '\u5b97', '\u90b9', '\u79df', '\u94bb', '\u539c', '\u5c0a', - '\u6628', '\u5159', '\u9fc3', '\u9fc4', }; - - /** - * Pinyin array. - * - * Each pinyin is corresponding to unihans of same - * offset in the unihans array. - */ - public static final byte[][] PINYINS = { - { 65, 0, 0, 0, 0, 0}, { 65, 73, 0, 0, 0, 0}, - { 65, 78, 0, 0, 0, 0}, { 65, 78, 71, 0, 0, 0}, - { 65, 79, 0, 0, 0, 0}, { 66, 65, 0, 0, 0, 0}, - { 66, 65, 73, 0, 0, 0}, { 66, 65, 78, 0, 0, 0}, - { 66, 65, 78, 71, 0, 0}, { 66, 65, 79, 0, 0, 0}, - { 66, 69, 73, 0, 0, 0}, { 66, 69, 78, 0, 0, 0}, - { 66, 69, 78, 71, 0, 0}, { 66, 73, 0, 0, 0, 0}, - { 66, 73, 65, 78, 0, 0}, { 66, 73, 65, 79, 0, 0}, - { 66, 73, 69, 0, 0, 0}, { 66, 73, 78, 0, 0, 0}, - { 66, 73, 78, 71, 0, 0}, { 66, 79, 0, 0, 0, 0}, - { 66, 85, 0, 0, 0, 0}, { 67, 65, 0, 0, 0, 0}, - { 67, 65, 73, 0, 0, 0}, { 67, 65, 78, 0, 0, 0}, - { 67, 65, 78, 71, 0, 0}, { 67, 65, 79, 0, 0, 0}, - { 67, 69, 0, 0, 0, 0}, { 67, 69, 78, 0, 0, 0}, - { 67, 69, 78, 71, 0, 0}, { 90, 69, 78, 71, 0, 0}, - { 67, 69, 78, 71, 0, 0}, { 67, 72, 65, 0, 0, 0}, - { 67, 72, 65, 73, 0, 0}, { 67, 72, 65, 78, 0, 0}, - { 67, 72, 65, 78, 71, 0}, { 67, 72, 65, 79, 0, 0}, - { 67, 72, 69, 0, 0, 0}, { 67, 72, 69, 78, 0, 0}, - { 83, 72, 69, 78, 0, 0}, { 67, 72, 69, 78, 0, 0}, - { 67, 72, 69, 78, 71, 0}, { 67, 72, 73, 0, 0, 0}, - { 67, 72, 79, 78, 71, 0}, { 67, 72, 79, 85, 0, 0}, - { 67, 72, 85, 0, 0, 0}, { 67, 72, 85, 65, 0, 0}, - { 67, 72, 85, 65, 73, 0}, { 67, 72, 85, 65, 78, 0}, - { 67, 72, 85, 65, 78, 71}, { 67, 72, 85, 73, 0, 0}, - { 67, 72, 85, 78, 0, 0}, { 67, 72, 85, 79, 0, 0}, - { 67, 73, 0, 0, 0, 0}, { 67, 79, 78, 71, 0, 0}, - { 67, 79, 85, 0, 0, 0}, { 67, 85, 0, 0, 0, 0}, - { 67, 85, 65, 78, 0, 0}, { 67, 85, 73, 0, 0, 0}, - { 67, 85, 78, 0, 0, 0}, { 67, 85, 79, 0, 0, 0}, - { 68, 65, 0, 0, 0, 0}, { 68, 65, 73, 0, 0, 0}, - { 68, 65, 78, 0, 0, 0}, { 68, 65, 78, 71, 0, 0}, - { 68, 65, 79, 0, 0, 0}, { 68, 69, 0, 0, 0, 0}, - { 68, 69, 78, 0, 0, 0}, { 68, 69, 78, 71, 0, 0}, - { 68, 73, 0, 0, 0, 0}, { 68, 73, 65, 0, 0, 0}, - { 68, 73, 65, 78, 0, 0}, { 68, 73, 65, 79, 0, 0}, - { 68, 73, 69, 0, 0, 0}, { 68, 73, 78, 71, 0, 0}, - { 68, 73, 85, 0, 0, 0}, { 68, 79, 78, 71, 0, 0}, - { 68, 79, 85, 0, 0, 0}, { 68, 85, 0, 0, 0, 0}, - { 68, 85, 65, 78, 0, 0}, { 68, 85, 73, 0, 0, 0}, - { 68, 85, 78, 0, 0, 0}, { 68, 85, 79, 0, 0, 0}, - { 69, 0, 0, 0, 0, 0}, { 69, 73, 0, 0, 0, 0}, - { 69, 78, 0, 0, 0, 0}, { 69, 78, 71, 0, 0, 0}, - { 69, 82, 0, 0, 0, 0}, { 70, 65, 0, 0, 0, 0}, - { 70, 65, 78, 0, 0, 0}, { 70, 65, 78, 71, 0, 0}, - { 70, 69, 73, 0, 0, 0}, { 70, 69, 78, 0, 0, 0}, - { 70, 69, 78, 71, 0, 0}, { 70, 73, 65, 79, 0, 0}, - { 70, 79, 0, 0, 0, 0}, { 70, 79, 85, 0, 0, 0}, - { 70, 85, 0, 0, 0, 0}, { 71, 65, 0, 0, 0, 0}, - { 71, 65, 73, 0, 0, 0}, { 71, 65, 78, 0, 0, 0}, - { 71, 65, 78, 71, 0, 0}, { 71, 65, 79, 0, 0, 0}, - { 71, 69, 0, 0, 0, 0}, { 71, 69, 73, 0, 0, 0}, - { 71, 69, 78, 0, 0, 0}, { 71, 69, 78, 71, 0, 0}, - { 71, 79, 78, 71, 0, 0}, { 71, 79, 85, 0, 0, 0}, - { 71, 85, 0, 0, 0, 0}, { 71, 85, 65, 0, 0, 0}, - { 71, 85, 65, 73, 0, 0}, { 71, 85, 65, 78, 0, 0}, - { 71, 85, 65, 78, 71, 0}, { 71, 85, 73, 0, 0, 0}, - { 71, 85, 78, 0, 0, 0}, { 71, 85, 79, 0, 0, 0}, - { 72, 65, 0, 0, 0, 0}, { 72, 65, 73, 0, 0, 0}, - { 72, 65, 78, 0, 0, 0}, { 72, 65, 78, 71, 0, 0}, - { 72, 65, 79, 0, 0, 0}, { 72, 69, 0, 0, 0, 0}, - { 72, 69, 73, 0, 0, 0}, { 72, 69, 78, 0, 0, 0}, - { 72, 69, 78, 71, 0, 0}, { 72, 77, 0, 0, 0, 0}, - { 72, 79, 78, 71, 0, 0}, { 72, 79, 85, 0, 0, 0}, - { 72, 85, 0, 0, 0, 0}, { 72, 85, 65, 0, 0, 0}, - { 72, 85, 65, 73, 0, 0}, { 72, 85, 65, 78, 0, 0}, - { 72, 85, 65, 78, 71, 0}, { 72, 85, 73, 0, 0, 0}, - { 72, 85, 78, 0, 0, 0}, { 72, 85, 79, 0, 0, 0}, - { 74, 73, 0, 0, 0, 0}, { 74, 73, 65, 0, 0, 0}, - { 74, 73, 65, 78, 0, 0}, { 74, 73, 65, 78, 71, 0}, - { 74, 73, 65, 79, 0, 0}, { 74, 73, 69, 0, 0, 0}, - { 74, 73, 78, 0, 0, 0}, { 74, 73, 78, 71, 0, 0}, - { 74, 73, 79, 78, 71, 0}, { 74, 73, 85, 0, 0, 0}, - { 74, 85, 0, 0, 0, 0}, { 74, 85, 65, 78, 0, 0}, - { 74, 85, 69, 0, 0, 0}, { 74, 85, 78, 0, 0, 0}, - { 75, 65, 0, 0, 0, 0}, { 75, 65, 73, 0, 0, 0}, - { 75, 65, 78, 0, 0, 0}, { 75, 65, 78, 71, 0, 0}, - { 75, 65, 79, 0, 0, 0}, { 75, 69, 0, 0, 0, 0}, - { 75, 69, 78, 0, 0, 0}, { 75, 69, 78, 71, 0, 0}, - { 75, 79, 78, 71, 0, 0}, { 75, 79, 85, 0, 0, 0}, - { 75, 85, 0, 0, 0, 0}, { 75, 85, 65, 0, 0, 0}, - { 75, 85, 65, 73, 0, 0}, { 75, 85, 65, 78, 0, 0}, - { 75, 85, 65, 78, 71, 0}, { 75, 85, 73, 0, 0, 0}, - { 75, 85, 78, 0, 0, 0}, { 75, 85, 79, 0, 0, 0}, - { 76, 65, 0, 0, 0, 0}, { 76, 65, 73, 0, 0, 0}, - { 76, 65, 78, 0, 0, 0}, { 76, 65, 78, 71, 0, 0}, - { 76, 65, 79, 0, 0, 0}, { 76, 69, 0, 0, 0, 0}, - { 76, 69, 73, 0, 0, 0}, { 76, 69, 78, 71, 0, 0}, - { 76, 73, 0, 0, 0, 0}, { 76, 73, 65, 0, 0, 0}, - { 76, 73, 65, 78, 0, 0}, { 76, 73, 65, 78, 71, 0}, - { 76, 73, 65, 79, 0, 0}, { 76, 73, 69, 0, 0, 0}, - { 76, 73, 78, 0, 0, 0}, { 76, 73, 78, 71, 0, 0}, - { 76, 73, 85, 0, 0, 0}, { 76, 79, 0, 0, 0, 0}, - { 76, 79, 78, 71, 0, 0}, { 76, 79, 85, 0, 0, 0}, - { 76, 85, 0, 0, 0, 0}, { 76, 85, 65, 78, 0, 0}, - { 76, 85, 69, 0, 0, 0}, { 76, 85, 78, 0, 0, 0}, - { 76, 85, 79, 0, 0, 0}, { 77, 0, 0, 0, 0, 0}, - { 77, 65, 0, 0, 0, 0}, { 77, 65, 73, 0, 0, 0}, - { 77, 65, 78, 0, 0, 0}, { 77, 65, 78, 71, 0, 0}, - { 77, 65, 79, 0, 0, 0}, { 77, 69, 0, 0, 0, 0}, - { 77, 69, 73, 0, 0, 0}, { 77, 69, 78, 0, 0, 0}, - { 77, 69, 78, 71, 0, 0}, { 77, 73, 0, 0, 0, 0}, - { 77, 73, 65, 78, 0, 0}, { 77, 73, 65, 79, 0, 0}, - { 77, 73, 69, 0, 0, 0}, { 77, 73, 78, 0, 0, 0}, - { 77, 73, 78, 71, 0, 0}, { 77, 73, 85, 0, 0, 0}, - { 77, 79, 0, 0, 0, 0}, { 77, 79, 85, 0, 0, 0}, - { 77, 85, 0, 0, 0, 0}, { 78, 0, 0, 0, 0, 0}, - { 78, 65, 0, 0, 0, 0}, { 78, 65, 73, 0, 0, 0}, - { 78, 65, 78, 0, 0, 0}, { 78, 65, 78, 71, 0, 0}, - { 78, 65, 79, 0, 0, 0}, { 78, 69, 0, 0, 0, 0}, - { 78, 69, 73, 0, 0, 0}, { 78, 69, 78, 0, 0, 0}, - { 78, 69, 78, 71, 0, 0}, { 78, 73, 0, 0, 0, 0}, - { 78, 73, 65, 78, 0, 0}, { 78, 73, 65, 78, 71, 0}, - { 78, 73, 65, 79, 0, 0}, { 78, 73, 69, 0, 0, 0}, - { 78, 73, 78, 0, 0, 0}, { 78, 73, 78, 71, 0, 0}, - { 78, 73, 85, 0, 0, 0}, { 78, 79, 78, 71, 0, 0}, - { 78, 79, 85, 0, 0, 0}, { 78, 85, 0, 0, 0, 0}, - { 78, 85, 65, 78, 0, 0}, { 78, 85, 69, 0, 0, 0}, - { 78, 85, 78, 0, 0, 0}, { 78, 85, 79, 0, 0, 0}, - { 79, 0, 0, 0, 0, 0}, { 79, 85, 0, 0, 0, 0}, - { 80, 65, 0, 0, 0, 0}, { 80, 65, 73, 0, 0, 0}, - { 80, 65, 78, 0, 0, 0}, { 80, 65, 78, 71, 0, 0}, - { 80, 65, 79, 0, 0, 0}, { 80, 69, 73, 0, 0, 0}, - { 80, 69, 78, 0, 0, 0}, { 80, 69, 78, 71, 0, 0}, - { 80, 73, 0, 0, 0, 0}, { 80, 73, 65, 78, 0, 0}, - { 80, 73, 65, 79, 0, 0}, { 80, 73, 69, 0, 0, 0}, - { 80, 73, 78, 0, 0, 0}, { 80, 73, 78, 71, 0, 0}, - { 80, 79, 0, 0, 0, 0}, { 80, 79, 85, 0, 0, 0}, - { 80, 85, 0, 0, 0, 0}, { 81, 73, 0, 0, 0, 0}, - { 81, 73, 65, 0, 0, 0}, { 81, 73, 65, 78, 0, 0}, - { 81, 73, 65, 78, 71, 0}, { 81, 73, 65, 79, 0, 0}, - { 81, 73, 69, 0, 0, 0}, { 81, 73, 78, 0, 0, 0}, - { 81, 73, 78, 71, 0, 0}, { 81, 73, 79, 78, 71, 0}, - { 81, 73, 85, 0, 0, 0}, { 81, 85, 0, 0, 0, 0}, - { 81, 85, 65, 78, 0, 0}, { 81, 85, 69, 0, 0, 0}, - { 81, 85, 78, 0, 0, 0}, { 82, 65, 78, 0, 0, 0}, - { 82, 65, 78, 71, 0, 0}, { 82, 65, 79, 0, 0, 0}, - { 82, 69, 0, 0, 0, 0}, { 82, 69, 78, 0, 0, 0}, - { 82, 69, 78, 71, 0, 0}, { 82, 73, 0, 0, 0, 0}, - { 82, 79, 78, 71, 0, 0}, { 82, 79, 85, 0, 0, 0}, - { 82, 85, 0, 0, 0, 0}, { 82, 85, 65, 0, 0, 0}, - { 82, 85, 65, 78, 0, 0}, { 82, 85, 73, 0, 0, 0}, - { 82, 85, 78, 0, 0, 0}, { 82, 85, 79, 0, 0, 0}, - { 83, 65, 0, 0, 0, 0}, { 83, 65, 73, 0, 0, 0}, - { 83, 65, 78, 0, 0, 0}, { 83, 65, 78, 71, 0, 0}, - { 83, 65, 79, 0, 0, 0}, { 83, 69, 0, 0, 0, 0}, - { 83, 69, 78, 0, 0, 0}, { 83, 69, 78, 71, 0, 0}, - { 83, 72, 65, 0, 0, 0}, { 83, 72, 65, 73, 0, 0}, - { 83, 72, 65, 78, 0, 0}, { 83, 72, 65, 78, 71, 0}, - { 83, 72, 65, 79, 0, 0}, { 83, 72, 69, 0, 0, 0}, - { 83, 72, 69, 78, 0, 0}, { 88, 73, 78, 0, 0, 0}, - { 83, 72, 69, 78, 0, 0}, { 83, 72, 69, 78, 71, 0}, - { 83, 72, 73, 0, 0, 0}, { 83, 72, 79, 85, 0, 0}, - { 83, 72, 85, 0, 0, 0}, { 83, 72, 85, 65, 0, 0}, - { 83, 72, 85, 65, 73, 0}, { 83, 72, 85, 65, 78, 0}, - { 83, 72, 85, 65, 78, 71}, { 83, 72, 85, 73, 0, 0}, - { 83, 72, 85, 78, 0, 0}, { 83, 72, 85, 79, 0, 0}, - { 83, 73, 0, 0, 0, 0}, { 83, 79, 78, 71, 0, 0}, - { 83, 79, 85, 0, 0, 0}, { 83, 85, 0, 0, 0, 0}, - { 83, 85, 65, 78, 0, 0}, { 83, 85, 73, 0, 0, 0}, - { 83, 85, 78, 0, 0, 0}, { 83, 85, 79, 0, 0, 0}, - { 84, 65, 0, 0, 0, 0}, { 84, 65, 73, 0, 0, 0}, - { 84, 65, 78, 0, 0, 0}, { 84, 65, 78, 71, 0, 0}, - { 84, 65, 79, 0, 0, 0}, { 84, 69, 0, 0, 0, 0}, - { 84, 69, 78, 71, 0, 0}, { 84, 73, 0, 0, 0, 0}, - { 84, 73, 65, 78, 0, 0}, { 84, 73, 65, 79, 0, 0}, - { 84, 73, 69, 0, 0, 0}, { 84, 73, 78, 71, 0, 0}, - { 84, 79, 78, 71, 0, 0}, { 84, 79, 85, 0, 0, 0}, - { 84, 85, 0, 0, 0, 0}, { 84, 85, 65, 78, 0, 0}, - { 84, 85, 73, 0, 0, 0}, { 84, 85, 78, 0, 0, 0}, - { 84, 85, 79, 0, 0, 0}, { 87, 65, 0, 0, 0, 0}, - { 87, 65, 73, 0, 0, 0}, { 87, 65, 78, 0, 0, 0}, - { 87, 65, 78, 71, 0, 0}, { 87, 69, 73, 0, 0, 0}, - { 87, 69, 78, 0, 0, 0}, { 87, 69, 78, 71, 0, 0}, - { 87, 79, 0, 0, 0, 0}, { 87, 85, 0, 0, 0, 0}, - { 88, 73, 0, 0, 0, 0}, { 88, 73, 65, 0, 0, 0}, - { 88, 73, 65, 78, 0, 0}, { 88, 73, 65, 78, 71, 0}, - { 88, 73, 65, 79, 0, 0}, { 88, 73, 69, 0, 0, 0}, - { 88, 73, 78, 0, 0, 0}, { 88, 73, 78, 71, 0, 0}, - { 88, 73, 79, 78, 71, 0}, { 88, 73, 85, 0, 0, 0}, - { 88, 85, 0, 0, 0, 0}, { 88, 85, 65, 78, 0, 0}, - { 88, 85, 69, 0, 0, 0}, { 88, 85, 78, 0, 0, 0}, - { 89, 65, 0, 0, 0, 0}, { 89, 65, 78, 0, 0, 0}, - { 89, 65, 78, 71, 0, 0}, { 89, 65, 79, 0, 0, 0}, - { 89, 69, 0, 0, 0, 0}, { 89, 73, 0, 0, 0, 0}, - { 89, 73, 78, 0, 0, 0}, { 89, 73, 78, 71, 0, 0}, - { 89, 79, 0, 0, 0, 0}, { 89, 79, 78, 71, 0, 0}, - { 89, 79, 85, 0, 0, 0}, { 89, 85, 0, 0, 0, 0}, - { 89, 85, 65, 78, 0, 0}, { 89, 85, 69, 0, 0, 0}, - { 89, 85, 78, 0, 0, 0}, { 74, 85, 78, 0, 0, 0}, - { 89, 85, 78, 0, 0, 0}, { 90, 65, 0, 0, 0, 0}, - { 90, 65, 73, 0, 0, 0}, { 90, 65, 78, 0, 0, 0}, - { 90, 65, 78, 71, 0, 0}, { 90, 65, 79, 0, 0, 0}, - { 90, 69, 0, 0, 0, 0}, { 90, 69, 73, 0, 0, 0}, - { 90, 69, 78, 0, 0, 0}, { 90, 69, 78, 71, 0, 0}, - { 90, 72, 65, 0, 0, 0}, { 90, 72, 65, 73, 0, 0}, - { 90, 72, 65, 78, 0, 0}, { 90, 72, 65, 78, 71, 0}, - { 67, 72, 65, 78, 71, 0}, { 90, 72, 65, 78, 71, 0}, - { 90, 72, 65, 79, 0, 0}, { 90, 72, 69, 0, 0, 0}, - { 90, 72, 69, 78, 0, 0}, { 90, 72, 69, 78, 71, 0}, - { 90, 72, 73, 0, 0, 0}, { 83, 72, 73, 0, 0, 0}, - { 90, 72, 73, 0, 0, 0}, { 90, 72, 79, 78, 71, 0}, - { 90, 72, 79, 85, 0, 0}, { 90, 72, 85, 0, 0, 0}, - { 90, 72, 85, 65, 0, 0}, { 90, 72, 85, 65, 73, 0}, - { 90, 72, 85, 65, 78, 0}, { 90, 72, 85, 65, 78, 71}, - { 90, 72, 85, 73, 0, 0}, { 90, 72, 85, 78, 0, 0}, - { 90, 72, 85, 79, 0, 0}, { 90, 73, 0, 0, 0, 0}, - { 90, 79, 78, 71, 0, 0}, { 90, 79, 85, 0, 0, 0}, - { 90, 85, 0, 0, 0, 0}, { 90, 85, 65, 78, 0, 0}, - { 90, 85, 73, 0, 0, 0}, { 90, 85, 78, 0, 0, 0}, - { 90, 85, 79, 0, 0, 0}, { 0, 0, 0, 0, 0, 0}, - { 83, 72, 65, 78, 0, 0}, { 0, 0, 0, 0, 0, 0}, }; - - /** First and last Chinese character with known Pinyin according to zh collation */ - private static final String FIRST_PINYIN_UNIHAN = "\u963F"; - private static final String LAST_PINYIN_UNIHAN = "\u9FFF"; - - private static final Collator COLLATOR = Collator.getInstance(Locale.CHINA); - - private static HanziToPinyin sInstance; - private final boolean mHasChinaCollator; - - public static class Token { - /** - * Separator between target string for each source char - */ - public static final String SEPARATOR = " "; - - public static final int LATIN = 1; - public static final int PINYIN = 2; - public static final int UNKNOWN = 3; - - public Token() { - } - - public Token(int type, String source, String target) { - this.type = type; - this.source = source; - this.target = target; - } - - /** - * Type of this token, ASCII, PINYIN or UNKNOWN. - */ - public int type; - /** - * Original string before translation. - */ - public String source; - /** - * Translated string of source. For Han, target is corresponding Pinyin. Otherwise target is - * original string in source. - */ - public String target; - } - - protected HanziToPinyin(boolean hasChinaCollator) { - mHasChinaCollator = hasChinaCollator; - } - - public static HanziToPinyin getInstance() { - synchronized (HanziToPinyin.class) { - if (sInstance != null) { - return sInstance; - } - // Check if zh_CN collation data is available - final Locale locale[] = Collator.getAvailableLocales(); - for (int i = 0; i < locale.length; i++) { - if (locale[i].equals(Locale.CHINESE) || locale[i].equals(Locale.SIMPLIFIED_CHINESE)) { - // Do self validation just once. - if (DEBUG) { - Log.d(TAG, "Self validation. Result: " + doSelfValidation()); - } - sInstance = new HanziToPinyin(true); - return sInstance; - } - } - Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled"); - sInstance = new HanziToPinyin(false); - return sInstance; - } - } - - /** - * Validate if our internal table has some wrong value. - * - * @return true when the table looks correct. - */ - private static boolean doSelfValidation() { - char lastChar = UNIHANS[0]; - String lastString = Character.toString(lastChar); - for (char c : UNIHANS) { - if (lastChar == c) { - continue; - } - final String curString = Character.toString(c); - int cmp = COLLATOR.compare(lastString, curString); - if (cmp >= 0) { - Log.e(TAG, "Internal error in Unihan table. " + "The last string \"" + lastString - + "\" is greater than current string \"" + curString + "\"."); - return false; - } - lastString = curString; - } - return true; - } - - private Token getToken(char character) { - Token token = new Token(); - final String letter = Character.toString(character); - token.source = letter; - int offset = -1; - int cmp; - if (character < 256) { - token.type = Token.LATIN; - token.target = letter; - return token; - } else { - cmp = COLLATOR.compare(letter, FIRST_PINYIN_UNIHAN); - if (cmp < 0) { - token.type = Token.UNKNOWN; - token.target = letter; - return token; - } else if (cmp == 0) { - token.type = Token.PINYIN; - offset = 0; - } else { - cmp = COLLATOR.compare(letter, LAST_PINYIN_UNIHAN); - if (cmp > 0) { - token.type = Token.UNKNOWN; - token.target = letter; - return token; - } else if (cmp == 0) { - token.type = Token.PINYIN; - offset = UNIHANS.length - 1; - } - } - } - - token.type = Token.PINYIN; - if (offset < 0) { - int begin = 0; - int end = UNIHANS.length - 1; - while (begin <= end) { - offset = (begin + end) / 2; - final String unihan = Character.toString(UNIHANS[offset]); - cmp = COLLATOR.compare(letter, unihan); - if (cmp == 0) { - break; - } else if (cmp > 0) { - begin = offset + 1; - } else { - end = offset - 1; - } - } - } - if (cmp < 0) { - offset--; - } - StringBuilder pinyin = new StringBuilder(); - for (int j = 0; j < PINYINS[offset].length && PINYINS[offset][j] != 0; j++) { - pinyin.append((char) PINYINS[offset][j]); - } - token.target = pinyin.toString(); - if (TextUtils.isEmpty(token.target)) { - token.type = Token.UNKNOWN; - token.target = token.source; - } - return token; - } - - /** - * Convert the input to a array of tokens. The sequence of ASCII or Unknown characters without - * space will be put into a Token, One Hanzi character which has pinyin will be treated as a - * Token. If these is no China collator, the empty token array is returned. - */ - public ArrayList get(final String input) { - ArrayList tokens = new ArrayList(); - if (!mHasChinaCollator || TextUtils.isEmpty(input)) { - // return empty tokens. - return tokens; - } - final int inputLength = input.length(); - final StringBuilder sb = new StringBuilder(); - int tokenType = Token.LATIN; - // Go through the input, create a new token when - // a. Token type changed - // b. Get the Pinyin of current charater. - // c. current character is space. - for (int i = 0; i < inputLength; i++) { - final char character = input.charAt(i); - if (character == ' ') { - if (sb.length() > 0) { - addToken(sb, tokens, tokenType); - } - } else if (character < 256) { - if (tokenType != Token.LATIN && sb.length() > 0) { - addToken(sb, tokens, tokenType); - } - tokenType = Token.LATIN; - sb.append(character); - } else { - Token t = getToken(character); - if (t.type == Token.PINYIN) { - if (sb.length() > 0) { - addToken(sb, tokens, tokenType); - } - tokens.add(t); - tokenType = Token.PINYIN; - } else { - if (tokenType != t.type && sb.length() > 0) { - addToken(sb, tokens, tokenType); - } - tokenType = t.type; - sb.append(character); - } - } - } - if (sb.length() > 0) { - addToken(sb, tokens, tokenType); - } - return tokens; - } - - private void addToken( - final StringBuilder sb, final ArrayList tokens, final int tokenType) { - String str = sb.toString(); - tokens.add(new Token(tokenType, str, str)); - sb.setLength(0); - } -} \ No newline at end of file diff --git a/apptools/src/main/java/libs/espressif/location/LocationUtils.java b/apptools/src/main/java/libs/espressif/location/LocationUtils.java deleted file mode 100644 index bd6b5c4..0000000 --- a/apptools/src/main/java/libs/espressif/location/LocationUtils.java +++ /dev/null @@ -1,16 +0,0 @@ -package libs.espressif.location; - -import android.content.Context; -import android.location.LocationManager; - -public class LocationUtils { - public static boolean isLocationEnable(Context context) { - LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); - if (locationManager == null) { - return false; - } - boolean locationGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - boolean locationNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); - return locationGPS || locationNetwork; - } -} diff --git a/apptools/src/main/java/libs/espressif/log/EspLog.java b/apptools/src/main/java/libs/espressif/log/EspLog.java deleted file mode 100644 index ddbc3ba..0000000 --- a/apptools/src/main/java/libs/espressif/log/EspLog.java +++ /dev/null @@ -1,90 +0,0 @@ -package libs.espressif.log; - -import android.util.Log; - -public class EspLog { - private final String mTag; - private Level mLevel = Level.V; - - /** - * @param cls The tag will use simple name of the cls. - */ - public EspLog(Class cls) { - mTag = String.format("[%s]", cls.getSimpleName()); - } - - /** - * Set the print lowest level. It will set {@link Level#NIL} if the level is null. - * - * @param level The lowest level can print log. - */ - public void setLevel(Level level) { - if (level == null) { - mLevel = Level.NIL; - } else { - mLevel = level; - } - } - - /** - * Send a {@link Level#V} log message. - * - * @param msg The message you would like logged. - */ - public void v(String msg) { - if (mLevel.ordinal() <= Level.V.ordinal()) { - Log.v(mTag, msg); - } - } - - /** - * Send a {@link Level#V} log message. - * - * @param msg The message you would like logged. - */ - public void d(String msg) { - if (mLevel.ordinal() <= Level.D.ordinal()) { - Log.d(mTag, msg); - } - } - - /** - * Send a {@link Level#I} log message. - * - * @param msg The message you would like logged. - */ - public void i(String msg) { - if (mLevel.ordinal() <= Level.I.ordinal()) { - Log.i(mTag, msg); - } - } - - /** - * Send a {@link Level#W} log message. - * - * @param msg The message you would like logged. - */ - public void w(String msg) { - if (mLevel.ordinal() <= Level.W.ordinal()) { - Log.w(mTag, msg); - } - } - - /** - * Send a {@link Level#E} log message. - * - * @param msg The message you would like logged. - */ - public void e(String msg) { - if (mLevel.ordinal() <= Level.E.ordinal()) { - Log.e(mTag, msg); - } - } - - /** - * The level allow logged - */ - public enum Level { - V, D, I, W, E, NIL - } -} diff --git a/apptools/src/main/java/libs/espressif/net/EspHttpHeader.java b/apptools/src/main/java/libs/espressif/net/EspHttpHeader.java deleted file mode 100644 index 31fb1f0..0000000 --- a/apptools/src/main/java/libs/espressif/net/EspHttpHeader.java +++ /dev/null @@ -1,48 +0,0 @@ -package libs.espressif.net; - -public class EspHttpHeader { - private String mName; - - private String mValue; - - public EspHttpHeader(String name, String value) { - if (name == null) { - throw new NullPointerException("Header name is null"); - } - mName = name; - if (value == null) { - throw new NullPointerException("Header value is null"); - } - mValue = value; - } - - /** - * @return the http header name - */ - public String getName() { - return mName; - } - - /** - * @return the http header value - */ - public String getValue() { - return mValue; - } - - /** - * Set the http value. - */ - public void setValue(String value) { - if (value == null) { - throw new NullPointerException("Header value is null"); - } - mValue = value; - } - - @Override - public String toString() { - return String.format("name=%s, value=%s", mName, mValue); - } - -} diff --git a/apptools/src/main/java/libs/espressif/net/EspHttpParams.java b/apptools/src/main/java/libs/espressif/net/EspHttpParams.java deleted file mode 100644 index 09ace92..0000000 --- a/apptools/src/main/java/libs/espressif/net/EspHttpParams.java +++ /dev/null @@ -1,87 +0,0 @@ -package libs.espressif.net; - -public class EspHttpParams { - private int mConnectTimeout = -1; - private int mSOTimeout = -1; - private int mTryCount = 1; - private boolean mRequireResponse = true; - private boolean mTrustAllCerts = false; - - /** - * Get the connect timeout milliseconds - * - * @return the connect timeout - */ - public int getConnectTimeout() { - return mConnectTimeout; - } - - /** - * Set the connect timeout milliseconds - * - * @param timeout the connect timeout - */ - public void setConnectTimeout(int timeout) { - mConnectTimeout = timeout; - } - - /** - * Get the so timeout milliseconds - * - * @return the so timeout - */ - public int getSOTimeout() { - return mSOTimeout; - } - - /** - * Set the so timeout milliseconds - * - * @param timeout the so timeout - */ - public void setSOTimeout(int timeout) { - mSOTimeout = timeout; - } - - /** - * Get connect task try count - * - * @return connect try count - */ - public int getTryCount() { - return mTryCount; - } - - /** - * Set connect task try count. - * - * @param count connect try count - */ - public void setTryCount(int count) { - mTryCount = count; - } - - /** - * Get is response required. - * - * @return true if response is required - */ - public boolean isRequireResponse() { - return mRequireResponse; - } - - /** - * Set response is requered, if false, the connection will disconnect immediately after posting http request. - */ - public void setRequireResponse(boolean require) { - mRequireResponse = require; - } - - public boolean isTrustAllCerts() { - return mTrustAllCerts; - } - - public void setTrustAllCerts(boolean trustAllCerts) { - mTrustAllCerts = trustAllCerts; - } -} diff --git a/apptools/src/main/java/libs/espressif/net/EspHttpResponse.java b/apptools/src/main/java/libs/espressif/net/EspHttpResponse.java deleted file mode 100644 index d4b1e93..0000000 --- a/apptools/src/main/java/libs/espressif/net/EspHttpResponse.java +++ /dev/null @@ -1,157 +0,0 @@ -package libs.espressif.net; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class EspHttpResponse { - private final Map mHeaders = new HashMap<>(); - - private int mCode; - private String mMessage; - private byte[] mContent; - - /** - * Get http code - * - * @return http status - */ - public int getCode() { - return mCode; - } - - /** - * Set http code - * - * @param code http status - */ - public void setCode(int code) { - mCode = code; - } - - /** - * Get http message - * - * @return http message - */ - public String getMessage() { - return mMessage; - } - - /** - * Set http message - * - * @param msg http message - */ - public void setMessage(String msg) { - mMessage = msg; - } - - /** - * Get http content data - * - * @return http content data - */ - public byte[] getContent() { - return mContent; - } - - /** - * Set http content data - * - * @param content http content data - */ - public void setContent(byte[] content) { - mContent = content; - } - - /** - * Get http content string - * - * @return http content string - */ - public String getContentString() { - if (mContent == null) { - return null; - } else { - return new String(mContent); - } - } - - /** - * Get http content json - * - * @return http content json - * @throws JSONException if content is not json format - */ - public JSONObject getContentJSON() throws JSONException { - if (mContent == null) { - return null; - } else { - return new JSONObject(new String(mContent)); - } - } - - /** - * Set the header - * - * @param header the header - */ - public void setHeader(EspHttpHeader header) { - if (header == null) { - return; - } - - synchronized (mHeaders) { - String key = header.getName().toLowerCase(); - mHeaders.put(key, header); - } - } - - /** - * Get all headers - * - * @return all headers - */ - public List getHeaders() { - synchronized (mHeaders) { - return new ArrayList<>(mHeaders.values()); - } - } - - /** - * Set the headers - * - * @param headers the headers - */ - public void setHeaders(Collection headers) { - synchronized (mHeaders) { - for (EspHttpHeader header : headers) { - String key = header.getName().toLowerCase(); - mHeaders.put(key, header); - } - } - } - - /** - * Get the requested name header - * - * @param name the name of the header - * @return the requested header - */ - public EspHttpHeader findHeader(String name) { - synchronized (mHeaders) { - return mHeaders.get(name.toLowerCase()); - } - } - - public String findHeaderValue(String name) { - EspHttpHeader header = findHeader(name); - return header == null ? null : header.getValue(); - } -} diff --git a/apptools/src/main/java/libs/espressif/net/EspHttpUtils.java b/apptools/src/main/java/libs/espressif/net/EspHttpUtils.java deleted file mode 100644 index d78572e..0000000 --- a/apptools/src/main/java/libs/espressif/net/EspHttpUtils.java +++ /dev/null @@ -1,448 +0,0 @@ -package libs.espressif.net; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TreeMap; - -import javax.net.ssl.HttpsURLConnection; - -import libs.espressif.log.EspLog; - -public class EspHttpUtils { - public static final String CONNECTION = "Connection"; - public static final String CONTENT_TYPE = "Content-Type"; - public static final String CONTENT_LENGTH = "Content-Length"; - public static final String TRANSFER_ENCODING = "Transfer-Encoding"; - - public static final String KEEP_ALIVE = "Keep-Alive"; - public static final String CLOSE = "close"; - public static final String APPLICATION_JSON = "application/json"; - public static final String CHUNKED = "chunked"; - - public static final String HTTP = "http"; - public static final String HTTPS = "https"; - - public static final EspHttpHeader HEADER_KEEP_ALIVE = new ConstHeader(CONNECTION, KEEP_ALIVE); - public static final EspHttpHeader HEADER_CONTENT_JSON = new ConstHeader(CONTENT_TYPE, APPLICATION_JSON); - public static final EspHttpHeader HEADER_CHUNKED = new ConstHeader(TRANSFER_ENCODING, CHUNKED); - - private static final EspLog log = new EspLog(EspHttpUtils.class); - - public static final String METHOD_GET = "GET"; - public static final String METHOD_POST = "POST"; - public static final String METHOD_HEAD = "HEAD"; - public static final String METHOD_OPTIONS = "OPTIONS"; - public static final String METHOD_PUT = "PUT"; - public static final String METHOD_DELETE = "DELETE"; - public static final String METHOD_TRACE = "TRACE"; - - private static final int TIMEOUT_CONNECT = 4000; - private static final int TIMEOUT_SO_GET = 5000; - private static final int TIMEOUT_SO_POST = 5000; - private static final int TIMEOUT_NO_RESPONSE = 1; - - private static final char[] SPEC_CHARS = {'+', '*', ':'}; - /** - * Execute Http Get request. - * - * @param url target url - * @param headers http headers - * @return response. null is failed. - */ - public static EspHttpResponse Get(String url, EspHttpParams params, EspHttpHeader... headers) { - return execute(url, METHOD_GET, null, params, headers); - } - - /** - * Execute Http Post request. - * - * @param url target url - * @param content content bytes - * @param headers http headers - * @return response. null is failed. - */ - public static EspHttpResponse Post(String url, byte[] content, EspHttpParams params, EspHttpHeader... headers) { - return execute(url, METHOD_POST, content, params, headers); - } - - /** - * Execute Http Put request. - * - * @param url target url - * @param content content bytes - * @param headers http headers - * @return response. null is failed. - */ - public static EspHttpResponse Put(String url, byte[] content, EspHttpParams params, EspHttpHeader... headers) { - return execute(url, METHOD_PUT, content, params, headers); - } - - /** - * Execute Http Delete request. - * - * @param url target url - * @param content content bytes - * @param headers http headers - * @return response. null is failed. - */ - public static EspHttpResponse Delete(String url, byte[] content, EspHttpParams params, EspHttpHeader... headers) { - return execute(url, METHOD_DELETE, content, params, headers); - } - - private static EspHttpResponse execute(String url, String method, byte[] content, - EspHttpParams params, EspHttpHeader... headers) { - EspHttpResponse response = null; - - int tryCount = 1; - boolean requireResp = true; - if (params != null) { - tryCount = Math.max(tryCount, params.getTryCount()); - requireResp = params.isRequireResponse(); - } - - for (int i = 0; i < tryCount; i++) { - if (Thread.currentThread().isInterrupted()) { - return null; - } - HttpURLConnection connection = createURLConnection(url, method, params, headers); - response = executeHttpRequest(connection, content, requireResp); - if (connection != null) { - connection.disconnect(); - } - if (response != null) { - break; - } - } - return response; - } - - private static HttpURLConnection createURLConnection(String url, String method, EspHttpParams params, EspHttpHeader... headers) { - try { - URL targetURL = new URL(url); - String file = targetURL.getFile(); - if (file != null) { - for (char c : SPEC_CHARS) { - String asciiStr = String.format(Locale.ENGLISH, "%%%02X", (int)c); - file = file.replace(String.valueOf(c), asciiStr); - } - targetURL = new URL(targetURL.getProtocol(), targetURL.getHost(), targetURL.getPort(), file); - } - HttpURLConnection connection = (HttpURLConnection) targetURL.openConnection(); - connection.setRequestMethod(method); - int timeoutConn = -1; - int timeoutSO = -1; - for (EspHttpHeader head : headers) { - if (head == null) { - continue; - } - - connection.addRequestProperty(head.getName(), head.getValue()); - } - String connValue = connection.getRequestProperty(CONNECTION); - if (connValue == null) { - connection.addRequestProperty(CONNECTION, CLOSE); - } - - if (params != null) { - timeoutConn = params.getConnectTimeout(); - timeoutSO = params.getSOTimeout(); - } - if (timeoutConn <= 0) { - timeoutConn = TIMEOUT_CONNECT; - } - connection.setConnectTimeout(timeoutConn); - if (timeoutSO < 0) { - timeoutSO = method.equals(METHOD_GET) ? TIMEOUT_SO_GET : TIMEOUT_SO_POST; - } - connection.setReadTimeout(timeoutSO); - - if (params != null && params.isTrustAllCerts() - && targetURL.getProtocol().toLowerCase(Locale.ENGLISH).equals(HTTPS)) { - HttpsURLConnection httpsConn = (HttpsURLConnection) connection; - SSLUtils.trustAllHosts(httpsConn); - httpsConn.setHostnameVerifier(SSLUtils.DO_NOT_VERIFY); - } - - return connection; - } catch (IOException e) { - e.printStackTrace(); - - return null; - } - } - - private static EspHttpResponse executeHttpRequest(HttpURLConnection connection, byte[] content, boolean requireResponse) { - if (connection == null) { - return null; - } - - if (!requireResponse) { - connection.setReadTimeout(TIMEOUT_NO_RESPONSE); - } - - try { - log.d("executeHttpRequest url = " + connection.getURL().toString()); - Map> requestProperties = connection.getRequestProperties(); - for (Map.Entry> entry : requestProperties.entrySet()) { - String key = entry.getKey(); - for (String value : entry.getValue()) { - log.d(key + ": " + value); - } - } - if (!isEmpty(content)) { - connection.setDoOutput(true); - log.d("executeHttpRequest execute write " + new String(content)); - connection.setFixedLengthStreamingMode(content.length); - connection.getOutputStream().write(content); - } else { - log.d("executeHttpRequest execute connect"); - connection.setFixedLengthStreamingMode(0); - } - } catch (IOException e) { - connection.disconnect(); - log.w("executeHttpRequest Connect failed"); - return null; - } - - EspHttpResponse response; - try { - response = readResponse(connection); - } catch (IOException e) { - log.w("executeHttpRequest read response IOException " + e.getMessage()); - if (requireResponse) { - response = null; - } else { - response = new EspHttpResponse(); - } - } finally { - connection.disconnect(); - } - - return response; - } - - private static EspHttpResponse readResponse(HttpURLConnection connection) throws IOException { - EspHttpResponse response = new EspHttpResponse(); - - // Get http code and message - int code = connection.getResponseCode(); - String msg = connection.getResponseMessage(); - response.setCode(code); - response.setMessage(msg); - - // Get http headers - Map> respHeaders = connection.getHeaderFields(); - for (Map.Entry> entry : respHeaders.entrySet()) { - String key = entry.getKey(); - if (key == null) { - String statusHeader = entry.getValue().get(0); - log.i(statusHeader); - continue; - } - List values = entry.getValue(); - if (values == null || values.isEmpty()) { - continue; - } - StringBuilder value = new StringBuilder(); - int index = 0; - for (String v : values) { - value.append(v); - if (index < values.size() - 1) { - value.append(';'); - } - index++; - } - - EspHttpHeader respHeader = new EspHttpHeader(key, value.toString()); - response.setHeader(respHeader); - log.i(key + ": " + value); - } - - // Get http content - ByteArrayOutputStream contentOS = new ByteArrayOutputStream(); - InputStream is = connection.getErrorStream() == null ? - connection.getInputStream() : connection.getErrorStream(); - try { - for (int data = is.read(); data != -1; data = is.read()) { - contentOS.write(data); - } - } catch (IOException e) { - e.printStackTrace(); - } - if (contentOS.size() > 0) { - response.setContent(contentOS.toByteArray()); - log.i(response.getContentString()); - } - contentOS.close(); - - return response; - } - - public static EspHttpResponse getResponseWithFixedLengthData(byte[] data) { - if (isEmpty(data)) { - log.w("null data"); - return null; - } - - EspHttpResponse result = new EspHttpResponse(); - - ByteArrayInputStream dataIS = new ByteArrayInputStream(data); - ByteArrayOutputStream headerOS = new ByteArrayOutputStream(); - ByteArrayOutputStream contentOS = new ByteArrayOutputStream(); - boolean readContent = false; - int last1, last2, last3, last4; - last1 = last2 = last3 = last4 = -1; - for (int read = dataIS.read(); read != -1; read = dataIS.read()) { - if (!readContent) { - headerOS.write(read); - - last1 = last2; - last2 = last3; - last3 = last4; - last4 = read; - if (last1 == '\r' && last2 == '\n' && last3 == '\r' && last4 == '\n') { - // Header End - readContent = true; - } - } else { - contentOS.write(read); - } - } - - String headersStr = new String(headerOS.toByteArray()); - String[] headers = headersStr.split("\r\n"); - if (headers.length <= 0) { - log.w("no status header"); - return null; - } - String statusHeader = headers[0]; - String[] statusValues = statusHeader.split(" "); - if (statusValues.length < 3) { - log.w("invalid status header " + statusHeader); - return null; - } else if (!statusValues[0].toUpperCase().startsWith("HTTP")) { - log.w("invalid status protocol " + statusHeader); - return null; - } else { - try { - int statusCode = Integer.parseInt(statusValues[1]); - result.setCode(statusCode); - } catch (NumberFormatException nfe) { - log.w("invalid status code " + statusHeader); - return null; - } - - StringBuilder statusMessage = new StringBuilder(); - for (int statusIndex = 2; statusIndex < statusValues.length; statusIndex ++) { - statusMessage.append(statusValues[statusIndex]); - if (statusIndex < statusValues.length - 1) { - statusMessage.append(" "); - } - } - result.setMessage(statusMessage.toString()); - } - - for (int i = 1; i < headers.length; i++) { - String headerStr = headers[i]; - int index = headerStr.indexOf(": "); - if (index == -1) { - log.w("invalid header : " + headerStr); - return null; - } - String name = headerStr.substring(0, index); - String value = headerStr.substring(index + 2, headerStr.length()); - EspHttpHeader h = new EspHttpHeader(name, value); - result.setHeader(h); - } - - if (contentOS.size() > 0) { - result.setContent(contentOS.toByteArray()); - } - - return result; - } - - private static boolean isEmpty(byte[] data) { - return data == null || data.length == 0; - } - - private final static class ConstHeader extends EspHttpHeader { - ConstHeader(String name, String value) { - super(name, value); - } - - @Override - public void setValue(String value) { - throw new IllegalArgumentException("Esp const header forbid change value"); - } - } - - public static Map getQueryMap(String url) - throws URISyntaxException, UnsupportedEncodingException { - URI uri = new URI(url); - String query = uri.getQuery(); - final String[] pairs = query.split("&"); - TreeMap queryMap = new TreeMap<>(); - for (String pair : pairs) { - final int idx = pair.indexOf("="); - final String key = idx > 0 ? pair.substring(0, idx) : pair; - if (!queryMap.containsKey(key)) { - queryMap.put(key, URLDecoder.decode(pair.substring(idx + 1), Charset.defaultCharset().name())); - } - } - return queryMap; - } - - public static String composeUrl(String protocol, String endPoint, Map queries) - throws UnsupportedEncodingException { - Map mapQueries = queries; - StringBuilder urlBuilder = new StringBuilder(""); - urlBuilder.append(protocol); - urlBuilder.append("://").append(endPoint); - if (-1 == urlBuilder.indexOf("?")) { - urlBuilder.append("/?"); - } - urlBuilder.append(concatQueryString(mapQueries)); - return urlBuilder.toString(); - } - - public static String concatQueryString(Map parameters) - throws UnsupportedEncodingException { - if (null == parameters) { - return null; - } - StringBuilder urlBuilder = new StringBuilder(""); - for (Map.Entry entry : parameters.entrySet()) { - String key = entry.getKey(); - String val = entry.getValue(); - urlBuilder.append(encode(key)); - if (val != null) { - urlBuilder.append("=").append(encode(val)); - } - urlBuilder.append("&"); - } - int strIndex = urlBuilder.length(); - if (parameters.size() > 0) { - urlBuilder.deleteCharAt(strIndex - 1); - } - return urlBuilder.toString(); - } - - public static String encode(String value) - throws UnsupportedEncodingException { - return URLEncoder.encode(value, "UTF-8"); - } -} diff --git a/apptools/src/main/java/libs/espressif/net/NetUtil.java b/apptools/src/main/java/libs/espressif/net/NetUtil.java deleted file mode 100644 index da11d45..0000000 --- a/apptools/src/main/java/libs/espressif/net/NetUtil.java +++ /dev/null @@ -1,475 +0,0 @@ -package libs.espressif.net; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.DhcpInfo; -import android.net.NetworkInfo; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Locale; - -import libs.espressif.app.SdkUtil; - -public class NetUtil { - public static final int WIFI_SECURITY_OPEN = 0x00; - public static final int WIFI_SECURITY_WEP = 0x01; - public static final int WIFI_SECURITY_WPA = 0x02; - - public static final String WIFI_SSID_NONE = ""; - - public static boolean isNetworkAvailable(Context context) { - ConnectivityManager cm = (ConnectivityManager) context.getApplicationContext() - .getSystemService(Context.CONNECTIVITY_SERVICE); - assert cm != null; - int[] types = new int[]{ConnectivityManager.TYPE_WIFI, ConnectivityManager.TYPE_MOBILE}; - for (int type : types) { - NetworkInfo info = cm.getNetworkInfo(type); - if (info != null && info.isAvailable()) { - return true; - } - } - - return false; - } - - public static InetAddress getWifiIpAddress(WifiManager wifi) { - InetAddress result = null; - try { - // default to Android localhost - result = InetAddress.getByName("10.0.0.2"); - - // figure out our wifi address, otherwise bail - WifiInfo wifiinfo = wifi.getConnectionInfo(); - int intaddr = wifiinfo.getIpAddress(); - byte[] byteaddr = new byte[]{(byte) (intaddr & 0xff), (byte) (intaddr >> 8 & 0xff), - (byte) (intaddr >> 16 & 0xff), (byte) (intaddr >> 24 & 0xff)}; - result = InetAddress.getByAddress(byteaddr); - } catch (UnknownHostException ex) { - ex.printStackTrace(); - } - - return result; - } - - public static String getIpStringForInt(int ip) { - return String.format(Locale.ENGLISH, "%d.%d.%d.%d", - ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff); - } - - public static byte[] getIpBytesForInt(int ip) { - return new byte[]{ - (byte) (ip & 0xff), - (byte) ((ip >> 8) & 0xff), - (byte) ((ip >> 16) & 0xff), - (byte) ((ip >> 24) & 0xff) - }; - } - - public static byte[] getMacBytesForString(String mac) { - byte[] result = new byte[6]; - String[] splits = mac.split(":"); - for (int i = 0; i < result.length; i++) { - result[i] = (byte) Integer.parseInt(splits[i], 16); - } - - return result; - } - - /** - * Get the ssid of the connected access point. - * - * @param context The Application Context. - * @return null if no wifi connection. - */ - public static String getCurrentConnectSSID(Context context) { - WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - assert wm != null; - WifiInfo connection = wm.getConnectionInfo(); - boolean isWifiConnected = connection != null && connection.getNetworkId() != -1; - if (isWifiConnected) { - String ssid = connection.getSSID(); - if (SdkUtil.isAtLeastJ_16()) { - if (ssid.startsWith("\"") && ssid.endsWith("\"")) { - ssid = ssid.substring(1, ssid.length() - 1); - } - } - - return ssid; - } else { - return null; - } - } - - /** - * Get the bssid of the connected access point. - * - * @param context The Application Context. - * @return null if no wifi connection. - */ - public static String getCurrentConnectBSSID(Context context) { - WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - assert wm != null; - WifiInfo connection = wm.getConnectionInfo(); - boolean isWifiConnected = connection != null && connection.getNetworkId() != -1; - if (isWifiConnected) { - return connection.getBSSID(); - } else { - return null; - } - } - - /** - * Get current ip on the connected access point. - * - * @param context The Application Context. - * @return Current connected ip, null is disconnected. - */ - public static String getCurrentConnectIP(Context context) { - WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - assert wm != null; - WifiInfo connection = wm.getConnectionInfo(); - boolean isWifiConnected = connection != null && connection.getNetworkId() != -1; - if (isWifiConnected) { - return getIpString(connection.getIpAddress()); - } else { - return null; - } - } - - private static String getIpString(int ip) { - StringBuilder ipSB = new StringBuilder(); - for (int i = 0; i < 4; i++) { - ipSB.append((ip >> (i * 8)) & 0xff); - if (i < 3) { - ipSB.append('.'); - } - } - - return ipSB.toString(); - } - - /** - * Get the connection information of the connected access point. - * - * @param context The Application Context. - * @return An information string array with [ssid bssid ipAddress frequency], or null if disconnected - */ - public static String[] getCurrentConnectionInfo(Context context) { - WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - assert wm != null; - WifiInfo connection = wm.getConnectionInfo(); - boolean isWifiConnected = connection != null && connection.getNetworkId() != -1; - if (isWifiConnected) { - String[] result = new String[4]; - - String ssid = connection.getSSID(); - if (ssid.startsWith("\"") && ssid.endsWith("\"")) { - ssid = ssid.substring(1, ssid.length() - 1); - } - - result[0] = ssid; - result[1] = connection.getBSSID(); - result[2] = getIpString(connection.getIpAddress()); - if (SdkUtil.isAtLeastL_21()) { - result[3] = String.valueOf(connection.getFrequency()); - } - return result; - } else { - return null; - } - } - - /** - * Check is connected the wifi. - * - * @param context The Application Content. - * @return Whether connected the wifi. - */ - public static boolean isWifiConnected(Context context) { - WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - if (wm == null) { - return false; - } - WifiInfo connection = wm.getConnectionInfo(); - return connection != null && connection.getNetworkId() != -1 && !WIFI_SSID_NONE.equals(connection.getSSID()); - } - - /** - * Check is the frequency 5G channel or not. - * - * @param frequency The frequency need check - * @return true if the frequency is 5G - */ - public static boolean is5GHz(int frequency) { - return frequency > 4900 && frequency < 5900; - } - - /** - * Check is the frequency 2.4G channel or not. - * - * @param frequency The frequency need check - * @return true if the frequency is 2.4G - */ - public static boolean is24GHz(int frequency) { - return frequency > 2400 && frequency < 2500; - } - - /** - * Get the channel by the frequency. - * - * @param frequency The wifi frequency. - * @return The wifi channel. -1 is unknown channel. - */ - public static int getWifiChannel(int frequency) { - switch (frequency) { - case 2412: - return 1; - case 2417: - return 2; - case 2422: - return 3; - case 2427: - return 4; - case 2432: - return 5; - case 2437: - return 6; - case 2442: - return 7; - case 2447: - return 8; - case 2452: - return 9; - case 2457: - return 10; - case 2462: - return 11; - case 2467: - return 12; - case 2472: - return 13; - case 2484: - return 14; - case 5035: - return 7; - case 5040: - return 8; - case 5045: - return 9; - case 5055: - return 11; - case 5060: - return 12; - case 5080: - return 16; - case 5170: - return 34; - case 5180: - return 36; - case 5190: - return 38; - case 5200: - return 40; - case 5210: - return 42; - case 5220: - return 44; - case 5230: - return 46; - case 5240: - return 48; - case 5260: - return 52; - case 5280: - return 56; - case 5300: - return 60; - case 5320: - return 64; - case 5500: - return 100; - case 5520: - return 104; - case 5540: - return 108; - case 5560: - return 112; - case 5580: - return 116; - case 5600: - return 120; - case 5620: - return 124; - case 5640: - return 128; - case 5660: - return 132; - case 5680: - return 136; - case 5700: - return 140; - case 5745: - return 149; - case 5765: - return 153; - case 5785: - return 157; - case 5805: - return 161; - case 5825: - return 165; - case 4915: - return 183; - case 4920: - return 184; - case 4925: - return 185; - case 4935: - return 187; - case 4940: - return 188; - case 4945: - return 189; - case 4960: - return 192; - case 4980: - return 196; - default: - return -1; - } - } - - public static InetAddress getBroadcastAddress(Context context) throws UnknownHostException { - WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - assert wifi != null; - DhcpInfo dhcp = wifi.getDhcpInfo(); - if (dhcp == null) { - return InetAddress.getByName("255.255.255.255"); - } - int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask; - byte[] quads = new byte[4]; - for (int k = 0; k < 4; k++) - quads[k] = (byte) ((broadcast >> k * 8) & 0xFF); - return InetAddress.getByAddress(quads); - } - - public static byte[] getOriginalSsidBytes(WifiInfo info) { - try { - Method method = info.getClass().getMethod("getWifiSsid"); - if (method == null) { - return null; - } - method.setAccessible(true); - Object wifiSsid = method.invoke(info); - if (wifiSsid == null) { - return null; - } - method = wifiSsid.getClass().getMethod("getOctets"); - if (method == null) { - return null; - } - method.setAccessible(true); - return (byte[]) method.invoke(wifiSsid); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (NullPointerException e) { - e.printStackTrace(); - } - return null; - } - - public static byte[] getOriginalSsidBytes(ScanResult scanResult) { - try { - Field field = scanResult.getClass().getField("wifiSsid"); - if (field == null) { - return null; - } - field.setAccessible(true); - Object wifiSsid = field.get(scanResult); - if (wifiSsid == null) { - return null; - } - Method method = wifiSsid.getClass().getMethod("getOctets"); - if (method == null) { - return null; - } - method.setAccessible(true); - return (byte[]) method.invoke(wifiSsid); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - - return null; - } - - public static WifiConfiguration newWifiConfigration(int security, String ssid, String password, boolean hide) { - WifiConfiguration config = new WifiConfiguration(); - config.allowedAuthAlgorithms.clear(); - config.allowedGroupCiphers.clear(); - config.allowedKeyManagement.clear(); - config.allowedPairwiseCiphers.clear(); - config.allowedProtocols.clear(); - - config.SSID = "\"" + ssid + "\""; // ## - config.hiddenSSID = hide; // ## - config.status = WifiConfiguration.Status.ENABLED; - - switch (security) { - case WIFI_SECURITY_OPEN: // OPEN - config.wepKeys[0] = "\"" + "\""; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.wepTxKeyIndex = 0; - break; - case WIFI_SECURITY_WEP: // WEP - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); - if (password != null && password.length() > 0) { - int length = password.length(); - // WEP-40, WEP-104, and 256-bit WEP (WEP-232?) - if ((length == 10 || length == 26 || length == 58) && password.matches("[0-9A-Fa-f]*")) { - config.wepKeys[0] = password; // ## - } else { - config.wepKeys[0] = '"' + password + '"'; // ## - } - } - break; - case WIFI_SECURITY_WPA: // WPA - config.preSharedKey = "\"" + password + "\""; // ## - - config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - // for WPA - config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); - // for WPA2 - config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - break; - default: - return null; - } - return config; - } -} diff --git a/apptools/src/main/java/libs/espressif/net/SSLUtils.java b/apptools/src/main/java/libs/espressif/net/SSLUtils.java deleted file mode 100644 index 79f7f1c..0000000 --- a/apptools/src/main/java/libs/espressif/net/SSLUtils.java +++ /dev/null @@ -1,104 +0,0 @@ -package libs.espressif.net; - - -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -public class SSLUtils { - public static void trustAllHttpsCertificates() throws Exception { - TrustManager[] trustAllCerts = new TrustManager[1]; - TrustManager tm = new miTM(); - trustAllCerts[0] = tm; - SSLContext sc = SSLContext.getInstance("SSL"); - sc.init(null, trustAllCerts, null); - HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - } - - public static void ignoreSsl() throws Exception { - HostnameVerifier hv = new HostnameVerifier() { - public boolean verify(String urlHostName, SSLSession session) { - System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost()); - return true; - } - }; - trustAllHttpsCertificates(); - HttpsURLConnection.setDefaultHostnameVerifier(hv); - } - - static class miTM implements TrustManager, X509TrustManager { - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - public boolean isServerTrusted(X509Certificate[] certs) { - return true; - } - - public boolean isClientTrusted(X509Certificate[] certs) { - return true; - } - - public void checkServerTrusted(X509Certificate[] certs, String authType) - throws CertificateException { - return; - } - - public void checkClientTrusted(X509Certificate[] certs, String authType) - throws CertificateException { - return; - } - } - - /** - * Cover defaoult java certs - */ - private static final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new java.security.cert.X509Certificate[]{}; - } - - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - } - }}; - - /** - * Skip host check - */ - public static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() { - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - - /** - * Trust all - * - * @param connection - * @return - */ - public static SSLSocketFactory trustAllHosts(HttpsURLConnection connection) { - SSLSocketFactory oldFactory = connection.getSSLSocketFactory(); - try { - SSLContext sc = SSLContext.getInstance("SSL"); - sc.init(null, trustAllCerts, new java.security.SecureRandom()); - SSLSocketFactory newFactory = sc.getSocketFactory(); - connection.setSSLSocketFactory(newFactory); - } catch (Exception e) { - e.printStackTrace(); - } - return oldFactory; - } -} diff --git a/apptools/src/main/java/libs/espressif/security/EspECC.java b/apptools/src/main/java/libs/espressif/security/EspECC.java deleted file mode 100644 index 33d05c3..0000000 --- a/apptools/src/main/java/libs/espressif/security/EspECC.java +++ /dev/null @@ -1,61 +0,0 @@ -package libs.espressif.security; - -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPrivateKeySpec; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; - -public class EspECC { - private ECPrivateKey mPrivateKey; - private ECPublicKey mPublicKey; - - public EspECC() { - KeyPairGenerator keyPairGenerator = null; - try { - keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC"); - keyPairGenerator.initialize(256); - KeyPair kp = keyPairGenerator.generateKeyPair(); - - mPublicKey = (ECPublicKey) kp.getPublic(); - mPrivateKey = (ECPrivateKey) kp.getPrivate(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (NoSuchProviderException e) { - e.printStackTrace(); - } - } - - public ECPublicKey getPublicKey() { - return mPublicKey; - } - - public ECPrivateKey getPrivateKey() { - return mPrivateKey; - } - - public BigInteger getOrder() { - return mPublicKey.getParams().getOrder(); - } - - public BigInteger getPublicKeyX() { - return mPublicKey.getW().getAffineX(); - } - - public BigInteger getPublicKeyY() { - return mPublicKey.getW().getAffineY(); - } - - public BigInteger getPrivateKeyS() { - return mPrivateKey.getS(); - } -} diff --git a/apptools/src/main/java/libs/espressif/security/EspMD5.java b/apptools/src/main/java/libs/espressif/security/EspMD5.java deleted file mode 100644 index 1bb54a3..0000000 --- a/apptools/src/main/java/libs/espressif/security/EspMD5.java +++ /dev/null @@ -1,42 +0,0 @@ -package libs.espressif.security; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class EspMD5 { - - public static byte[] getMD5Byte(byte[] data) { - try { - MessageDigest digest = MessageDigest.getInstance("md5"); - digest.update(data); - return digest.digest(); - } catch (NoSuchAlgorithmException | NullPointerException e) { - e.printStackTrace(); - } - - return null; - } - - public static String getMD5String(byte[] data) { - try { - MessageDigest digest = MessageDigest.getInstance("md5"); - digest.update(data); - byte[] result = digest.digest(); - StringBuilder sb = new StringBuilder(); - for (byte b : result) { - int number = b & 0xff; - String str = Integer.toHexString(number); - if (str.length() == 1) { - sb.append("0"); - } - sb.append(str); - } - - return sb.toString(); - } catch (NoSuchAlgorithmException | NullPointerException e) { - e.printStackTrace(); - } - - return ""; - } -} diff --git a/apptools/src/main/java/libs/espressif/security/EspPBKDF2.java b/apptools/src/main/java/libs/espressif/security/EspPBKDF2.java deleted file mode 100644 index 1dc60b4..0000000 --- a/apptools/src/main/java/libs/espressif/security/EspPBKDF2.java +++ /dev/null @@ -1,24 +0,0 @@ -package libs.espressif.security; - -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; - -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; - -public class EspPBKDF2 { - public static byte[] getPBKDF2Bytes(char[] password, byte[] salt, int iterationCount, int keyLength) { - PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength); - try { - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); - SecretKey secretKey = keyFactory.generateSecret(keySpec); - return secretKey.getEncoded(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeySpecException e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/apptools/src/main/java/libs/espressif/security/EspRSA.java b/apptools/src/main/java/libs/espressif/security/EspRSA.java deleted file mode 100644 index 72bd728..0000000 --- a/apptools/src/main/java/libs/espressif/security/EspRSA.java +++ /dev/null @@ -1,115 +0,0 @@ -package libs.espressif.security; - -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; - -public class EspRSA { - private static final String ALGORITHM = "RSA"; - - private static RSAPublicKey getPublicKey(byte[] keyData) - throws NoSuchAlgorithmException, InvalidKeySpecException { - KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); - X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyData); - return (RSAPublicKey) keyFactory.generatePublic(x509KeySpec); - } - - private static RSAPrivateKey getPrivateKey(byte[] keyData) - throws NoSuchAlgorithmException, InvalidKeySpecException { - KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); - PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyData); - return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); - } - - public static byte[] encryptWithPublicKey(byte[] publicKey, byte[] data) { - try { - PublicKey rsaPB = getPublicKey(publicKey); - - Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); - cipher.init(Cipher.ENCRYPT_MODE, rsaPB); - - return cipher.doFinal(data); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (InvalidKeySpecException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - } - - return null; - } - - public static byte[] decryptWithPrivateKey(byte[] privateKey, byte[] data) { - try { - Key rsaPV = getPrivateKey(privateKey); - - Cipher cipher = Cipher.getInstance(ALGORITHM); - cipher.init(Cipher.DECRYPT_MODE, rsaPV); - - return cipher.doFinal(data); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeySpecException e) { - e.printStackTrace(); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - } - - return null; - } - - public static byte[] decryptWithPrivateKey(PrivateKey privateKey, byte[] data) { - try { - Cipher cipher = Cipher.getInstance(ALGORITHM); - cipher.init(Cipher.DECRYPT_MODE, privateKey); - - return cipher.doFinal(data); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - } - - return null; - } - -// public static PrivateKey getPrivateKeyWithPKCS1(byte[] privateKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { -// RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(privateKeyBytes)); -// RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent()); -// KeyFactory keyFactory= KeyFactory.getInstance("RSA"); -// PrivateKey priKey= keyFactory.generatePrivate(rsaPrivKeySpec); -// return priKey; -// } -} diff --git a/apptools/src/main/java/libs/espressif/utils/DataUtil.java b/apptools/src/main/java/libs/espressif/utils/DataUtil.java deleted file mode 100644 index 5e4dad2..0000000 --- a/apptools/src/main/java/libs/espressif/utils/DataUtil.java +++ /dev/null @@ -1,341 +0,0 @@ -package libs.espressif.utils; - -import java.util.ArrayList; -import java.util.List; - -public class DataUtil { - - public static void printBytes(byte[] bytes) { - printBytes(bytes, 20); - } - - /** - * Print byte array row by row. - */ - public static void printBytes(byte[] bytes, int colCount) { - StringBuilder sb = new StringBuilder(":\n"); - for (int i = 0; i < colCount; i++) { - if (i < 10) { - sb.append(0); - } - sb.append(i).append('\t'); - } - sb.append('\n'); - - for (int i = 0; i < colCount; i++) { - sb.append("-\t"); - } - sb.append('\n'); - - for (int i = 0; i < bytes.length; i++) { - sb.append(Integer.toHexString(bytes[i] & 0xff)).append('\t'); - if (i % colCount == (colCount - 1)) { - sb.append("| ").append(i / colCount).append('\n'); - } - } - - System.out.println(sb.toString()); - } - - public static boolean equals(byte[] data1, byte[] data2) { - if (data1 == data2) { - return true; - } - if (data1 == null || data2 == null) { - return false; - } - - if (data1.length != data2.length) { - return false; - } - - for (int i = 0; i < data1.length; i++) { - if (data1[i] != data2[i]) { - return false; - } - } - - return true; - } - - public static byte[] longToBigEndianBytes(long value, int bytesLength) { - byte[] result = new byte[bytesLength]; - int offset = 0; - for (int i = bytesLength - 1; i >= 0; i--) { - result[i] = (byte) ((value >> (8 * offset)) & 0xff); - offset++; - } - return result; - } - - public static byte[] longToLittleEndianBytes(long value, int byteSize) { - byte[] result = new byte[byteSize]; - for (int i = 0; i < byteSize; i++) { - result[i] = (byte) ((value >> (8 * i)) & 0xff); - } - return result; - } - - public static long bigEndianBytesToLong(byte[] bytes) { - long result = 0L; - for (int index = bytes.length - 1; index >= 0L; index--) { - long l = bytes[index] & 0xffL; - int offset = (bytes.length - 1 - index) * 8; - - result |= (l << offset); - } - return result; - } - - public static long littleEndianBytesToLong(byte[] bytes) { - long result = 0L; - for (int i = 0; i < bytes.length; i++) { - long l = bytes[i] & 0xffL; - result |= (l << (8 * i)); - } - return result; - } - - public static byte[] hexStringToBigEndianBytes(String string) { - if (string.length() % 2 != 0) { - string = "0" + string; - } - byte[] result = new byte[string.length() / 2]; - for (int i = 0; i < string.length(); i += 2) { - result[i / 2] = (byte) Integer.parseInt(string.substring(i, i + 2), 16); - } - return result; - } - - public static byte[] hexStringToLittleEndianBytes(String string) { - if (string.length() % 2 != 0) { - string = "0" + string; - } - - byte[] result = new byte[string.length() / 2]; - for (int i = 0; i < string.length(); i += 2) { - int endIndex = string.length() - i; - result[i / 2] = (byte) Integer.parseInt(string.substring(endIndex - 2, endIndex), 16); - } - return result; - } - - public static String bigEndianBytesToHexString(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - int number = b & 0xff; - String str = Integer.toHexString(number); - if (str.length() == 1) { - sb.append("0"); - } - sb.append(str); - } - return sb.toString(); - } - - public static String littleEndianBytesToHexString(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (int i = bytes.length - 1; i >=0; i--) { - int number = bytes[i] & 0xff; - String str = Integer.toHexString(number); - if (str.length() == 1) { - sb.append("0"); - } - sb.append(str); - } - return sb.toString(); - } - - /** - * Convert a Byte list to a byte array - */ - public static byte[] byteListToArray(List list) { - byte[] result = new byte[list.size()]; - for (int i = 0; i < result.length; i++) { - result[i] = list.get(i); - } - return result; - } - - /** - * Convert a byte array to a Byte list - */ - public static List byteArrayToList(byte[] bytes) { - List result = new ArrayList<>(bytes.length); - for (byte b : bytes) { - result.add(b); - } - return result; - } - - /** - * @return true if two array contain same value - */ - public static boolean equleBytes(byte[] b1, byte[] b2) { - if (b1 == null || b2 == null) { - return false; - } - - if (b1.length != b2.length) { - return false; - } - - for (int i = 0; i < b1.length; i++) { - if (b1[i] != b2[i]) { - return false; - } - } - - return true; - } - - /** - * @return true if data starts with the prefix - */ - public static boolean startsWith(byte[] data, byte[] prefix) { - if (data.length < prefix.length) { - return false; - } - for (int i = 0; i < prefix.length; i++) { - if (prefix[i] != data[i]) { - return false; - } - } - - return true; - } - - /** - * @return true if data ends with the suffix - */ - public static boolean endsWith(byte[] data, byte[] suffix) { - if (data.length < suffix.length) { - return false; - } - for (int i = 0; i < suffix.length; i++) { - if (suffix[i] != data[data.length - (suffix.length - i)]) { - return false; - } - } - - return true; - } - - /** - * @return true if data starts with the prefix - */ - public static boolean startsWith(List list, byte[] prefix) { - if (list.size() < prefix.length) { - return false; - } - for (int i = 0; i < prefix.length; i++) { - if (prefix[i] != list.get(i)) { - return false; - } - } - - return true; - } - - /** - * @return true if data ends with the suffix - */ - public static boolean endsWith(List list, byte[] suffix) { - if (list.size() < suffix.length) { - return false; - } - for (int i = 0; i < suffix.length; i++) { - if (suffix[i] != list.get(list.size() - (suffix.length - i))) { - return false; - } - } - - return true; - } - - /** - * @return true if the data is null or emtpy - */ - public static boolean isEmpty(byte[] data) { - return data == null || data.length == 0; - } - - /** - * Merge the bytes arrays. - * - * @return a new merged array - */ - public static byte[] mergeBytes(byte[] bytes, byte[]... moreBytes) { - int resultLen = bytes.length; - for (byte[] data : moreBytes) { - resultLen += data.length; - } - - byte[] result = new byte[resultLen]; - - System.arraycopy(bytes, 0, result, 0, bytes.length); - int offset = bytes.length; - for (byte[] data : moreBytes) { - System.arraycopy(data, 0, result, offset, data.length); - offset += data.length; - } - - return result; - } - - public static byte[] subBytes(byte[] src, int begin) { - int length = src.length - begin; - byte[] result = new byte[length]; - System.arraycopy(src, begin, result, 0, length); - return result; - } - - public static byte[] subBytes(byte[] src, int begin, int length) { - byte[] result = new byte[length]; - System.arraycopy(src, begin, result, 0, length); - return result; - } - - public static byte[] reverseBytes(byte[] src) { - byte[] result = new byte[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[src.length - 1 - i]; - } - return result; - } - - public static List splitBytes(byte[] src, int splitLength) { - List result = new ArrayList<>(); - int offset = 0; - do { - byte[] split; - if (offset + splitLength < src.length) { - split = subBytes(src, offset, splitLength); - } else { - split = subBytes(src, offset); - } - result.add(split); - - offset += splitLength; - } while (offset < src.length); - - return result; - } - - /** - * Get a byte array for tlv format - * - * @param type data type - * @param lLength length of the Length - * @param value data value - * @return tlv byte array - */ - public static byte[] getTLV(byte[] type, int lLength, byte[] value) { - byte[] length = new byte[lLength]; - for (int i = 0; i < length.length; i++) { - length[i] = (byte) ((value.length >> (i * 8)) & 0xff); - } - - return mergeBytes(type, length, value); - } -} diff --git a/apptools/src/main/java/libs/espressif/utils/EnumUtil.java b/apptools/src/main/java/libs/espressif/utils/EnumUtil.java deleted file mode 100644 index eab8ccc..0000000 --- a/apptools/src/main/java/libs/espressif/utils/EnumUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -package libs.espressif.utils; - -public class EnumUtil { - /** - * Get the enum instance with the name - * - * @param enumClass the class of the enum - * @param nameStr the name string of the enum - * @param Class Enum - * @return target name enum - */ - public static > E getEnumForName(Class enumClass, String nameStr) { - if (enumClass.isEnum()) { - E[] enums = enumClass.getEnumConstants(); - for (E e : enums) { - if (e.name().equals(nameStr)) { - return e; - } - } - } - - return null; - } -} diff --git a/apptools/src/main/java/libs/espressif/utils/RandomUtil.java b/apptools/src/main/java/libs/espressif/utils/RandomUtil.java deleted file mode 100755 index 5f33348..0000000 --- a/apptools/src/main/java/libs/espressif/utils/RandomUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -package libs.espressif.utils; - -import java.util.Random; - -public class RandomUtil { - - /** - * map int to String - * - * @param i int value - * @return 0-9: "0"-"9" 10-25: "a"-"z" - */ - private static String map(int i) { - if (i < 10) - return Integer.toString(i); - else { - char c = (char) ('a' + i - 10); - return Character.toString(c); - } - } - - /** - * Generate a target length String, the value range is "0-9" and "a-z" - * - * @param length except string length - * @return target length random string - */ - public static String randomString(int length) { - Random random = new Random(); - String token = ""; - for (int i = 0; i < length; i++) { - int x = random.nextInt(36); - token += map(x); - } - return token; - } - - /** - * Generate a target length byte array. - * - * @param length except array length - * @return random byte array - */ - public static byte[] randomBytes(int length) { - Random random = new Random(); - byte[] result = new byte[length]; - random.nextBytes(result); - return result; - } -} diff --git a/apptools/src/main/java/libs/espressif/utils/TextUtils.java b/apptools/src/main/java/libs/espressif/utils/TextUtils.java deleted file mode 100644 index 6db047f..0000000 --- a/apptools/src/main/java/libs/espressif/utils/TextUtils.java +++ /dev/null @@ -1,13 +0,0 @@ -package libs.espressif.utils; - -import java.util.Locale; - -public final class TextUtils { - public static boolean isEmpty(CharSequence text) { - return android.text.TextUtils.isEmpty(text); - } - - public static String format(String format, Object... args) { - return String.format(Locale.ENGLISH, format, args); - } -} diff --git a/apptools/src/main/java/libs/espressif/utils/TimeUtil.java b/apptools/src/main/java/libs/espressif/utils/TimeUtil.java deleted file mode 100644 index e1175df..0000000 --- a/apptools/src/main/java/libs/espressif/utils/TimeUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package libs.espressif.utils; - -import java.util.TimeZone; - -public class TimeUtil { - public static long getUTCTime(long time) { - TimeZone timeZone = TimeZone.getDefault(); - return time - timeZone.getRawOffset(); - } - - public static long getSystemTime(long utcTime) { - TimeZone timeZone = TimeZone.getDefault(); - return utcTime + timeZone.getRawOffset(); - } -} diff --git a/apptools/src/main/res/values/strings.xml b/apptools/src/main/res/values/strings.xml deleted file mode 100644 index 8542005..0000000 --- a/apptools/src/main/res/values/strings.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/blufilibrary/build.gradle b/blufilibrary/build.gradle index bd82e62..e003c7e 100644 --- a/blufilibrary/build.gradle +++ b/blufilibrary/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 18 - targetSdkVersion 28 - versionCode 6 - versionName "2.2.2" + targetSdkVersion 29 + versionCode 7 + versionName "2.2.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -25,6 +25,4 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - - implementation project(':apptools') } diff --git a/blufilibrary/src/main/AndroidManifest.xml b/blufilibrary/src/main/AndroidManifest.xml index 58be2f6..aeb2ea7 100644 --- a/blufilibrary/src/main/AndroidManifest.xml +++ b/blufilibrary/src/main/AndroidManifest.xml @@ -4,9 +4,4 @@ - - - - diff --git a/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java b/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java index 95ebf46..a0b658a 100644 --- a/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java +++ b/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java @@ -11,7 +11,7 @@ import blufi.espressif.response.BlufiVersionResponse; public class BlufiClient { - public static final String VERSION = "2.2.2"; + public static final String VERSION = "2.2.3"; private BlufiClientImpl mImpl; diff --git a/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java b/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java index 612a43e..6660fc9 100644 --- a/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java +++ b/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java @@ -5,11 +5,11 @@ import android.os.Handler; import android.os.Looper; import android.text.TextUtils; +import android.util.Log; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigInteger; -import java.security.spec.InvalidKeySpecException; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -25,14 +25,14 @@ import blufi.espressif.response.BlufiScanResult; import blufi.espressif.response.BlufiStatusResponse; import blufi.espressif.response.BlufiVersionResponse; -import libs.espressif.log.EspLog; -import libs.espressif.security.EspAES; -import libs.espressif.security.EspCRC; -import libs.espressif.security.EspDH; -import libs.espressif.security.EspMD5; -import libs.espressif.utils.DataUtil; +import blufi.espressif.security.BlufiAES; +import blufi.espressif.security.BlufiCRC; +import blufi.espressif.security.BlufiDH; +import blufi.espressif.security.BlufiMD5; class BlufiClientImpl implements BlufiParameter { + private static final String TAG = "BlufiClientImpl"; + private static final int DEFAULT_PACKAGE_LENGTH = 20; private static final int PACKAGE_HEADER_LENGTH = 4; private static final int MIN_PACKAGE_LENGTH = 6; @@ -44,8 +44,6 @@ class BlufiClientImpl implements BlufiParameter { private static final String DH_G = "2"; private static final String AES_TRANSFORMATION = "AES/CFB/NoPadding"; - private final EspLog mLog = new EspLog(getClass()); - private BlufiClient mClient; private BluetoothGatt mGatt; @@ -61,7 +59,7 @@ class BlufiClientImpl implements BlufiParameter { private AtomicInteger mReadSequence; private LinkedBlockingQueue mAck; - private volatile BlufiNotiData mNotiData; + private volatile BlufiNotiyData mNotiyData; private byte[] mSecretKeyMD5; @@ -217,18 +215,18 @@ void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic cha return; } - if (mNotiData == null) { - mNotiData = new BlufiNotiData(); + if (mNotiyData == null) { + mNotiyData = new BlufiNotiyData(); } byte[] data = characteristic.getValue(); // lt 0 is error, eq 0 is complete, gt 0 is continue - int parse = parseNotification(data, mNotiData); + int parse = parseNotification(data, mNotiyData); if (parse < 0) { onError(BlufiCallback.CODE_INVALID_NOTIFICATION); } else if (parse == 0) { - parseBlufiNotiData(mNotiData); - mNotiData = null; + parseBlufiNotiData(mNotiyData); + mNotiyData = null; } } @@ -242,10 +240,42 @@ void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic chara } } + private void logd(String msg) { + Log.d(TAG, msg); + } + + private void logw(String msg) { + Log.w(TAG, msg); + } + private int toInt(byte b) { return b & 0xff; } + private String toHex(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + int number = b & 0xff; + String str = Integer.toHexString(number); + if (str.length() == 1) { + sb.append("0"); + } + sb.append(str); + } + return sb.toString(); + } + + private byte[] toBytes(String hex) { + if (hex.length() % 2 != 0) { + hex = "0" + hex; + } + byte[] result = new byte[hex.length() / 2]; + for (int i = 0; i < hex.length(); i += 2) { + result[i / 2] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16); + } + return result; + } + private int getTypeValue(int type, int subtype) { return (subtype << 2) | type; } @@ -376,16 +406,19 @@ private byte[] getPostBytes(int type, int frameCtrl, int sequence, int dataLengt if (frameCtrlData.isChecksum()) { byte[] willCheckBytes = new byte[]{(byte) sequence, (byte) dataLength}; if (data != null) { - willCheckBytes = DataUtil.mergeBytes(willCheckBytes, data); + ByteArrayOutputStream os = new ByteArrayOutputStream(willCheckBytes.length + data.length); + os.write(willCheckBytes, 0, willCheckBytes.length); + os.write(data, 0, data.length); + willCheckBytes = os.toByteArray(); } - int checksum = EspCRC.calcCRC16(0, willCheckBytes); + int checksum = BlufiCRC.calcCRC(0, willCheckBytes); byte checksumByte1 = (byte) (checksum & 0xff); byte checksumByte2 = (byte) ((checksum >> 8) & 0xff); checksumBytes = new byte[]{checksumByte1, checksumByte2}; } if (frameCtrlData.isEncrypted() && data != null) { - EspAES espAES = new EspAES(mSecretKeyMD5, AES_TRANSFORMATION, generateAESIV(sequence)); + BlufiAES espAES = new BlufiAES(mSecretKeyMD5, AES_TRANSFORMATION, generateAESIV(sequence)); data = espAES.encrypt(data); } if (data != null) { @@ -400,20 +433,20 @@ private byte[] getPostBytes(int type, int frameCtrl, int sequence, int dataLengt return byteOS.toByteArray(); } - private int parseNotification(byte[] response, BlufiNotiData notification) { + private int parseNotification(byte[] response, BlufiNotiyData notification) { if (response == null) { - mLog.w("parseNotification null data"); + logw("parseNotification null data"); return -1; } if (response.length < 4) { - mLog.w("parseNotification data length less than 4"); + logw("parseNotification data length less than 4"); return -2; } int sequence = toInt(response[2]); if (sequence != mReadSequence.incrementAndGet()) { - mLog.w("parseNotification read sequence wrong"); + logw("parseNotification read sequence wrong"); return -3; } @@ -439,7 +472,7 @@ private int parseNotification(byte[] response, BlufiNotiData notification) { } if (frameCtrlData.isEncrypted()) { - EspAES espAES = new EspAES(mSecretKeyMD5, AES_TRANSFORMATION, generateAESIV(sequence)); + BlufiAES espAES = new BlufiAES(mSecretKeyMD5, AES_TRANSFORMATION, generateAESIV(sequence)); dataBytes = espAES.decrypt(dataBytes); } @@ -453,7 +486,7 @@ private int parseNotification(byte[] response, BlufiNotiData notification) { for (byte b : dataBytes) { checkByteOS.write(b); } - int checksum = EspCRC.calcCRC16(0, checkByteOS.toByteArray()); + int checksum = BlufiCRC.calcCRC(0, checkByteOS.toByteArray()); int calcChecksum1 = (checksum >> 8) & 0xff; int calcChecksum2 = checksum & 0xff; @@ -475,7 +508,7 @@ private int parseNotification(byte[] response, BlufiNotiData notification) { return frameCtrlData.hasFrag() ? 1 : 0; } - private void parseBlufiNotiData(BlufiNotiData data) { + private void parseBlufiNotiData(BlufiNotiyData data) { int pkgType = data.getPkgType(); int subType = data.getSubType(); if (mUserCallback != null) { @@ -612,7 +645,7 @@ private void parseWifiStateData(BlufiStatusResponse response, int infoType, byte response.setSoftAPSSID(softapSSID); break; case BlufiParameter.Type.Data.SUBTYPE_STA_WIFI_BSSID: - String staBssid = DataUtil.bigEndianBytesToHexString(data); + String staBssid = toHex(data); response.setStaBSSID(staBssid); break; case BlufiParameter.Type.Data.SUBTYPE_STA_WIFI_SSID: @@ -641,7 +674,7 @@ private void parseWifiScanList(byte[] data) { if (readLength) { read = dataIS.read(); if (read == -1) { - mLog.d("parseWifiScanList read len null"); + logd("parseWifiScanList read len null"); break; } @@ -653,7 +686,7 @@ private void parseWifiScanList(byte[] data) { if (readRssi) { read = dataIS.read(); if (read == -1) { - mLog.d("parseWifiScanList read rssi null"); + logd("parseWifiScanList read rssi null"); break; } @@ -665,7 +698,7 @@ private void parseWifiScanList(byte[] data) { if (readSSID) { read = dataIS.read(); if (read == -1) { - mLog.d("parseWifiScanList read ssid null"); + logd("parseWifiScanList read ssid null"); break; } @@ -689,20 +722,17 @@ private void parseWifiScanList(byte[] data) { } private void onError(final int errCode) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onError(mClient, errCode); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onError(mClient, errCode); } }); } private void __negotiateSecurity() { - EspDH espDH = postNegotiateSecurity(); + BlufiDH espDH = postNegotiateSecurity(); if (espDH == null) { - mLog.w("negotiateSecurity postNegotiateSecurity failed"); + logw("negotiateSecurity postNegotiateSecurity failed"); onNegotiateSecurityResult(BlufiCallback.CODE_NEG_POST_FAILED); return; } @@ -727,8 +757,8 @@ private void __negotiateSecurity() { return; } - mSecretKeyMD5 = EspMD5.getMD5Byte(espDH.getSecretKey()); - } catch (InvalidKeySpecException e) { + mSecretKeyMD5 = BlufiMD5.getMD5Bytes(espDH.getSecretKey()); + } catch (Exception e) { e.printStackTrace(); onNegotiateSecurityResult(BlufiCallback.CODE_NEG_ERR_SECURITY); return; @@ -751,37 +781,34 @@ private void __negotiateSecurity() { } private void onNegotiateSecurityResult(final int status) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onNegotiateSecurityResult(mClient, status); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onNegotiateSecurityResult(mClient, status); } }); } - private EspDH postNegotiateSecurity() { + private BlufiDH postNegotiateSecurity() { int type = getTypeValue(Type.Data.PACKAGE_VALUE, Type.Data.SUBTYPE_NEG); final int radix = 16; final int dhLength = 1024; final BigInteger dhP = new BigInteger(DH_P, radix); final BigInteger dhG = new BigInteger(DH_G); - EspDH espDH; + BlufiDH espDH; String p; String g; String k; do { - espDH = new EspDH(dhP, dhG, dhLength); + espDH = new BlufiDH(dhP, dhG, dhLength); p = espDH.getP().toString(radix); g = espDH.getG().toString(radix); k = getPublicValue(espDH); } while (k == null); - byte[] pBytes = DataUtil.hexStringToBigEndianBytes(p); - byte[] gBytes = DataUtil.hexStringToBigEndianBytes(g); - byte[] kBytes = DataUtil.hexStringToBigEndianBytes(k); + byte[] pBytes = toBytes(p); + byte[] gBytes = toBytes(g); + byte[] kBytes = toBytes(k); ByteArrayOutputStream dataOS = new ByteArrayOutputStream(); @@ -843,7 +870,7 @@ private EspDH postNegotiateSecurity() { return espDH; } - private String getPublicValue(EspDH espDH) { + private String getPublicValue(BlufiDH espDH) { DHPublicKey publicKey = espDH.getPublicKey(); if (publicKey != null) { BigInteger y = publicKey.getY(); @@ -886,7 +913,7 @@ private boolean postSetSecurity(boolean ctrlEncrypted, boolean ctrlChecksum, boo private class SecurityCallback { void onReceiveDevicePublicKey(byte[] keyData) { - String keyStr = DataUtil.bigEndianBytesToHexString(keyData); + String keyStr = toHex(keyData); try { BigInteger devicePublicValue = new BigInteger(keyStr, 16); mDevicePublicKeyQueue.add(devicePublicValue); @@ -955,12 +982,9 @@ private void __configure(BlufiConfigureParams params) { } private void onConfigureResult(final int status) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onConfigureResult(mClient, status); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onConfigureResult(mClient, status); } }); } @@ -1050,21 +1074,11 @@ private boolean postSoftAPInfo(BlufiConfigureParams params) { } } - private byte[] convertAddressStringToByteArray(String address) { - String[] splits = address.split(":"); - byte[] result = new byte[splits.length]; - for (int i = 0; i < result.length; i++) { - result[i] = (byte) Integer.parseInt(splits[i], 16); - } - - return result; - } - private void __requestDeviceVersion() { int type = getTypeValue(Type.Ctrl.PACKAGE_VALUE, Type.Ctrl.SUBTYPE_GET_VERSION); boolean request; try { - request = post(mEncrypted, mChecksum, false, type, (byte[]) null); + request = post(mEncrypted, mChecksum, false, type, (byte[]) null); } catch (InterruptedException e) { e.printStackTrace(); request = false; @@ -1077,12 +1091,9 @@ private void __requestDeviceVersion() { } private void onVersionResponse(final int status, final BlufiVersionResponse response) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onDeviceVersionResponse(mClient, status, response); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onDeviceVersionResponse(mClient, status, response); } }); } @@ -1104,12 +1115,9 @@ private void __requestDeviceStatus() { } private void onStatusResponse(final int status, final BlufiStatusResponse response) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onDeviceStatusResponse(mClient, status, response); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onDeviceStatusResponse(mClient, status, response); } }); } @@ -1131,12 +1139,9 @@ private void __requestDeviceWifiScan() { } private void onDeviceScanResult(final int status, final List results) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onDeviceScanResult(mClient, status, results); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onDeviceScanResult(mClient, status, results); } }); } @@ -1154,23 +1159,17 @@ private void __postCustomData(byte[] data) { } private void onPostCustomDataResult(final int status, final byte[] data) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onPostCustomDataResult(mClient, status, data); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onPostCustomDataResult(mClient, status, data); } }); } private void onReceiveCustomData(final int status, final byte[] data) { - mUIHandler.post(new Runnable() { - @Override - public void run() { - if (mUserCallback != null) { - mUserCallback.onReceiveCustomData(mClient, status, data); - } + mUIHandler.post(() -> { + if (mUserCallback != null) { + mUserCallback.onReceiveCustomData(mClient, status, data); } }); } diff --git a/blufilibrary/src/main/java/blufi/espressif/BlufiNotiData.java b/blufilibrary/src/main/java/blufi/espressif/BlufiNotiyData.java similarity index 95% rename from blufilibrary/src/main/java/blufi/espressif/BlufiNotiData.java rename to blufilibrary/src/main/java/blufi/espressif/BlufiNotiyData.java index 583ae4f..7bc6309 100644 --- a/blufilibrary/src/main/java/blufi/espressif/BlufiNotiData.java +++ b/blufilibrary/src/main/java/blufi/espressif/BlufiNotiyData.java @@ -2,7 +2,7 @@ import java.io.ByteArrayOutputStream; -public class BlufiNotiData { +public class BlufiNotiyData { private int mTypeValue; private int mPkgType; private int mSubType; @@ -11,7 +11,7 @@ public class BlufiNotiData { private ByteArrayOutputStream mDataOS; - public BlufiNotiData() { + public BlufiNotiyData() { mDataOS = new ByteArrayOutputStream(); } diff --git a/apptools/src/main/java/libs/espressif/security/EspAES.java b/blufilibrary/src/main/java/blufi/espressif/security/BlufiAES.java similarity index 92% rename from apptools/src/main/java/libs/espressif/security/EspAES.java rename to blufilibrary/src/main/java/blufi/espressif/security/BlufiAES.java index 27e2c9f..4dc5865 100644 --- a/apptools/src/main/java/libs/espressif/security/EspAES.java +++ b/blufilibrary/src/main/java/blufi/espressif/security/BlufiAES.java @@ -1,4 +1,4 @@ -package libs.espressif.security; +package blufi.espressif.security; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; @@ -11,18 +11,14 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -public class EspAES { +public class BlufiAES { private final byte[] mKey; private final byte[] mIV; private final String mTransformation; private Cipher mEncryptCipher; private Cipher mDecryptCipher; - public EspAES(byte[] key, String transformation) { - this(key, transformation, null); - } - - public EspAES(byte[] key, String transformation, byte[] iv) { + public BlufiAES(byte[] key, String transformation, byte[] iv) { mKey = key; mIV = iv; mTransformation = transformation; diff --git a/apptools/src/main/java/libs/espressif/security/EspCRC.java b/blufilibrary/src/main/java/blufi/espressif/security/BlufiCRC.java similarity index 95% rename from apptools/src/main/java/libs/espressif/security/EspCRC.java rename to blufilibrary/src/main/java/blufi/espressif/security/BlufiCRC.java index 2c8af29..6464710 100644 --- a/apptools/src/main/java/libs/espressif/security/EspCRC.java +++ b/blufilibrary/src/main/java/blufi/espressif/security/BlufiCRC.java @@ -1,6 +1,6 @@ -package libs.espressif.security; +package blufi.espressif.security; -public class EspCRC { +public class BlufiCRC { private static final int[] CRC_TB = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, @@ -20,7 +20,7 @@ public class EspCRC { 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; - public static int calcCRC16(int crc, byte[] pByte) { + public static int calcCRC(int crc, byte[] pByte) { crc = (~crc) & 0xffff; for (byte aPByte : pByte) { crc = CRC_TB[(crc >> 8) ^ (aPByte & 0xff)] ^ (crc << 8); diff --git a/apptools/src/main/java/libs/espressif/security/EspDH.java b/blufilibrary/src/main/java/blufi/espressif/security/BlufiDH.java similarity index 52% rename from apptools/src/main/java/libs/espressif/security/EspDH.java rename to blufilibrary/src/main/java/blufi/espressif/security/BlufiDH.java index 3693031..fd468b8 100644 --- a/apptools/src/main/java/libs/espressif/security/EspDH.java +++ b/blufilibrary/src/main/java/blufi/espressif/security/BlufiDH.java @@ -1,24 +1,15 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package libs.espressif.security; +package blufi.espressif.security; import java.math.BigInteger; -import java.security.AlgorithmParameterGenerator; -import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; +import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; -import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; -import java.security.spec.InvalidParameterSpecException; import javax.crypto.KeyAgreement; import javax.crypto.interfaces.DHPrivateKey; @@ -26,8 +17,7 @@ import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; -public class EspDH { - private final int mLength; +public class BlufiDH { private BigInteger mP; private BigInteger mG; @@ -36,51 +26,13 @@ public class EspDH { private byte[] mSecretKey; - public EspDH(BigInteger p, BigInteger g, int length) { + public BlufiDH(BigInteger p, BigInteger g, int length) { mP = p; mG = g; - mLength = length; - generateKeys(); - } - - private BigInteger[] generatePG() { - AlgorithmParameterGenerator paramGen = null; - try { - paramGen = AlgorithmParameterGenerator.getInstance("DH"); - paramGen.init(mLength, new SecureRandom()); - AlgorithmParameters params = paramGen.generateParameters(); - DHParameterSpec dhSpec = params.getParameterSpec(DHParameterSpec.class); - BigInteger pv = dhSpec.getP(); - BigInteger gv = dhSpec.getG(); - - return new BigInteger[]{pv, gv}; - } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) { - e.printStackTrace(); - } - - return null; - } - - private boolean generateKeys() { - try { - // Use the values to generate a key pair - KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); - DHParameterSpec dhSpec = new DHParameterSpec(mP, mG, mLength); - keyGen.initialize(dhSpec); - KeyPair keypair = keyGen.generateKeyPair(); - - // Get the generated public and private keys - mPrivateKey = (DHPrivateKey) keypair.getPrivate(); - mPublicKey = (DHPublicKey) keypair.getPublic(); - - return true; - } catch (NoSuchAlgorithmException - | InvalidAlgorithmParameterException - | ClassCastException e) { - e.printStackTrace(); - - return false; - } + Key[] keys = generateKeys(p, g, length); + assert keys != null; + mPrivateKey = (DHPrivateKey) keys[0]; + mPublicKey = (DHPublicKey) keys[1]; } public BigInteger getP() { @@ -91,7 +43,7 @@ public BigInteger getG() { return mG; } - public DHPrivateKey getPriveteKey() { + public DHPrivateKey getPrivateKey() { return mPrivateKey; } @@ -103,11 +55,11 @@ public byte[] getSecretKey() { return mSecretKey; } - public void generateSecretKey(BigInteger y) throws InvalidKeySpecException { + public void generateSecretKey(BigInteger y) { try { - DHPublicKeySpec ks = new DHPublicKeySpec(y, mP, mG); + DHPublicKeySpec pbks = new DHPublicKeySpec(y, mP, mG); KeyFactory keyFact = KeyFactory.getInstance("DH"); - PublicKey publicKey = keyFact.generatePublic(ks); + PublicKey publicKey = keyFact.generatePublic(pbks); // Prepare to generate the secret key with the private key and public key of the other party KeyAgreement ka = KeyAgreement.getInstance("DH"); @@ -116,8 +68,31 @@ public void generateSecretKey(BigInteger y) throws InvalidKeySpecException { // Generate the secret key mSecretKey = ka.generateSecret(); - } catch (NoSuchAlgorithmException | InvalidKeyException e) { + } catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException e) { e.printStackTrace(); } } + + private static Key[] generateKeys(BigInteger p, BigInteger g, int length) { + try { + // Use the values to generate a key pair + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); + DHParameterSpec dhSpec = new DHParameterSpec(p, g, length); + keyGen.initialize(dhSpec); + KeyPair keypair = keyGen.generateKeyPair(); + + // Get the generated public and private keys + Key[] result = new Key[2]; + result[0] = keypair.getPrivate(); + result[1] = keypair.getPublic(); + + return result; + } catch (NoSuchAlgorithmException + | InvalidAlgorithmParameterException + | ClassCastException e) { + e.printStackTrace(); + + return null; + } + } } diff --git a/blufilibrary/src/main/java/blufi/espressif/security/BlufiMD5.java b/blufilibrary/src/main/java/blufi/espressif/security/BlufiMD5.java new file mode 100644 index 0000000..5ed0479 --- /dev/null +++ b/blufilibrary/src/main/java/blufi/espressif/security/BlufiMD5.java @@ -0,0 +1,18 @@ +package blufi.espressif.security; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class BlufiMD5 { + public static byte[] getMD5Bytes(byte[] data) { + try { + MessageDigest digest = MessageDigest.getInstance("md5"); + digest.update(data); + return digest.digest(); + } catch (NoSuchAlgorithmException | NullPointerException e) { + e.printStackTrace(); + } + + return null; + } +} diff --git a/build.gradle b/build.gradle index c5c31db..5600a93 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.2' + classpath 'com.android.tools.build:gradle:3.5.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 50f13c8..4d4717a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Apr 26 15:27:54 CST 2019 +#Thu Aug 29 15:00:19 CST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/log/updatelog-en.md b/log/updatelog-en.md index 5576ec7..926fa93 100644 --- a/log/updatelog-en.md +++ b/log/updatelog-en.md @@ -2,6 +2,10 @@ # Update Log +## v1.4.3 +- Make blufilibrary module fully independent, delete apptools module +- Change targetSdkVersion to Android Q(29) + ## v1.4.2 - Add app upgrade option in Settings diff --git a/log/updatelog-zh-rCN.md b/log/updatelog-zh-rCN.md index b2c6cae..638a141 100644 --- a/log/updatelog-zh-rCN.md +++ b/log/updatelog-zh-rCN.md @@ -2,6 +2,10 @@ # 更新日志 +## v1.4.3 +- 将 blufilibrary 模块改为完全独立的模块, 删除 apptools 模块 +- 将 targetSdkVersion 改为 Android Q(29) + # v1.4.2 - 设置界面内增加 APP 检查更新功能 diff --git a/settings.gradle b/settings.gradle index 0ffa74c..1658890 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ -include ':app', ':blufilibrary', ':apptools' +include ':app' +include ':blufilibrary'