rename dir
11
doric-android/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.project
|
||||
.classpath
|
||||
.settings/
|
201
doric-android/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [2019] [Doric.Pub]
|
||||
|
||||
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.
|
3
doric-android/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Doric Android SDK
|
||||
|
||||
## Usages
|
1
doric-android/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
34
doric-android/app/build.gradle
Normal file
@@ -0,0 +1,34 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.2'
|
||||
defaultConfig {
|
||||
applicationId "pub.doric.demo"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation "com.google.android.material:material:1.0.0"
|
||||
implementation "pub.doric:core:${rootProject.ext.Version}"
|
||||
implementation "pub.doric:devkit:${rootProject.ext.Version}"
|
||||
implementation 'com.github.bumptech.glide:glide:4.10.0'
|
||||
implementation 'com.github.bumptech.glide:annotations:4.10.0'
|
||||
implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.3.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0'
|
||||
}
|
21
doric-android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# 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
|
26
doric-android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="pub.doric.demo">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".MyApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".PullableActivity"></activity>
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
1
doric-android/app/src/main/assets/demo/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.js
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.demo;
|
||||
|
||||
import pub.doric.DoricComponent;
|
||||
import pub.doric.DoricLibrary;
|
||||
import pub.doric.DoricRegistry;
|
||||
|
||||
@DoricComponent
|
||||
public class DemoLibrary extends DoricLibrary {
|
||||
@Override
|
||||
public void load(DoricRegistry registry) {
|
||||
registry.registerNativePlugin(DemoPlugin.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.demo;
|
||||
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.extension.bridge.DoricMethod;
|
||||
import pub.doric.extension.bridge.DoricPlugin;
|
||||
import pub.doric.extension.bridge.DoricPromise;
|
||||
import pub.doric.plugin.DoricJavaPlugin;
|
||||
import pub.doric.utils.ThreadMode;
|
||||
|
||||
@DoricPlugin(name = "demo")
|
||||
public class DemoPlugin extends DoricJavaPlugin {
|
||||
public DemoPlugin(DoricContext doricContext) {
|
||||
super(doricContext);
|
||||
}
|
||||
|
||||
@DoricMethod(thread = ThreadMode.UI)
|
||||
public void test() {
|
||||
Toast.makeText(getDoricContext().getContext(), "test", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@DoricMethod(thread = ThreadMode.UI)
|
||||
public void testPromise(boolean b, DoricPromise doricPromise) {
|
||||
if (b) {
|
||||
doricPromise.resolve(new JavaValue("resolved by me"));
|
||||
} else {
|
||||
doricPromise.reject(new JavaValue("rejected by me"));
|
||||
}
|
||||
Toast.makeText(getDoricContext().getContext(), "test", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
121
doric-android/app/src/main/java/pub/doric/demo/MainActivity.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.demo;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import pub.doric.devkit.ui.DemoDebugActivity;
|
||||
import pub.doric.refresh.DoricSwipeLayout;
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
final DoricSwipeLayout swipeLayout = findViewById(R.id.swipe_layout);
|
||||
swipeLayout.setOnRefreshListener(new DoricSwipeLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
swipeLayout.setRefreshing(false);
|
||||
}
|
||||
});
|
||||
swipeLayout.setBackgroundColor(Color.YELLOW);
|
||||
swipeLayout.getRefreshView().setBackgroundColor(Color.RED);
|
||||
TextView textView = new TextView(this);
|
||||
textView.setText("This is header");
|
||||
swipeLayout.getRefreshView().setContent(textView);
|
||||
RecyclerView recyclerView = findViewById(R.id.root);
|
||||
recyclerView.setBackgroundColor(Color.WHITE);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
try {
|
||||
String[] demos = getAssets().list("demo");
|
||||
List<String> ret = new ArrayList<>();
|
||||
for (String str : demos) {
|
||||
if (str.endsWith("js")) {
|
||||
ret.add(str);
|
||||
}
|
||||
}
|
||||
recyclerView.setAdapter(new MyAdapter(ret.toArray(new String[0])));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private final String[] data;
|
||||
|
||||
public MyAdapter(String[] demos) {
|
||||
this.data = demos;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
TextView textView = new TextView(parent.getContext());
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setLayoutParams(new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
DoricUtils.dp2px(50)));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
||||
return new RecyclerView.ViewHolder(textView) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
|
||||
final TextView tv = (TextView) holder.itemView;
|
||||
tv.setText(data[position]);
|
||||
tv.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(tv.getContext(), DemoDebugActivity.class);
|
||||
intent.putExtra("scheme", "assets://demo/" + data[position]);
|
||||
intent.putExtra("alias", data[position]);
|
||||
tv.getContext().startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return data.length;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.demo;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import pub.doric.Doric;
|
||||
import pub.doric.DoricRegistry;
|
||||
|
||||
public class MyApplication extends Application {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Doric.init(this);
|
||||
DoricRegistry.register(new DemoLibrary());
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.demo;
|
||||
|
||||
import com.bumptech.glide.annotation.GlideModule;
|
||||
import com.bumptech.glide.module.AppGlideModule;
|
||||
|
||||
@GlideModule
|
||||
public class MyGlideModule extends AppGlideModule {
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package pub.doric.demo;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import pub.doric.refresh.DoricSwipeLayout;
|
||||
|
||||
public class PullableActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_pullable);
|
||||
final DoricSwipeLayout swipeRefreshLayout = findViewById(R.id.swipe_layout);
|
||||
FrameLayout frameLayout = new FrameLayout(this);
|
||||
frameLayout.setBackgroundColor(Color.YELLOW);
|
||||
swipeRefreshLayout.addView(frameLayout);
|
||||
swipeRefreshLayout.setOnRefreshListener(new DoricSwipeLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
13
doric-android/app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<pub.doric.refresh.DoricSwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/swipe_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity" />
|
||||
</pub.doric.refresh.DoricSwipeLayout>
|
13
doric-android/app/src/main/res/layout/activity_pullable.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".PullableActivity">
|
||||
|
||||
<pub.doric.refresh.DoricSwipeLayout
|
||||
android:id="@+id/swipe_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</FrameLayout>
|
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
BIN
doric-android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
doric-android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
doric-android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
doric-android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
doric-android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 6.7 KiB |
BIN
doric-android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 10 KiB |
BIN
doric-android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 15 KiB |
6
doric-android/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
3
doric-android/app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Doric</string>
|
||||
</resources>
|
11
doric-android/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
</network-security-config>
|
63
doric-android/build.gradle
Normal file
@@ -0,0 +1,63 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://dl.bintray.com/osborn/Android"
|
||||
}
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
def needReplaceLocal = true
|
||||
gradle.startParameter.taskNames.each {
|
||||
if (it.contains('uploadArchives')) {
|
||||
needReplaceLocal = false
|
||||
}
|
||||
}
|
||||
if (needReplaceLocal) {
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
dependencySubstitution {
|
||||
substitute module('pub.doric:core') with project(":doric")
|
||||
substitute module('pub.doric:devkit') with project(":devkit")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
Properties properties = new Properties()
|
||||
properties.load(project.rootProject.file('version.properties').newDataInputStream())
|
||||
ext {
|
||||
Version = properties.version
|
||||
}
|
||||
|
||||
task publisCore dependsOn(":doric:uploadArchives") {
|
||||
println "doric published"
|
||||
}
|
||||
|
||||
task publishDevKit dependsOn(publisCore, ":devkit:uploadArchives") {
|
||||
println "devkit published"
|
||||
}
|
||||
|
||||
task PublishAll dependsOn(publisCore, publishDevKit) {
|
||||
println "All published"
|
||||
}
|
1
doric-android/devkit/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
45
doric-android/devkit/build.gradle
Normal file
@@ -0,0 +1,45 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation "pub.doric:core:${rootProject.ext.Version}"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation "com.google.android.material:material:1.0.0"
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'cn.bingoogolapple:bga-qrcode-zbar:1.3.7'
|
||||
implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.15"
|
||||
api 'org.greenrobot:eventbus:3.1.1'
|
||||
implementation 'com.lahm.library:easy-protector-release:1.1.1'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('scripts/upload.gradle')
|
0
doric-android/devkit/consumer-rules.pro
Normal file
3
doric-android/devkit/pom.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
name=DoricDevKit
|
||||
groupId=pub.doric
|
||||
artifactId=devkit
|
21
doric-android/devkit/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# 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
|
@@ -0,0 +1,27 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
|
||||
assertEquals("pub.doric.devkit.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
13
doric-android/devkit/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="pub.doric.devkit">
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application>
|
||||
<activity android:name=".ui.ScanQRCodeActivity" />
|
||||
<activity
|
||||
android:name=".ui.DemoDebugActivity"
|
||||
android:theme="@style/Theme.Design.Light.NoActionBar" />
|
||||
</application>
|
||||
</manifest>
|
@@ -0,0 +1,44 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class DevKit implements IDevKit {
|
||||
|
||||
public static boolean isRunningInEmulator = false;
|
||||
public static String ip = "";
|
||||
private static Gson gson = new Gson();
|
||||
|
||||
private static class Inner {
|
||||
private static final DevKit sInstance = new DevKit();
|
||||
}
|
||||
|
||||
private DevKit() {
|
||||
}
|
||||
|
||||
public static DevKit getInstance() {
|
||||
return Inner.sInstance;
|
||||
}
|
||||
|
||||
|
||||
private WSClient wsClient;
|
||||
|
||||
@Override
|
||||
public void connectDevKit(String url) {
|
||||
wsClient = new WSClient(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDevCommand(IDevKit.Command command, JsonObject jsonObject) {
|
||||
JsonObject result = new JsonObject();
|
||||
result.addProperty("cmd", command.toString());
|
||||
result.add("data", jsonObject);
|
||||
wsClient.send(gson.toJson(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnectDevKit() {
|
||||
wsClient.close();
|
||||
wsClient = null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.DoricContextManager;
|
||||
import pub.doric.DoricNativeDriver;
|
||||
|
||||
public class DoricContextDebuggable {
|
||||
private DoricContext doricContext;
|
||||
private DoricDebugDriver doricDebugDriver;
|
||||
public boolean isDebugging = false;
|
||||
|
||||
public DoricContextDebuggable(String contextId) {
|
||||
this.doricContext = DoricContextManager.getContext(contextId);
|
||||
isDebugging = true;
|
||||
}
|
||||
|
||||
public void startDebug() {
|
||||
doricDebugDriver = new DoricDebugDriver(new IStatusCallback() {
|
||||
@Override
|
||||
public void start() {
|
||||
doricContext.setDriver(doricDebugDriver);
|
||||
doricContext.reInit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void stopDebug() {
|
||||
isDebugging = false;
|
||||
doricDebugDriver.destroy();
|
||||
doricContext.setDriver(DoricNativeDriver.getInstance());
|
||||
doricContext.reInit();
|
||||
}
|
||||
|
||||
public DoricContext getContext() {
|
||||
return doricContext;
|
||||
}
|
||||
}
|
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.devkit;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import pub.doric.DoricRegistry;
|
||||
import pub.doric.IDoricDriver;
|
||||
import pub.doric.async.AsyncCall;
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.engine.DoricJSEngine;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
import pub.doric.utils.DoricLog;
|
||||
import pub.doric.utils.ThreadMode;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricDebugDriver implements IDoricDriver {
|
||||
private final DoricJSEngine doricJSEngine;
|
||||
private final ExecutorService mBridgeExecutor;
|
||||
private final Handler mUIHandler;
|
||||
private final Handler mJSHandler;
|
||||
|
||||
|
||||
public DoricDebugDriver(IStatusCallback statusCallback) {
|
||||
doricJSEngine = new DoricDebugJSEngine(statusCallback);
|
||||
mBridgeExecutor = Executors.newCachedThreadPool();
|
||||
mUIHandler = new Handler(Looper.getMainLooper());
|
||||
mJSHandler = doricJSEngine.getJSHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<JSDecoder> invokeContextEntityMethod(final String contextId, final String method, final Object... args) {
|
||||
final Object[] nArgs = new Object[args.length + 2];
|
||||
nArgs[0] = contextId;
|
||||
nArgs[1] = method;
|
||||
if (args.length > 0) {
|
||||
System.arraycopy(args, 0, nArgs, 2, args.length);
|
||||
}
|
||||
return invokeDoricMethod(DoricConstant.DORIC_CONTEXT_INVOKE, nArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<JSDecoder>() {
|
||||
@Override
|
||||
public JSDecoder call() {
|
||||
try {
|
||||
return doricJSEngine.invokeDoricMethod(method, args);
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("invokeDoricMethod(%s,...),error is %s", method, e.getLocalizedMessage());
|
||||
return new JSDecoder(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> AsyncResult<T> asyncCall(Callable<T> callable, ThreadMode threadMode) {
|
||||
switch (threadMode) {
|
||||
case JS:
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, callable);
|
||||
case UI:
|
||||
return AsyncCall.ensureRunInHandler(mUIHandler, callable);
|
||||
case INDEPENDENT:
|
||||
default:
|
||||
return AsyncCall.ensureRunInExecutor(mBridgeExecutor, callable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
doricJSEngine.prepareContext(contextId, script, source);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("createContext %s error is %s", source, e.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> destroyContext(final String contextId) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
doricJSEngine.destroyContext(contextId);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("destroyContext %s error is %s", contextId, e.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoricRegistry getRegistry() {
|
||||
return doricJSEngine.getRegistry();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
doricJSEngine.teardown();
|
||||
mBridgeExecutor.shutdown();
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import pub.doric.devkit.remote.DoricRemoteJSExecutor;
|
||||
import pub.doric.engine.DoricJSEngine;
|
||||
|
||||
public class DoricDebugJSEngine extends DoricJSEngine {
|
||||
|
||||
private IStatusCallback statusCallback;
|
||||
|
||||
public DoricDebugJSEngine(IStatusCallback statusCallback) {
|
||||
super();
|
||||
this.statusCallback = statusCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initJSEngine() {
|
||||
mDoricJSE = new DoricRemoteJSExecutor(statusCallback);
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class DoricDev {
|
||||
public static void connectDevKit(String url) {
|
||||
DevKit.getInstance().connectDevKit(url);
|
||||
}
|
||||
|
||||
public static void sendDevCommand(IDevKit.Command command, JsonObject jsonObject) {
|
||||
DevKit.getInstance().sendDevCommand(command, jsonObject);
|
||||
}
|
||||
|
||||
public static void disconnectDevKit() {
|
||||
DevKit.getInstance().disconnectDevKit();
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public interface IDevKit {
|
||||
|
||||
enum Command {
|
||||
DEBUG, HOT_RELOAD
|
||||
}
|
||||
|
||||
void connectDevKit(String url);
|
||||
|
||||
void sendDevCommand(IDevKit.Command command, JsonObject jsonObject);
|
||||
|
||||
void disconnectDevKit();
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
public interface IStatusCallback {
|
||||
void start();
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.devkit;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.net.ConnectException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.WebSocket;
|
||||
import okhttp3.WebSocketListener;
|
||||
import pub.doric.devkit.event.ConnectExceptionEvent;
|
||||
import pub.doric.devkit.event.EOFExceptionEvent;
|
||||
import pub.doric.devkit.event.EnterDebugEvent;
|
||||
import pub.doric.devkit.event.OpenEvent;
|
||||
import pub.doric.devkit.event.ReloadEvent;
|
||||
import pub.doric.devkit.ui.DevPanel;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric.dev
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-08-03
|
||||
*/
|
||||
public class WSClient extends WebSocketListener {
|
||||
private final WebSocket webSocket;
|
||||
|
||||
public WSClient(String url) {
|
||||
OkHttpClient okHttpClient = new OkHttpClient
|
||||
.Builder()
|
||||
.readTimeout(10, TimeUnit.SECONDS)
|
||||
.writeTimeout(10, TimeUnit.SECONDS)
|
||||
.build();
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
webSocket = okHttpClient.newWebSocket(request, this);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
webSocket.close(-1, "Close");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, Response response) {
|
||||
super.onOpen(webSocket, response);
|
||||
|
||||
DevPanel.isDevConnected = true;
|
||||
EventBus.getDefault().post(new OpenEvent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(WebSocket webSocket, String text) {
|
||||
super.onMessage(webSocket, text);
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(text);
|
||||
String cmd = jsonObject.optString("cmd");
|
||||
switch (cmd) {
|
||||
case "RELOAD": {
|
||||
String source = jsonObject.optString("source");
|
||||
String script = jsonObject.optString("script");
|
||||
EventBus.getDefault().post(new ReloadEvent(source, script));
|
||||
}
|
||||
break;
|
||||
case "SWITCH_TO_DEBUG": {
|
||||
String contextId = jsonObject.optString("contextId");
|
||||
EventBus.getDefault().post(new EnterDebugEvent());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosing(WebSocket webSocket, int code, String reason) {
|
||||
super.onClosing(webSocket, code, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(WebSocket webSocket, int code, String reason) {
|
||||
super.onClosed(webSocket, code, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||
super.onFailure(webSocket, t, response);
|
||||
|
||||
if (t instanceof EOFException) {
|
||||
DevPanel.isDevConnected = false;
|
||||
EventBus.getDefault().post(new EOFExceptionEvent());
|
||||
} else if (t instanceof ConnectException) {
|
||||
DevPanel.isDevConnected = false;
|
||||
EventBus.getDefault().post(new ConnectExceptionEvent());
|
||||
}
|
||||
}
|
||||
|
||||
public void send(String command) {
|
||||
webSocket.send(command);
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
package pub.doric.devkit.event;
|
||||
|
||||
public class ConnectExceptionEvent {
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
package pub.doric.devkit.event;
|
||||
|
||||
public class EOFExceptionEvent {
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
package pub.doric.devkit.event;
|
||||
|
||||
public class EnterDebugEvent {
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
package pub.doric.devkit.event;
|
||||
|
||||
public class OpenEvent {
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package pub.doric.devkit.event;
|
||||
|
||||
public class ReloadEvent {
|
||||
public String source;
|
||||
public String script;
|
||||
|
||||
public ReloadEvent(String source, String script) {
|
||||
this.source = source;
|
||||
this.script = script;
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package pub.doric.devkit.event;
|
||||
|
||||
public class StartDebugEvent {
|
||||
private String contextId;
|
||||
|
||||
public StartDebugEvent(String contextId) {
|
||||
this.contextId = contextId;
|
||||
}
|
||||
|
||||
public String getContextId() {
|
||||
return contextId;
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
package pub.doric.devkit.event;
|
||||
|
||||
public class StopDebugEvent {
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.devkit.remote;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSRuntimeException;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import pub.doric.devkit.IStatusCallback;
|
||||
import pub.doric.engine.IDoricJSE;
|
||||
|
||||
public class DoricRemoteJSExecutor implements IDoricJSE {
|
||||
|
||||
private final RemoteJSExecutor mRemoteJSExecutor;
|
||||
|
||||
public DoricRemoteJSExecutor(IStatusCallback statusCallback) {
|
||||
this.mRemoteJSExecutor = new RemoteJSExecutor(statusCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loadJS(String script, String source) throws JSRuntimeException {
|
||||
return mRemoteJSExecutor.loadJS(script, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder evaluateJS(String script, String source, boolean hashKey) throws JSRuntimeException {
|
||||
return mRemoteJSExecutor.evaluateJS(script, source, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSFunction(String name, JavaFunction javaFunction) {
|
||||
mRemoteJSExecutor.injectGlobalJSFunction(name, javaFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSObject(String name, JavaValue javaValue) {
|
||||
mRemoteJSExecutor.injectGlobalJSObject(name, javaValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) throws JSRuntimeException {
|
||||
return mRemoteJSExecutor.invokeMethod(objectName, functionName, javaValues, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teardown() {
|
||||
mRemoteJSExecutor.destroy();
|
||||
}
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
package pub.doric.devkit.remote;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSONBuilder;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.net.ConnectException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.WebSocket;
|
||||
import okhttp3.WebSocketListener;
|
||||
import pub.doric.devkit.DevKit;
|
||||
import pub.doric.devkit.IStatusCallback;
|
||||
import pub.doric.devkit.event.StopDebugEvent;
|
||||
|
||||
public class RemoteJSExecutor {
|
||||
private final WebSocket webSocket;
|
||||
private final Map<String, JavaFunction> globalFunctions = new HashMap<>();
|
||||
private JSDecoder temp;
|
||||
|
||||
public RemoteJSExecutor(final IStatusCallback statusCallback) {
|
||||
OkHttpClient okHttpClient = new OkHttpClient
|
||||
.Builder()
|
||||
.readTimeout(10, TimeUnit.SECONDS)
|
||||
.writeTimeout(10, TimeUnit.SECONDS)
|
||||
.build();
|
||||
final Request request = new Request.Builder().url("ws://" + DevKit.ip + ":2080").build();
|
||||
|
||||
final Thread current = Thread.currentThread();
|
||||
webSocket = okHttpClient.newWebSocket(request, new WebSocketListener() {
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, Response response) {
|
||||
LockSupport.unpark(current);
|
||||
statusCallback.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||
if (t instanceof ConnectException) {
|
||||
// 连接remote异常
|
||||
LockSupport.unpark(current);
|
||||
throw new RuntimeException("remote js executor cannot connect");
|
||||
} else if (t instanceof EOFException) {
|
||||
// 被远端强制断开
|
||||
System.out.println("remote js executor eof");
|
||||
|
||||
LockSupport.unpark(current);
|
||||
EventBus.getDefault().post(new StopDebugEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(text);
|
||||
String cmd = jsonObject.optString("cmd");
|
||||
switch (cmd) {
|
||||
case "injectGlobalJSFunction": {
|
||||
String name = jsonObject.optString("name");
|
||||
JSONArray arguments = jsonObject.optJSONArray("arguments");
|
||||
assert arguments != null;
|
||||
JSDecoder[] decoders = new JSDecoder[arguments.length()];
|
||||
for (int i = 0; i < arguments.length(); i++) {
|
||||
Object o = arguments.get(i);
|
||||
decoders[i] = new JSDecoder(new ValueBuilder(o).build());
|
||||
}
|
||||
globalFunctions.get(name).exec(decoders);
|
||||
}
|
||||
|
||||
break;
|
||||
case "invokeMethod": {
|
||||
try {
|
||||
Object result = jsonObject.opt("result");
|
||||
ValueBuilder vb = new ValueBuilder(result);
|
||||
temp = new JSDecoder(vb.build());
|
||||
System.out.println(result);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
LockSupport.unpark(current);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
LockSupport.park(current);
|
||||
}
|
||||
|
||||
public String loadJS(String script, String source) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSDecoder evaluateJS(String script, String source, boolean hashKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void injectGlobalJSFunction(String name, JavaFunction javaFunction) {
|
||||
globalFunctions.put(name, javaFunction);
|
||||
webSocket.send(new JSONBuilder().put("cmd", "injectGlobalJSFunction")
|
||||
.put("name", name).toString()
|
||||
);
|
||||
}
|
||||
|
||||
public void injectGlobalJSObject(String name, JavaValue javaValue) {
|
||||
}
|
||||
|
||||
public JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (JavaValue javaValue : javaValues) {
|
||||
jsonArray.put(new JSONBuilder()
|
||||
.put("type", javaValue.getType())
|
||||
.put("value", javaValue.getValue())
|
||||
.toJSONObject());
|
||||
}
|
||||
webSocket.send(new JSONBuilder()
|
||||
.put("cmd", "invokeMethod")
|
||||
.put("objectName", objectName)
|
||||
.put("functionName", functionName)
|
||||
.put("javaValues", jsonArray)
|
||||
.put("hashKey", hashKey)
|
||||
.toString());
|
||||
|
||||
LockSupport.park(Thread.currentThread());
|
||||
return temp;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
webSocket.close(1000, "destroy");
|
||||
}
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
package pub.doric.devkit.remote;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Created by pengfei.zhou on 2018/4/17.
|
||||
*/
|
||||
public class ValueBuilder {
|
||||
private final Object val;
|
||||
|
||||
private void writeBoolean(ByteArrayOutputStream output, boolean b) {
|
||||
output.write((byte) (b ? 1 : 0));
|
||||
}
|
||||
|
||||
private void writeInt(ByteArrayOutputStream output, int i) {
|
||||
output.write((byte) (i >>> 24));
|
||||
output.write((byte) (i >>> 16));
|
||||
output.write((byte) (i >>> 8));
|
||||
output.write((byte) i);
|
||||
}
|
||||
|
||||
private void writeDouble(ByteArrayOutputStream output, double d) {
|
||||
long l = Double.doubleToRawLongBits(d);
|
||||
output.write((byte) (l >>> 56));
|
||||
output.write((byte) (l >>> 48));
|
||||
output.write((byte) (l >>> 40));
|
||||
output.write((byte) (l >>> 32));
|
||||
output.write((byte) (l >>> 24));
|
||||
output.write((byte) (l >>> 16));
|
||||
output.write((byte) (l >>> 8));
|
||||
output.write((byte) l);
|
||||
}
|
||||
|
||||
private void writeString(ByteArrayOutputStream output, String S) {
|
||||
byte[] buf;
|
||||
try {
|
||||
buf = S.getBytes("UTF-8");
|
||||
} catch (Exception e) {
|
||||
buf = new byte[0];
|
||||
}
|
||||
int i = buf.length;
|
||||
writeInt(output, i);
|
||||
output.write(buf, 0, i);
|
||||
}
|
||||
|
||||
|
||||
private void write(ByteArrayOutputStream output, Object O) {
|
||||
if (O instanceof Number) {
|
||||
output.write((byte) 'D');
|
||||
writeDouble(output, Double.valueOf(String.valueOf(O)));
|
||||
} else if (O instanceof String) {
|
||||
output.write((byte) 'S');
|
||||
writeString(output, (String) O);
|
||||
} else if (O instanceof Boolean) {
|
||||
output.write((byte) 'B');
|
||||
writeBoolean(output, (Boolean) O);
|
||||
} else if (O instanceof JSONObject) {
|
||||
output.write((byte) 'O');
|
||||
//writeBoolean(output, (Boolean) O);
|
||||
Iterator<String> iterator = ((JSONObject) O).keys();
|
||||
while (iterator.hasNext()) {
|
||||
String key = iterator.next();
|
||||
write(output, key);
|
||||
write(output, ((JSONObject) O).opt(key));
|
||||
}
|
||||
output.write((byte) 'N');
|
||||
} else if (O instanceof JSONArray) {
|
||||
output.write((byte) 'A');
|
||||
writeInt(output, ((JSONArray) O).length());
|
||||
for (int i = 0; i < ((JSONArray) O).length(); i++) {
|
||||
write(output, ((JSONArray) O).opt(i));
|
||||
}
|
||||
} else {
|
||||
output.write((byte) 'N');
|
||||
}
|
||||
}
|
||||
|
||||
public ValueBuilder(Object o) {
|
||||
this.val = o;
|
||||
}
|
||||
|
||||
public byte[] build() {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
write(outputStream, val);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
package pub.doric.devkit.ui;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.DoricContextManager;
|
||||
import pub.doric.devkit.DoricDev;
|
||||
import pub.doric.devkit.IDevKit;
|
||||
import pub.doric.devkit.R;
|
||||
import pub.doric.devkit.event.StartDebugEvent;
|
||||
|
||||
public class DebugContextPanel extends DialogFragment {
|
||||
|
||||
public DebugContextPanel() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState
|
||||
) {
|
||||
return inflater.inflate(R.layout.layout_debug_context, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null) {
|
||||
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
|
||||
LinearLayout container = getView().findViewById(R.id.container);
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
|
||||
for (final DoricContext doricContext : DoricContextManager.aliveContexts()) {
|
||||
View cell = inflater.inflate(R.layout.layout_debug_context_cell, container, false);
|
||||
|
||||
TextView contextIdTextView = cell.findViewById(R.id.context_id_text_view);
|
||||
contextIdTextView.setText(doricContext.getContextId());
|
||||
|
||||
TextView sourceTextView = cell.findViewById(R.id.source_text_view);
|
||||
sourceTextView.setText(doricContext.getSource());
|
||||
|
||||
cell.findViewById(R.id.debug_text_view).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
EventBus.getDefault().post(new StartDebugEvent(doricContext.getContextId()));
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("contextId", doricContext.getContextId());
|
||||
jsonObject.addProperty("source", doricContext.getSource().replace(".js", ".ts"));
|
||||
DoricDev.sendDevCommand(IDevKit.Command.DEBUG, jsonObject);
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
});
|
||||
|
||||
container.addView(cell);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.devkit.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import pub.doric.DoricActivity;
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.DoricContextManager;
|
||||
import pub.doric.devkit.DoricContextDebuggable;
|
||||
import pub.doric.devkit.event.EnterDebugEvent;
|
||||
import pub.doric.devkit.event.ReloadEvent;
|
||||
import pub.doric.devkit.event.StartDebugEvent;
|
||||
import pub.doric.devkit.event.StopDebugEvent;
|
||||
import pub.doric.devkit.util.SensorManagerHelper;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric.demo
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-11-19
|
||||
*/
|
||||
public class DemoDebugActivity extends DoricActivity {
|
||||
private SensorManagerHelper sensorHelper;
|
||||
private DoricContextDebuggable doricContextDebuggable;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
sensorHelper = new SensorManagerHelper(this);
|
||||
sensorHelper.setOnShakeListener(new SensorManagerHelper.OnShakeListener() {
|
||||
@Override
|
||||
public void onShake() {
|
||||
Fragment devPanel = getSupportFragmentManager().findFragmentByTag("DevPanel");
|
||||
if (devPanel != null && devPanel.isAdded()) {
|
||||
return;
|
||||
}
|
||||
new DevPanel().show(getSupportFragmentManager(), "DevPanel");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
sensorHelper.stop();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onStartDebugEvent(StartDebugEvent startDebugEvent) {
|
||||
doricContextDebuggable = new DoricContextDebuggable(startDebugEvent.getContextId());
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEnterDebugEvent(EnterDebugEvent enterDebugEvent) {
|
||||
doricContextDebuggable.startDebug();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onQuitDebugEvent(StopDebugEvent quitDebugEvent) {
|
||||
doricContextDebuggable.stopDebug();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onReloadEvent(ReloadEvent reloadEvent) {
|
||||
for (DoricContext context : DoricContextManager.aliveContexts()) {
|
||||
if (reloadEvent.source.contains(context.getSource())) {
|
||||
if (doricContextDebuggable != null &&
|
||||
doricContextDebuggable.isDebugging &&
|
||||
doricContextDebuggable.getContext().getContextId().equals(context.getContextId())) {
|
||||
System.out.println("is debugging context id: " + context.getContextId());
|
||||
} else {
|
||||
context.reload(reloadEvent.script);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (KeyEvent.KEYCODE_MENU == event.getKeyCode()) {
|
||||
new DevPanel().show(getSupportFragmentManager(), "DevPanel");
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
@@ -0,0 +1,136 @@
|
||||
package pub.doric.devkit.ui;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
import com.lahm.library.EasyProtectorLib;
|
||||
import com.lahm.library.EmulatorCheckCallback;
|
||||
import com.tbruyelle.rxpermissions2.RxPermissions;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import pub.doric.devkit.DevKit;
|
||||
import pub.doric.devkit.DoricDev;
|
||||
import pub.doric.devkit.R;
|
||||
import pub.doric.devkit.event.ConnectExceptionEvent;
|
||||
import pub.doric.devkit.event.EOFExceptionEvent;
|
||||
import pub.doric.devkit.event.OpenEvent;
|
||||
|
||||
public class DevPanel extends BottomSheetDialogFragment {
|
||||
|
||||
public static boolean isDevConnected = false;
|
||||
|
||||
public DevPanel() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState
|
||||
) {
|
||||
return inflater.inflate(R.layout.layout_dev, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
updateUI();
|
||||
|
||||
getView().findViewById(R.id.connect_dev_kit_text_view).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (DevKit.isRunningInEmulator) {
|
||||
DevKit.ip = "10.0.2.2";
|
||||
DoricDev.connectDevKit("ws://" + DevKit.ip + ":7777");
|
||||
} else {
|
||||
final RxPermissions rxPermissions = new RxPermissions(DevPanel.this);
|
||||
Disposable disposable = rxPermissions
|
||||
.request(Manifest.permission.CAMERA)
|
||||
.subscribe(new Consumer<Boolean>() {
|
||||
@Override
|
||||
public void accept(Boolean grant) throws Exception {
|
||||
if (grant) {
|
||||
Intent intent = new Intent(getContext(), ScanQRCodeActivity.class);
|
||||
getContext().startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getView().findViewById(R.id.debug_text_view).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
DebugContextPanel debugContextPanel = new DebugContextPanel();
|
||||
debugContextPanel.show(getActivity().getSupportFragmentManager(), "DebugContextPanel");
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
EventBus.getDefault().register(this);
|
||||
DevKit.isRunningInEmulator = EasyProtectorLib.checkIsRunningInEmulator(context, new EmulatorCheckCallback() {
|
||||
@Override
|
||||
public void findEmulator(String emulatorInfo) {
|
||||
System.out.println(emulatorInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onOpenEvent(OpenEvent openEvent) {
|
||||
updateUI();
|
||||
Toast.makeText(getContext(), "dev kit connected", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEOFEvent(EOFExceptionEvent eofExceptionEvent) {
|
||||
updateUI();
|
||||
Toast.makeText(getContext(), "dev kit eof exception", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onConnectExceptionEvent(ConnectExceptionEvent connectExceptionEvent) {
|
||||
updateUI();
|
||||
Toast.makeText(getContext(), "dev kit connection exception", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
if (isDevConnected) {
|
||||
getView().findViewById(R.id.connect_dev_kit_text_view).setVisibility(View.GONE);
|
||||
getView().findViewById(R.id.debug_text_view).setVisibility(View.VISIBLE);
|
||||
getView().findViewById(R.id.hot_reload_text_view).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
getView().findViewById(R.id.connect_dev_kit_text_view).setVisibility(View.VISIBLE);
|
||||
getView().findViewById(R.id.debug_text_view).setVisibility(View.GONE);
|
||||
getView().findViewById(R.id.hot_reload_text_view).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
package pub.doric.devkit.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cn.bingoogolapple.qrcode.core.QRCodeView;
|
||||
import cn.bingoogolapple.qrcode.zbar.ZBarView;
|
||||
import pub.doric.devkit.DevKit;
|
||||
import pub.doric.devkit.DoricDev;
|
||||
import pub.doric.devkit.R;
|
||||
|
||||
public class ScanQRCodeActivity extends AppCompatActivity implements QRCodeView.Delegate {
|
||||
|
||||
private ZBarView mZbarView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.layout_scan_qrcode);
|
||||
mZbarView = findViewById(R.id.zbar_view);
|
||||
mZbarView.setDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
mZbarView.startCamera();
|
||||
mZbarView.startSpotAndShowRect();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
mZbarView.stopCamera();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mZbarView.onDestroy();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanQRCodeSuccess(String result) {
|
||||
setTitle("扫描结果为:" + result);
|
||||
DevKit.ip = result;
|
||||
Toast.makeText(this, "dev kit connecting to " + result, Toast.LENGTH_LONG).show();
|
||||
DoricDev.connectDevKit("ws://" + result + ":7777");
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCameraAmbientBrightnessChanged(boolean isDark) {
|
||||
String tipText = mZbarView.getScanBoxView().getTipText();
|
||||
String ambientBrightnessTip = "\n环境过暗,请打开闪光灯";
|
||||
if (isDark) {
|
||||
if (!tipText.contains(ambientBrightnessTip)) {
|
||||
mZbarView.getScanBoxView().setTipText(tipText + ambientBrightnessTip);
|
||||
}
|
||||
} else {
|
||||
if (tipText.contains(ambientBrightnessTip)) {
|
||||
tipText = tipText.substring(0, tipText.indexOf(ambientBrightnessTip));
|
||||
mZbarView.getScanBoxView().setTipText(tipText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanQRCodeOpenCameraError() {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
package pub.doric.devkit.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
|
||||
public class SensorManagerHelper implements SensorEventListener {
|
||||
|
||||
// 速度阈值,当摇晃速度达到这值后产生作用
|
||||
private final int SPEED_SHRESHOLD = 5000;
|
||||
// 两次检测的时间间隔
|
||||
private final int UPTATE_INTERVAL_TIME = 50;
|
||||
// 传感器管理器
|
||||
private SensorManager sensorManager;
|
||||
// 传感器
|
||||
private Sensor sensor;
|
||||
// 重力感应监听器
|
||||
private OnShakeListener onShakeListener;
|
||||
// 上下文对象context
|
||||
private Context context;
|
||||
// 手机上一个位置时重力感应坐标
|
||||
private float lastX;
|
||||
private float lastY;
|
||||
private float lastZ;
|
||||
// 上次检测时间
|
||||
private long lastUpdateTime;
|
||||
|
||||
public SensorManagerHelper(Context context) {
|
||||
this.context = context;
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始检测
|
||||
*/
|
||||
public void start() {
|
||||
// 获得传感器管理器
|
||||
sensorManager = (SensorManager) context
|
||||
.getSystemService(Context.SENSOR_SERVICE);
|
||||
if (sensorManager != null) {
|
||||
// 获得重力传感器
|
||||
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
}
|
||||
// 注册
|
||||
if (sensor != null) {
|
||||
sensorManager.registerListener(this, sensor,
|
||||
SensorManager.SENSOR_DELAY_GAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止检测
|
||||
*/
|
||||
public void stop() {
|
||||
sensorManager.unregisterListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 摇晃监听接口
|
||||
*/
|
||||
public interface OnShakeListener {
|
||||
void onShake();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置重力感应监听器
|
||||
*/
|
||||
public void setOnShakeListener(OnShakeListener listener) {
|
||||
onShakeListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 重力感应器感应获得变化数据
|
||||
* android.hardware.SensorEventListener#onSensorChanged(android.hardware
|
||||
* .SensorEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
// 现在检测时间
|
||||
long currentUpdateTime = System.currentTimeMillis();
|
||||
// 两次检测的时间间隔
|
||||
long timeInterval = currentUpdateTime - lastUpdateTime;
|
||||
// 判断是否达到了检测时间间隔
|
||||
if (timeInterval < UPTATE_INTERVAL_TIME) return;
|
||||
// 现在的时间变成last时间
|
||||
lastUpdateTime = currentUpdateTime;
|
||||
// 获得x,y,z坐标
|
||||
float x = event.values[0];
|
||||
float y = event.values[1];
|
||||
float z = event.values[2];
|
||||
// 获得x,y,z的变化值
|
||||
float deltaX = x - lastX;
|
||||
float deltaY = y - lastY;
|
||||
float deltaZ = z - lastZ;
|
||||
// 将现在的坐标变成last坐标
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
lastZ = z;
|
||||
double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ
|
||||
* deltaZ)
|
||||
/ timeInterval * 10000;
|
||||
// 达到速度阀值,发出提示
|
||||
if (speed >= SPEED_SHRESHOLD) {
|
||||
onShakeListener.onShake();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/context_id_text_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:singleLine="true"
|
||||
android:text="{Context Id}"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/source_text_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_weight="3"
|
||||
android:gravity="center"
|
||||
android:singleLine="true"
|
||||
android:text="{Source}"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/debug_text_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#ff0000"
|
||||
android:gravity="center"
|
||||
android:singleLine="true"
|
||||
android:text="Debug"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
34
doric-android/devkit/src/main/res/layout/layout_dev.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@drawable/divider"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="middle">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/connect_dev_kit_text_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:gravity="center"
|
||||
android:text="Dev Kit"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/debug_text_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:gravity="center"
|
||||
android:text="Debug via Visual Studio Code"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hot_reload_text_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:gravity="center"
|
||||
android:text="Enable Hot Reload"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<cn.bingoogolapple.qrcode.zbar.ZBarView
|
||||
android:id="@+id/zbar_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:qrcv_animTime="1000"
|
||||
app:qrcv_borderColor="@android:color/white"
|
||||
app:qrcv_borderSize="1dp"
|
||||
app:qrcv_cornerColor="@android:color/white"
|
||||
app:qrcv_cornerLength="20dp"
|
||||
app:qrcv_cornerSize="3dp"
|
||||
app:qrcv_isShowDefaultScanLineDrawable="true"
|
||||
app:qrcv_maskColor="#33FFFFFF"
|
||||
app:qrcv_rectWidth="200dp"
|
||||
app:qrcv_scanLineColor="@android:color/white"
|
||||
app:qrcv_topOffset="90dp" />
|
||||
</LinearLayout>
|
3
doric-android/devkit/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">devkit</string>
|
||||
</resources>
|
1
doric-android/doric/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
55
doric-android/doric/build.gradle
Normal file
@@ -0,0 +1,55 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.2'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
buildJSBundle.exec()
|
||||
}
|
||||
|
||||
task buildJSBundle(type: Exec) {
|
||||
commandLine 'sh', project.rootDir.getParent() + "/bundle.sh"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
api 'com.github.penfeizhou:jsc4a:0.1.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
|
||||
implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.3.1'
|
||||
implementation 'jp.wasabeef:glide-transformations:4.1.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation "com.google.android.material:material:1.0.0"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
|
||||
|
||||
def nav_version = "2.1.0"
|
||||
|
||||
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
||||
implementation "androidx.navigation:navigation-ui:$nav_version"
|
||||
}
|
||||
|
||||
apply from: rootProject.file('scripts/upload.gradle')
|
4
doric-android/doric/pom.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
name=Doric
|
||||
groupId=pub.doric
|
||||
artifactId=core
|
||||
version=0.1.0
|
31
doric-android/doric/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# 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
|
||||
-keep class com.github.penfeizhou.doric.extension.bridge.DoricPlugin
|
||||
-keep class com.github.penfeizhou.doric.extension.bridge.DoricMethod
|
||||
|
||||
-keep @com.github.penfeizhou.doric.extension.bridge.DoricPlugin class * {*;}
|
||||
|
||||
-keepclasseswithmembers @com.github.penfeizhou.doric.extension.bridge.DoricPlugin class * {*;}
|
||||
|
||||
-keep class * {
|
||||
@com.github.penfeizhou.doric.extension.bridge.DoricMethod <fields>;
|
||||
}
|
17
doric-android/doric/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="pub.doric">
|
||||
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name="pub.doric.DoricActivity"
|
||||
android:theme="@style/Theme.Design.Light.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</manifest>
|
1
doric-android/doric/src/main/assets/bundle/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.js
|
35
doric-android/doric/src/main/java/pub/doric/Doric.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class Doric {
|
||||
private static Application sApplication;
|
||||
|
||||
public static void init(Application application) {
|
||||
sApplication = application;
|
||||
}
|
||||
|
||||
public static Application application() {
|
||||
return sApplication;
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric.demo
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-11-19
|
||||
*/
|
||||
public class DoricActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.doric_activity);
|
||||
if (savedInstanceState == null) {
|
||||
String scheme = getIntent().getStringExtra("scheme");
|
||||
String alias = getIntent().getStringExtra("alias");
|
||||
DoricFragment doricFragment = DoricFragment.newInstance(scheme, alias);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.container, doricFragment)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DoricComponent {
|
||||
String name() default "";
|
||||
}
|
214
doric-android/doric/src/main/java/pub/doric/DoricContext.java
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSONBuilder;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.navbar.IDoricNavBar;
|
||||
import pub.doric.navigator.IDoricNavigator;
|
||||
import pub.doric.plugin.DoricJavaPlugin;
|
||||
import pub.doric.shader.RootNode;
|
||||
import pub.doric.shader.ViewNode;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
import pub.doric.utils.DoricMetaInfo;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricContext {
|
||||
private final String mContextId;
|
||||
private final Map<String, DoricJavaPlugin> mPluginMap = new HashMap<>();
|
||||
private final Context mContext;
|
||||
private RootNode mRootNode = new RootNode(this);
|
||||
private final String source;
|
||||
private String script;
|
||||
private String extra;
|
||||
private JSONObject initParams;
|
||||
private IDoricDriver doricDriver;
|
||||
private final Map<String, ViewNode> mHeadNodes = new HashMap<>();
|
||||
|
||||
public Collection<ViewNode> allHeadNodes() {
|
||||
return mHeadNodes.values();
|
||||
}
|
||||
|
||||
public void addHeadNode(ViewNode viewNode) {
|
||||
mHeadNodes.put(viewNode.getId(), viewNode);
|
||||
}
|
||||
|
||||
public void removeHeadNode(ViewNode viewNode) {
|
||||
mHeadNodes.remove(viewNode.getId());
|
||||
}
|
||||
|
||||
public ViewNode targetViewNode(String id) {
|
||||
if (id.equals(mRootNode.getId())) {
|
||||
return mRootNode;
|
||||
}
|
||||
return mHeadNodes.get(id);
|
||||
}
|
||||
|
||||
protected DoricContext(Context context, String contextId, String source, String extra) {
|
||||
this.mContext = context;
|
||||
this.mContextId = contextId;
|
||||
this.source = source;
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public static DoricContext create(Context context, String script, String source, String extra) {
|
||||
DoricContext doricContext = DoricContextManager.getInstance().createContext(context, script, source, extra);
|
||||
doricContext.script = script;
|
||||
doricContext.extra = extra;
|
||||
return doricContext;
|
||||
}
|
||||
|
||||
public void init(float width, float height) {
|
||||
this.initParams = new JSONBuilder()
|
||||
.put("width", width)
|
||||
.put("height", height)
|
||||
.toJSONObject();
|
||||
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams, extra);
|
||||
callEntity(DoricConstant.DORIC_ENTITY_CREATE);
|
||||
}
|
||||
|
||||
public void reInit() {
|
||||
this.mRootNode.setId("");
|
||||
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams, extra);
|
||||
callEntity(DoricConstant.DORIC_ENTITY_CREATE);
|
||||
}
|
||||
|
||||
public AsyncResult<JSDecoder> callEntity(String methodName, Object... args) {
|
||||
return getDriver().invokeContextEntityMethod(mContextId, methodName, args);
|
||||
}
|
||||
|
||||
public IDoricDriver getDriver() {
|
||||
if (doricDriver == null) {
|
||||
doricDriver = DoricNativeDriver.getInstance();
|
||||
}
|
||||
return doricDriver;
|
||||
}
|
||||
|
||||
public void setDriver(IDoricDriver doricDriver) {
|
||||
this.doricDriver = doricDriver;
|
||||
}
|
||||
|
||||
public RootNode getRootNode() {
|
||||
return mRootNode;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public String getContextId() {
|
||||
return mContextId;
|
||||
}
|
||||
|
||||
public void teardown() {
|
||||
callEntity(DoricConstant.DORIC_ENTITY_DESTROY);
|
||||
DoricContextManager.getInstance().destroyContext(this).setCallback(new AsyncResult.Callback<Boolean>() {
|
||||
@Override
|
||||
public void onResult(Boolean result) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
mPluginMap.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DoricJavaPlugin obtainPlugin(DoricMetaInfo<DoricJavaPlugin> doricMetaInfo) {
|
||||
DoricJavaPlugin plugin = mPluginMap.get(doricMetaInfo.getName());
|
||||
if (plugin == null) {
|
||||
plugin = doricMetaInfo.createInstance(this);
|
||||
mPluginMap.put(doricMetaInfo.getName(), plugin);
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public void reload(String script) {
|
||||
this.script = script;
|
||||
this.mRootNode.setId("");
|
||||
getDriver().createContext(mContextId, script, source);
|
||||
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams, extra);
|
||||
onShow();
|
||||
}
|
||||
|
||||
public void onShow() {
|
||||
callEntity(DoricConstant.DORIC_ENTITY_SHOW);
|
||||
}
|
||||
|
||||
public void onHidden() {
|
||||
callEntity(DoricConstant.DORIC_ENTITY_HIDDEN);
|
||||
}
|
||||
|
||||
private IDoricNavigator doricNavigator;
|
||||
|
||||
public void setDoricNavigator(IDoricNavigator doricNavigator) {
|
||||
this.doricNavigator = doricNavigator;
|
||||
}
|
||||
|
||||
public IDoricNavigator getDoricNavigator() {
|
||||
return this.doricNavigator;
|
||||
}
|
||||
|
||||
private IDoricNavBar doricNavBar;
|
||||
|
||||
public void setDoricNavBar(IDoricNavBar navBar) {
|
||||
this.doricNavBar = navBar;
|
||||
}
|
||||
|
||||
public IDoricNavBar getDoricNavBar() {
|
||||
return this.doricNavBar;
|
||||
}
|
||||
|
||||
private AnimatorSet animatorSet;
|
||||
|
||||
public void setAnimatorSet(AnimatorSet animatorSet) {
|
||||
this.animatorSet = animatorSet;
|
||||
}
|
||||
|
||||
public AnimatorSet getAnimatorSet() {
|
||||
return this.animatorSet;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import pub.doric.async.AsyncResult;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-19
|
||||
*/
|
||||
public class DoricContextManager {
|
||||
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
private final Map<String, DoricContext> doricContextMap = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
private static class Inner {
|
||||
private static final DoricContextManager sInstance = new DoricContextManager();
|
||||
}
|
||||
|
||||
private DoricContextManager() {
|
||||
|
||||
}
|
||||
|
||||
public static DoricContextManager getInstance() {
|
||||
return Inner.sInstance;
|
||||
}
|
||||
|
||||
DoricContext createContext(Context context, final String script, final String source, String extra) {
|
||||
final String contextId = String.valueOf(counter.incrementAndGet());
|
||||
final DoricContext doricContext = new DoricContext(context, contextId, source, extra);
|
||||
doricContextMap.put(contextId, doricContext);
|
||||
doricContext.getDriver().createContext(contextId, script, source);
|
||||
return doricContext;
|
||||
}
|
||||
|
||||
AsyncResult<Boolean> destroyContext(final DoricContext context) {
|
||||
final AsyncResult<Boolean> result = new AsyncResult<>();
|
||||
context.getDriver().destroyContext(context.getContextId()).setCallback(new AsyncResult.Callback<Boolean>() {
|
||||
@Override
|
||||
public void onResult(Boolean b) {
|
||||
result.setResult(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
result.setError(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
doricContextMap.remove(context.getContextId());
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static DoricContext getContext(String contextId) {
|
||||
return getInstance().doricContextMap.get(contextId);
|
||||
}
|
||||
|
||||
public static Set<String> getKeySet() {
|
||||
return getInstance().doricContextMap.keySet();
|
||||
}
|
||||
|
||||
public static Collection<DoricContext> aliveContexts() {
|
||||
return getInstance().doricContextMap.values();
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-11-23
|
||||
*/
|
||||
public class DoricFragment extends Fragment {
|
||||
|
||||
public static DoricFragment newInstance(String scheme, String alias) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString("scheme", scheme);
|
||||
args.putString("alias", alias);
|
||||
DoricFragment fragment = new DoricFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host);
|
||||
if (!navController.popBackStack()) {
|
||||
if (getActivity() != null) {
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.doric_fragment, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-20
|
||||
*/
|
||||
public abstract class DoricLibrary {
|
||||
public abstract void load(DoricRegistry registry);
|
||||
}
|
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import pub.doric.async.AsyncCall;
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.engine.DoricJSEngine;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
import pub.doric.utils.DoricLog;
|
||||
import pub.doric.utils.ThreadMode;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricNativeDriver implements IDoricDriver {
|
||||
private final DoricJSEngine doricJSEngine;
|
||||
private final ExecutorService mBridgeExecutor;
|
||||
private final Handler mUIHandler;
|
||||
private final Handler mJSHandler;
|
||||
|
||||
private static class Inner {
|
||||
private static final DoricNativeDriver sInstance = new DoricNativeDriver();
|
||||
}
|
||||
|
||||
private DoricNativeDriver() {
|
||||
doricJSEngine = new DoricJSEngine();
|
||||
mBridgeExecutor = Executors.newCachedThreadPool();
|
||||
mUIHandler = new Handler(Looper.getMainLooper());
|
||||
mJSHandler = doricJSEngine.getJSHandler();
|
||||
}
|
||||
|
||||
public static DoricNativeDriver getInstance() {
|
||||
return Inner.sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<JSDecoder> invokeContextEntityMethod(final String contextId, final String method, final Object... args) {
|
||||
final Object[] nArgs = new Object[args.length + 2];
|
||||
nArgs[0] = contextId;
|
||||
nArgs[1] = method;
|
||||
if (args.length > 0) {
|
||||
System.arraycopy(args, 0, nArgs, 2, args.length);
|
||||
}
|
||||
return invokeDoricMethod(DoricConstant.DORIC_CONTEXT_INVOKE, nArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<JSDecoder>() {
|
||||
@Override
|
||||
public JSDecoder call() {
|
||||
try {
|
||||
return doricJSEngine.invokeDoricMethod(method, args);
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("invokeDoricMethod(%s,...),error is %s", method, e.getLocalizedMessage());
|
||||
return new JSDecoder(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> AsyncResult<T> asyncCall(Callable<T> callable, ThreadMode threadMode) {
|
||||
switch (threadMode) {
|
||||
case JS:
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, callable);
|
||||
case UI:
|
||||
return AsyncCall.ensureRunInHandler(mUIHandler, callable);
|
||||
case INDEPENDENT:
|
||||
default:
|
||||
return AsyncCall.ensureRunInExecutor(mBridgeExecutor, callable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
doricJSEngine.prepareContext(contextId, script, source);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("createContext %s error is %s", source, e.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> destroyContext(final String contextId) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
doricJSEngine.destroyContext(contextId);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("destroyContext %s error is %s", contextId, e.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoricRegistry getRegistry() {
|
||||
return doricJSEngine.getRegistry();
|
||||
}
|
||||
}
|
113
doric-android/doric/src/main/java/pub/doric/DoricPanel.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricPanel extends FrameLayout implements LifecycleObserver {
|
||||
|
||||
private DoricContext mDoricContext;
|
||||
|
||||
public DoricPanel(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public DoricPanel(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public DoricPanel(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
if (getContext() instanceof LifecycleOwner) {
|
||||
((LifecycleOwner) getContext()).getLifecycle().addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void config(String script, String alias, String extra) {
|
||||
DoricContext doricContext = DoricContext.create(getContext(), script, alias, extra);
|
||||
config(doricContext);
|
||||
}
|
||||
|
||||
public void config(DoricContext doricContext) {
|
||||
mDoricContext = doricContext;
|
||||
mDoricContext.getRootNode().setRootView(this);
|
||||
if (getMeasuredState() != 0) {
|
||||
mDoricContext.init(DoricUtils.px2dp(getMeasuredWidth()), DoricUtils.px2dp(getMeasuredHeight()));
|
||||
}
|
||||
if (getContext() instanceof LifecycleOwner
|
||||
&& ((LifecycleOwner) getContext()).getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
|
||||
mDoricContext.onShow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
}
|
||||
|
||||
public DoricContext getDoricContext() {
|
||||
return mDoricContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
if (oldw != w || oldh != h) {
|
||||
if (mDoricContext != null) {
|
||||
mDoricContext.init(DoricUtils.px2dp(w), DoricUtils.px2dp(h));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||
public void onActivityResume() {
|
||||
if (mDoricContext != null) {
|
||||
mDoricContext.onShow();
|
||||
}
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||
public void onActivityPause() {
|
||||
if (mDoricContext != null) {
|
||||
mDoricContext.onHidden();
|
||||
}
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
||||
public void onActivityDestroy() {
|
||||
if (mDoricContext != null) {
|
||||
mDoricContext.teardown();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.loader.DoricJSLoaderManager;
|
||||
import pub.doric.navbar.BaseDoricNavBar;
|
||||
import pub.doric.navigator.IDoricNavigator;
|
||||
import pub.doric.utils.DoricLog;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-11-23
|
||||
*/
|
||||
public class DoricPanelFragment extends Fragment implements IDoricNavigator {
|
||||
private DoricPanel doricPanel;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.doric_framgent_panel, container, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
doricPanel = view.findViewById(R.id.doric_panel);
|
||||
Bundle argument = getArguments();
|
||||
if (argument == null) {
|
||||
if (getActivity() != null && getActivity().getIntent() != null) {
|
||||
argument = getActivity().getIntent().getExtras();
|
||||
}
|
||||
}
|
||||
if (argument == null) {
|
||||
DoricLog.e("DoricPanelFragment argument is null");
|
||||
return;
|
||||
}
|
||||
final String alias = argument.getString("alias");
|
||||
String scheme = argument.getString("scheme");
|
||||
final String extra = argument.getString("extra");
|
||||
DoricJSLoaderManager.getInstance().loadJSBundle(scheme).setCallback(new AsyncResult.Callback<String>() {
|
||||
@Override
|
||||
public void onResult(String result) {
|
||||
doricPanel.config(result, alias, extra);
|
||||
DoricContext context = doricPanel.getDoricContext();
|
||||
context.setDoricNavigator(DoricPanelFragment.this);
|
||||
BaseDoricNavBar navBar = requireActivity().getWindow().getDecorView().findViewById(R.id.doric_nav_bar);
|
||||
context.setDoricNavBar(navBar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
DoricLog.e("DoricPanelFragment load JS error:" + t.getLocalizedMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(String scheme, String alias, String extra) {
|
||||
Bundle argument = new Bundle();
|
||||
argument.putString("scheme", scheme);
|
||||
argument.putString("alias", alias);
|
||||
argument.putString("extra", extra);
|
||||
getNavController()
|
||||
.navigate(R.id.action_doricPanelFragment_to_doricPanelFragment, argument);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pop() {
|
||||
getNavController().popBackStack();
|
||||
}
|
||||
|
||||
private NavController getNavController() {
|
||||
return Navigation.findNavController(getView());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
doricPanel.onActivityResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
doricPanel.onActivityPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
doricPanel.onActivityDestroy();
|
||||
}
|
||||
}
|
153
doric-android/doric/src/main/java/pub/doric/DoricRegistry.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import pub.doric.loader.DoricAssetJSLoader;
|
||||
import pub.doric.loader.DoricHttpJSLoader;
|
||||
import pub.doric.loader.IDoricJSLoader;
|
||||
import pub.doric.plugin.AnimatePlugin;
|
||||
import pub.doric.plugin.NavBarPlugin;
|
||||
import pub.doric.plugin.NavigatorPlugin;
|
||||
import pub.doric.plugin.NetworkPlugin;
|
||||
import pub.doric.plugin.PopoverPlugin;
|
||||
import pub.doric.plugin.ShaderPlugin;
|
||||
import pub.doric.plugin.StoragePlugin;
|
||||
import pub.doric.refresh.RefreshableNode;
|
||||
import pub.doric.shader.HLayoutNode;
|
||||
import pub.doric.shader.ImageNode;
|
||||
import pub.doric.shader.InputNode;
|
||||
import pub.doric.shader.ScrollerNode;
|
||||
import pub.doric.shader.flowlayout.FlowLayoutItemNode;
|
||||
import pub.doric.shader.flowlayout.FlowLayoutNode;
|
||||
import pub.doric.shader.list.ListItemNode;
|
||||
import pub.doric.shader.list.ListNode;
|
||||
import pub.doric.shader.RootNode;
|
||||
import pub.doric.shader.StackNode;
|
||||
import pub.doric.shader.TextNode;
|
||||
import pub.doric.shader.VLayoutNode;
|
||||
import pub.doric.shader.ViewNode;
|
||||
import pub.doric.shader.slider.NestedSliderNode;
|
||||
import pub.doric.shader.slider.SlideItemNode;
|
||||
import pub.doric.shader.slider.SliderNode;
|
||||
import pub.doric.utils.DoricMetaInfo;
|
||||
import pub.doric.plugin.DoricJavaPlugin;
|
||||
import pub.doric.plugin.ModalPlugin;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-20
|
||||
*/
|
||||
public class DoricRegistry {
|
||||
private static Map<String, String> bundles = new ConcurrentHashMap<>();
|
||||
private static Set<DoricLibrary> doricLibraries = new HashSet<>();
|
||||
private static Set<IDoricJSLoader> jsLoaders = new HashSet<>();
|
||||
|
||||
static {
|
||||
addJSLoader(new DoricAssetJSLoader());
|
||||
addJSLoader(new DoricHttpJSLoader());
|
||||
}
|
||||
|
||||
private Map<String, DoricMetaInfo<DoricJavaPlugin>> pluginInfoMap = new HashMap<>();
|
||||
private Map<String, DoricMetaInfo<ViewNode>> nodeInfoMap = new HashMap<>();
|
||||
|
||||
private static void initRegistry(DoricRegistry doricRegistry) {
|
||||
for (DoricLibrary library : doricLibraries) {
|
||||
library.load(doricRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void register(DoricLibrary doricLibrary) {
|
||||
doricLibraries.add(doricLibrary);
|
||||
}
|
||||
|
||||
public DoricRegistry() {
|
||||
this.registerNativePlugin(ShaderPlugin.class);
|
||||
this.registerNativePlugin(ModalPlugin.class);
|
||||
this.registerNativePlugin(NetworkPlugin.class);
|
||||
this.registerNativePlugin(StoragePlugin.class);
|
||||
this.registerNativePlugin(NavigatorPlugin.class);
|
||||
this.registerNativePlugin(NavBarPlugin.class);
|
||||
this.registerNativePlugin(PopoverPlugin.class);
|
||||
this.registerNativePlugin(AnimatePlugin.class);
|
||||
|
||||
this.registerViewNode(RootNode.class);
|
||||
this.registerViewNode(TextNode.class);
|
||||
this.registerViewNode(ImageNode.class);
|
||||
this.registerViewNode(StackNode.class);
|
||||
this.registerViewNode(VLayoutNode.class);
|
||||
this.registerViewNode(HLayoutNode.class);
|
||||
this.registerViewNode(ListNode.class);
|
||||
this.registerViewNode(ListItemNode.class);
|
||||
this.registerViewNode(ScrollerNode.class);
|
||||
this.registerViewNode(SliderNode.class);
|
||||
this.registerViewNode(SlideItemNode.class);
|
||||
this.registerViewNode(RefreshableNode.class);
|
||||
this.registerViewNode(FlowLayoutNode.class);
|
||||
this.registerViewNode(FlowLayoutItemNode.class);
|
||||
this.registerViewNode(InputNode.class);
|
||||
this.registerViewNode(NestedSliderNode.class);
|
||||
initRegistry(this);
|
||||
}
|
||||
|
||||
public void registerJSBundle(String name, String bundle) {
|
||||
bundles.put(name, bundle);
|
||||
}
|
||||
|
||||
public void registerNativePlugin(Class<? extends DoricJavaPlugin> pluginClass) {
|
||||
DoricMetaInfo<DoricJavaPlugin> doricMetaInfo = new DoricMetaInfo<>(pluginClass);
|
||||
if (!TextUtils.isEmpty(doricMetaInfo.getName())) {
|
||||
pluginInfoMap.put(doricMetaInfo.getName(), doricMetaInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public DoricMetaInfo<DoricJavaPlugin> acquirePluginInfo(String name) {
|
||||
return pluginInfoMap.get(name);
|
||||
}
|
||||
|
||||
public void registerViewNode(Class<? extends ViewNode> pluginClass) {
|
||||
DoricMetaInfo<ViewNode> doricMetaInfo = new DoricMetaInfo<>(pluginClass);
|
||||
if (!TextUtils.isEmpty(doricMetaInfo.getName())) {
|
||||
nodeInfoMap.put(doricMetaInfo.getName(), doricMetaInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public DoricMetaInfo<ViewNode> acquireViewNodeInfo(String name) {
|
||||
return nodeInfoMap.get(name);
|
||||
}
|
||||
|
||||
public String acquireJSBundle(String name) {
|
||||
return bundles.get(name);
|
||||
}
|
||||
|
||||
public static void addJSLoader(IDoricJSLoader jsLoader) {
|
||||
jsLoaders.add(jsLoader);
|
||||
}
|
||||
|
||||
public static Collection<IDoricJSLoader> getJSLoaders() {
|
||||
return jsLoaders;
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric;
|
||||
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.utils.ThreadMode;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-19
|
||||
*/
|
||||
public interface IDoricDriver {
|
||||
|
||||
AsyncResult<JSDecoder> invokeContextEntityMethod(final String contextId, final String method, final Object... args);
|
||||
|
||||
AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args);
|
||||
|
||||
<T> AsyncResult<T> asyncCall(Callable<T> callable, ThreadMode threadMode);
|
||||
|
||||
AsyncResult<Boolean> createContext(final String contextId, final String script, final String source);
|
||||
|
||||
AsyncResult<Boolean> destroyContext(final String contextId);
|
||||
|
||||
DoricRegistry getRegistry();
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.async;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric.async
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-19
|
||||
*/
|
||||
public class AsyncCall {
|
||||
|
||||
public static <T> AsyncResult<T> ensureRunInHandler(Handler handler, final Callable<T> callable) {
|
||||
final AsyncResult<T> asyncResult = new AsyncResult<>();
|
||||
if (Looper.myLooper() == handler.getLooper()) {
|
||||
try {
|
||||
asyncResult.setResult(callable.call());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
asyncResult.setError(e);
|
||||
}
|
||||
} else {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
asyncResult.setResult(callable.call());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
asyncResult.setError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return asyncResult;
|
||||
}
|
||||
|
||||
public static <T> AsyncResult<T> ensureRunInExecutor(ExecutorService executorService, final Callable<T> callable) {
|
||||
final AsyncResult<T> asyncResult = new AsyncResult<>();
|
||||
executorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
asyncResult.setResult(callable.call());
|
||||
} catch (Exception e) {
|
||||
asyncResult.setError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return asyncResult;
|
||||
}
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.async;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric.async
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-19
|
||||
*/
|
||||
public class AsyncResult<R> {
|
||||
private static Object EMPTY = new Object();
|
||||
private Object result = EMPTY;
|
||||
|
||||
private Callback<R> callback = null;
|
||||
|
||||
public AsyncResult() {
|
||||
}
|
||||
|
||||
public AsyncResult(R r) {
|
||||
this.result = r;
|
||||
}
|
||||
|
||||
public void setResult(R result) {
|
||||
this.result = result;
|
||||
if (this.callback != null) {
|
||||
this.callback.onResult(result);
|
||||
this.callback.onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
public void setError(Throwable result) {
|
||||
this.result = result;
|
||||
if (this.callback != null) {
|
||||
this.callback.onError(result);
|
||||
this.callback.onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasResult() {
|
||||
return result != EMPTY;
|
||||
}
|
||||
|
||||
public R getResult() {
|
||||
return (R) result;
|
||||
}
|
||||
|
||||
public void setCallback(Callback<R> callback) {
|
||||
this.callback = callback;
|
||||
if (result instanceof Throwable) {
|
||||
this.callback.onError((Throwable) result);
|
||||
this.callback.onFinish();
|
||||
} else if (result != EMPTY) {
|
||||
this.callback.onResult((R) result);
|
||||
this.callback.onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
public SettableFuture<R> synchronous() {
|
||||
final SettableFuture<R> settableFuture = new SettableFuture<>();
|
||||
|
||||
setCallback(new Callback<R>() {
|
||||
@Override
|
||||
public void onResult(R result) {
|
||||
settableFuture.set(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
settableFuture.set(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
||||
}
|
||||
});
|
||||
return settableFuture;
|
||||
}
|
||||
|
||||
public interface Callback<R> {
|
||||
void onResult(R result);
|
||||
|
||||
void onError(Throwable t);
|
||||
|
||||
void onFinish();
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.async;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric.async
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A super simple Future-like class that can safely notify another Thread when a value is ready.
|
||||
* Does not support setting errors or canceling.
|
||||
*/
|
||||
public class SettableFuture<T> {
|
||||
|
||||
private final CountDownLatch mReadyLatch = new CountDownLatch(1);
|
||||
private volatile
|
||||
T mResult;
|
||||
|
||||
/**
|
||||
* Sets the result. If another thread has called {@link #get}, they will immediately receive the
|
||||
* value. Must only be called once.
|
||||
*/
|
||||
public void set(T result) {
|
||||
if (mReadyLatch.getCount() == 0) {
|
||||
throw new RuntimeException("Result has already been set!");
|
||||
}
|
||||
mResult = result;
|
||||
mReadyLatch.countDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait up to the timeout time for another Thread to set a value on this future. If a value has
|
||||
* already been set, this method will return immediately.
|
||||
* <p>
|
||||
* NB: For simplicity, we catch and wrap InterruptedException. Do NOT use this class if you
|
||||
* are in the 1% of cases where you actually want to handle that.
|
||||
*/
|
||||
public T get(long timeoutMS) {
|
||||
try {
|
||||
if (!mReadyLatch.await(timeoutMS, TimeUnit.MILLISECONDS)) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return mResult;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
try {
|
||||
mReadyLatch.await();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return mResult;
|
||||
}
|
||||
|
||||
public static class TimeoutException extends RuntimeException {
|
||||
|
||||
public TimeoutException() {
|
||||
super("Timed out waiting for future");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.engine;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSONBuilder;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import pub.doric.Doric;
|
||||
import pub.doric.DoricRegistry;
|
||||
import pub.doric.extension.bridge.DoricBridgeExtension;
|
||||
import pub.doric.extension.timer.DoricTimerExtension;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
import pub.doric.utils.DoricLog;
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.TimerCallback {
|
||||
|
||||
private HandlerThread handlerThread;
|
||||
private final Handler mJSHandler;
|
||||
private final DoricBridgeExtension mDoricBridgeExtension = new DoricBridgeExtension();
|
||||
protected IDoricJSE mDoricJSE;
|
||||
private final DoricTimerExtension mTimerExtension;
|
||||
private final DoricRegistry mDoricRegistry = new DoricRegistry();
|
||||
|
||||
public DoricJSEngine() {
|
||||
handlerThread = new HandlerThread(this.getClass().getSimpleName());
|
||||
handlerThread.start();
|
||||
Looper looper = handlerThread.getLooper();
|
||||
mJSHandler = new Handler(looper, this);
|
||||
mJSHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initJSEngine();
|
||||
injectGlobal();
|
||||
initDoricRuntime();
|
||||
}
|
||||
});
|
||||
mTimerExtension = new DoricTimerExtension(looper, this);
|
||||
}
|
||||
|
||||
public Handler getJSHandler() {
|
||||
return mJSHandler;
|
||||
}
|
||||
|
||||
protected void initJSEngine() {
|
||||
mDoricJSE = new DoricNativeJSExecutor();
|
||||
}
|
||||
|
||||
private void injectGlobal() {
|
||||
String appName = "";
|
||||
String appVersion = "";
|
||||
Context context = Doric.application();
|
||||
try {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(
|
||||
context.getPackageName(), 0);
|
||||
int labelRes = packageInfo.applicationInfo.labelRes;
|
||||
appName = context.getResources().getString(labelRes);
|
||||
appVersion = packageInfo.versionName;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
mDoricJSE.injectGlobalJSObject(DoricConstant.INJECT_ENVIRONMENT, new JavaValue(new JSONBuilder()
|
||||
.put("platform", "Android")
|
||||
.put("platformVersion", String.valueOf(android.os.Build.VERSION.SDK_INT))
|
||||
.put("appName", appName)
|
||||
.put("appVersion", appVersion)
|
||||
.put("screenWidth", DoricUtils.px2dp(DoricUtils.getScreenWidth()))
|
||||
.put("screenHeight", DoricUtils.px2dp(DoricUtils.getScreenHeight()))
|
||||
.toJSONObject()));
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_LOG, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
String type = args[0].string();
|
||||
String message = args[1].string();
|
||||
switch (type) {
|
||||
case "w":
|
||||
DoricLog.suffix_w("_js", message);
|
||||
break;
|
||||
case "e":
|
||||
DoricLog.suffix_e("_js", message);
|
||||
break;
|
||||
default:
|
||||
DoricLog.suffix_d("_js", message);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_EMPTY, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_REQUIRE, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
String name = args[0].string();
|
||||
String content = mDoricRegistry.acquireJSBundle(name);
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
DoricLog.e("require js bundle:%s is empty", name);
|
||||
return new JavaValue(false);
|
||||
}
|
||||
mDoricJSE.loadJS(packageModuleScript(name, content), "Module://" + name);
|
||||
return new JavaValue(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new JavaValue(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_TIMER_SET, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
mTimerExtension.setTimer(
|
||||
args[0].number().longValue(),
|
||||
args[1].number().longValue(),
|
||||
args[2].bool());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_TIMER_CLEAR, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
mTimerExtension.clearTimer(args[0].number().longValue());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_BRIDGE, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
String contextId = args[0].string();
|
||||
String module = args[1].string();
|
||||
String method = args[2].string();
|
||||
String callbackId = args[3].string();
|
||||
JSDecoder jsDecoder = args[4];
|
||||
return mDoricBridgeExtension.callNative(contextId, module, method, callbackId, jsDecoder);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initDoricRuntime() {
|
||||
loadBuiltinJS(DoricConstant.DORIC_BUNDLE_SANDBOX);
|
||||
String libName = DoricConstant.DORIC_MODULE_LIB;
|
||||
String libJS = DoricUtils.readAssetFile(DoricConstant.DORIC_BUNDLE_LIB);
|
||||
mDoricJSE.loadJS(packageModuleScript(libName, libJS), "Module://" + libName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void teardown() {
|
||||
mDoricJSE.teardown();
|
||||
mTimerExtension.teardown();
|
||||
handlerThread.quit();
|
||||
mJSHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
|
||||
private void loadBuiltinJS(String assetName) {
|
||||
String script = DoricUtils.readAssetFile(assetName);
|
||||
mDoricJSE.loadJS(script, "Assets://" + assetName);
|
||||
}
|
||||
|
||||
public void prepareContext(final String contextId, final String script, final String source) {
|
||||
mDoricJSE.loadJS(packageContextScript(contextId, script), "Context://" + source);
|
||||
}
|
||||
|
||||
public void destroyContext(final String contextId) {
|
||||
mDoricJSE.loadJS(String.format(DoricConstant.TEMPLATE_CONTEXT_DESTROY, contextId), "_Context://" + contextId);
|
||||
}
|
||||
|
||||
private String packageContextScript(String contextId, String content) {
|
||||
return String.format(DoricConstant.TEMPLATE_CONTEXT_CREATE, content, contextId, contextId, contextId);
|
||||
}
|
||||
|
||||
private String packageModuleScript(String moduleName, String content) {
|
||||
return String.format(DoricConstant.TEMPLATE_MODULE, moduleName, content);
|
||||
}
|
||||
|
||||
public JSDecoder invokeDoricMethod(final String method, final Object... args) {
|
||||
ArrayList<JavaValue> values = new ArrayList<>();
|
||||
for (Object arg : args) {
|
||||
values.add(DoricUtils.toJavaValue(arg));
|
||||
}
|
||||
return mDoricJSE.invokeMethod(DoricConstant.GLOBAL_DORIC, method,
|
||||
values.toArray(new JavaValue[values.size()]), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callback(long timerId) {
|
||||
try {
|
||||
invokeDoricMethod(DoricConstant.DORIC_TIMER_CALLBACK, timerId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
DoricLog.e("Timer Callback error:%s", e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public DoricRegistry getRegistry() {
|
||||
return mDoricRegistry;
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.engine;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSExecutor;
|
||||
import com.github.pengfeizhou.jscore.JSRuntimeException;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricNativeJSExecutor implements IDoricJSE {
|
||||
|
||||
private final JSExecutor mJSExecutor;
|
||||
|
||||
public DoricNativeJSExecutor() {
|
||||
this.mJSExecutor = JSExecutor.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loadJS(String script, String source) throws JSRuntimeException {
|
||||
return mJSExecutor.loadJS(script, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder evaluateJS(String script, String source, boolean hashKey) throws JSRuntimeException {
|
||||
return mJSExecutor.evaluateJS(script, source, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSFunction(String name, JavaFunction javaFunction) {
|
||||
mJSExecutor.injectGlobalJSFunction(name, javaFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSObject(String name, JavaValue javaValue) {
|
||||
mJSExecutor.injectGlobalJSObject(name, javaValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) throws JSRuntimeException {
|
||||
return mJSExecutor.invokeMethod(objectName, functionName, javaValues, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teardown() {
|
||||
mJSExecutor.destroy();
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.engine;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSRuntimeException;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public interface IDoricJSE {
|
||||
/**
|
||||
* 执行JS语句
|
||||
*
|
||||
* @param script 执行的JS语句
|
||||
* @param source 该JS语句对应的文件名,在输出错误的堆栈信息时有用
|
||||
* @return 返回JS语句的执行结果,以String形式返回
|
||||
* @throws JSRuntimeException 如果执行的脚本有异常,会抛出包含堆栈的JSRuntimeException
|
||||
*/
|
||||
String loadJS(String script, String source) throws JSRuntimeException;
|
||||
|
||||
/**
|
||||
* 执行JS语句
|
||||
*
|
||||
* @param script 执行的JS语句
|
||||
* @param source 该JS语句对应的文件名,在输出错误的堆栈信息时有用
|
||||
* @param hashKey 是否在返回对象序列化时将key hash化
|
||||
* @return 返回JS语句的执行结果,以二进制数据的形式返回
|
||||
* @throws JSRuntimeException 如果执行的脚本有异常,会抛出包含堆栈的JSRuntimeException
|
||||
*/
|
||||
JSDecoder evaluateJS(String script, String source, boolean hashKey) throws JSRuntimeException;
|
||||
|
||||
|
||||
/**
|
||||
* 向JS注入全局方法,由java实现
|
||||
*
|
||||
* @param name js的方法名
|
||||
* @param javaFunction java中对应的实现类
|
||||
*/
|
||||
void injectGlobalJSFunction(String name, JavaFunction javaFunction);
|
||||
|
||||
/**
|
||||
* 向JS注入全局变量
|
||||
*
|
||||
* @param name js中的变量名
|
||||
* @param javaValue 注入的全局变量,按Value进行组装
|
||||
*/
|
||||
void injectGlobalJSObject(String name, JavaValue javaValue);
|
||||
|
||||
/**
|
||||
* 执行JS某个方法
|
||||
*
|
||||
* @param objectName 执行的方法所属的变量名,如果方法为全局方法,该参数传null
|
||||
* @param functionName 执行的方法名
|
||||
* @param javaValues 方法需要的参数列表,按数组传入
|
||||
* @param hashKey 是否在返回对象序列化时将key hash化
|
||||
* @throws JSRuntimeException 如果执行的方法有异常,会抛出包含堆栈的JSRuntimeException
|
||||
*/
|
||||
JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) throws JSRuntimeException;
|
||||
|
||||
void teardown();
|
||||
}
|
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.extension.bridge;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.plugin.DoricJavaPlugin;
|
||||
import pub.doric.DoricContextManager;
|
||||
import pub.doric.utils.DoricLog;
|
||||
import pub.doric.utils.DoricMetaInfo;
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricBridgeExtension {
|
||||
|
||||
public DoricBridgeExtension() {
|
||||
}
|
||||
|
||||
public JavaValue callNative(String contextId, String module, String methodName, final String callbackId, final JSDecoder jsDecoder) {
|
||||
final DoricContext context = DoricContextManager.getContext(contextId);
|
||||
DoricMetaInfo<DoricJavaPlugin> pluginInfo = context.getDriver().getRegistry().acquirePluginInfo(module);
|
||||
if (pluginInfo == null) {
|
||||
DoricLog.e("Cannot find plugin class:%s", module);
|
||||
return new JavaValue(false);
|
||||
}
|
||||
final DoricJavaPlugin doricJavaPlugin = context.obtainPlugin(pluginInfo);
|
||||
if (doricJavaPlugin == null) {
|
||||
DoricLog.e("Cannot obtain plugin instance:%s,method:%", module);
|
||||
return new JavaValue(false);
|
||||
}
|
||||
final Method method = pluginInfo.getMethod(methodName);
|
||||
if (method == null) {
|
||||
DoricLog.e("Cannot find plugin method in class:%s,method:%s", module, methodName);
|
||||
return new JavaValue(false);
|
||||
}
|
||||
DoricMethod doricMethod = method.getAnnotation(DoricMethod.class);
|
||||
if (doricMethod == null) {
|
||||
DoricLog.e("Cannot find DoricMethod annotation in class:%s,method:%s", module, methodName);
|
||||
return new JavaValue(false);
|
||||
}
|
||||
Callable<JavaValue> callable = new Callable<JavaValue>() {
|
||||
@Override
|
||||
public JavaValue call() throws Exception {
|
||||
Class[] classes = method.getParameterTypes();
|
||||
Object ret;
|
||||
if (classes.length == 0) {
|
||||
ret = method.invoke(doricJavaPlugin);
|
||||
} else if (classes.length == 1) {
|
||||
ret = method.invoke(doricJavaPlugin, createParam(context, classes[0], callbackId, jsDecoder));
|
||||
} else {
|
||||
ret = method.invoke(doricJavaPlugin,
|
||||
createParam(context, classes[0], callbackId, jsDecoder),
|
||||
createParam(context, classes[1], callbackId, jsDecoder));
|
||||
}
|
||||
return DoricUtils.toJavaValue(ret);
|
||||
}
|
||||
};
|
||||
AsyncResult<JavaValue> asyncResult = context.getDriver().asyncCall(callable, doricMethod.thread());
|
||||
if (asyncResult.hasResult()) {
|
||||
return asyncResult.getResult();
|
||||
}
|
||||
return new JavaValue(true);
|
||||
}
|
||||
|
||||
private Object createParam(DoricContext context, Class clz, String callbackId, JSDecoder jsDecoder) {
|
||||
if (clz == DoricPromise.class) {
|
||||
return new DoricPromise(context, callbackId);
|
||||
} else {
|
||||
try {
|
||||
return DoricUtils.toJavaObject(clz, jsDecoder);
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("createParam error:%s", e.getLocalizedMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.extension.bridge;
|
||||
|
||||
import pub.doric.utils.ThreadMode;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DoricMethod {
|
||||
String name() default "";
|
||||
|
||||
ThreadMode thread() default ThreadMode.INDEPENDENT;
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.extension.bridge;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DoricPlugin {
|
||||
String name();
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.extension.bridge;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doric.extension.bridge
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-19
|
||||
*/
|
||||
public class DoricPromise {
|
||||
private final DoricContext context;
|
||||
private final String callbackId;
|
||||
|
||||
public DoricPromise(DoricContext context, String callbackId) {
|
||||
this.context = context;
|
||||
this.callbackId = callbackId;
|
||||
}
|
||||
|
||||
public void resolve(JavaValue... javaValue) {
|
||||
Object[] params = new Object[javaValue.length + 2];
|
||||
params[0] = context.getContextId();
|
||||
params[1] = callbackId;
|
||||
System.arraycopy(javaValue, 0, params, 2, javaValue.length);
|
||||
context.getDriver().invokeDoricMethod(
|
||||
DoricConstant.DORIC_BRIDGE_RESOLVE,
|
||||
params);
|
||||
}
|
||||
|
||||
public void reject(JavaValue... javaValue) {
|
||||
Object[] params = new Object[javaValue.length + 2];
|
||||
params[0] = context.getContextId();
|
||||
params[1] = callbackId;
|
||||
System.arraycopy(javaValue, 0, params, 2, javaValue.length);
|
||||
context.getDriver().invokeDoricMethod(
|
||||
DoricConstant.DORIC_BRIDGE_REJECT,
|
||||
params);
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.extension.timer;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricTimerExtension implements Handler.Callback {
|
||||
|
||||
private static final int MSG_TIMER = 0;
|
||||
private final Handler mTimerHandler;
|
||||
private final TimerCallback mTimerCallback;
|
||||
private Set<Long> mDeletedTimerIds = new HashSet<>();
|
||||
|
||||
public DoricTimerExtension(Looper looper, TimerCallback timerCallback) {
|
||||
mTimerHandler = new Handler(looper, this);
|
||||
mTimerCallback = timerCallback;
|
||||
}
|
||||
|
||||
public void setTimer(long timerId, long time, boolean repeat) {
|
||||
TimerInfo timerInfo = new TimerInfo();
|
||||
timerInfo.timerId = timerId;
|
||||
timerInfo.time = time;
|
||||
timerInfo.repeat = repeat;
|
||||
mTimerHandler.sendMessageDelayed(Message.obtain(mTimerHandler, MSG_TIMER, timerInfo), timerInfo.time);
|
||||
}
|
||||
|
||||
public void clearTimer(long timerId) {
|
||||
mDeletedTimerIds.add(timerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
if (msg.obj instanceof TimerInfo) {
|
||||
TimerInfo timerInfo = (TimerInfo) msg.obj;
|
||||
if (mDeletedTimerIds.contains(timerInfo.timerId)) {
|
||||
mDeletedTimerIds.remove(timerInfo.timerId);
|
||||
} else {
|
||||
mTimerCallback.callback(timerInfo.timerId);
|
||||
if (timerInfo.repeat) {
|
||||
mTimerHandler.sendMessageDelayed(Message.obtain(mTimerHandler, MSG_TIMER, timerInfo), timerInfo.time);
|
||||
} else {
|
||||
mDeletedTimerIds.remove(timerInfo.timerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void teardown() {
|
||||
mTimerHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
|
||||
private class TimerInfo {
|
||||
long timerId;
|
||||
long time;
|
||||
boolean repeat;
|
||||
}
|
||||
|
||||
public interface TimerCallback {
|
||||
void callback(long timerId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.loader;
|
||||
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
/**
|
||||
* @Description: handle "assets://asset-file-path"
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-11-23
|
||||
*/
|
||||
public class DoricAssetJSLoader implements IDoricJSLoader {
|
||||
@Override
|
||||
public boolean filter(String scheme) {
|
||||
return scheme.startsWith("assets");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<String> request(String scheme) {
|
||||
return new AsyncResult<>(DoricUtils.readAssetFile(scheme.substring("assets://".length())));
|
||||
}
|
||||
}
|