Add 'android/commons/' from commit '2f13cb5b5bc54ff5a3217c9d19b150b45363dc8f'
git-subtree-dir: android/commons
git-subtree-mainline: d1937cbcfb25c713a7c39feeed41aa86724273d8
git-subtree-split: 2f13cb5b5bc54ff5a3217c9d19b150b45363dc8f
diff --git a/android/commons/build.gradle b/android/commons/build.gradle
new file mode 100644
index 0000000..d6d07eb
--- /dev/null
+++ b/android/commons/build.gradle
@@ -0,0 +1,77 @@
+plugins {
+ id "com.github.hierynomus.license" version "0.14.0"
+}
+
+apply plugin: 'com.android.library'
+
+android {
+
+ compileSdkVersion project.compileSdkVersion
+// buildToolsVersion project.buildToolsVersion
+ resourcePrefix "weexcomm"
+
+ defaultConfig {
+ minSdkVersion project.minSdkVersion
+ targetSdkVersion project.targetSdkVersion
+ versionCode 1
+ versionName "1.0"
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+
+ debug {
+ jniDebuggable true
+ debuggable true
+
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':weex_sdk')
+ implementation "com.android.support:support-v4:${project.supportLibVersion}"
+ implementation "com.android.support:appcompat-v7:${project.supportLibVersion}"
+ // implementation project(':weex_sdk')
+ implementation 'com.squareup.picasso:picasso:2.5.2'
+ implementation 'com.facebook.fresco:fresco:0.10.0'
+ implementation 'com.taobao.android.weex_inspection:protocol:1.1.4.1'
+
+ compileOnly 'com.taobao.android:weex_analyzer:0.1.0.5'
+ compileOnly 'com.squareup.okhttp:okhttp:2.3.0'
+ compileOnly 'com.squareup.okhttp:okhttp-ws:2.3.0'
+ compileOnly "com.alibaba:fastjson:${project.fastjsonLibVersion}"
+
+ testImplementation 'junit:junit:4.12'
+ testImplementation 'org.hamcrest:hamcrest-core:1.3'
+ testImplementation 'org.javassist:javassist:3.20.0-GA'
+ testImplementation 'org.mockito:mockito-core:1.10.19'
+ testImplementation 'org.objenesis:objenesis:2.1'
+ testImplementation 'org.powermock:powermock-core:1.6.4'
+ testImplementation 'org.powermock:powermock-api-mockito:1.6.4'
+ testImplementation 'org.powermock:powermock-module-junit4-common:1.6.4'
+ testImplementation 'org.powermock:powermock-module-junit4:1.6.4'
+ testImplementation 'org.powermock:powermock-module-junit4-legacy:1.6.4'
+ testImplementation 'org.powermock:powermock-module-testng:1.6.4'
+ testImplementation 'org.robolectric:robolectric:3.0-rc3'
+}
+
+if(file('../license/LICENSE').exists()){
+ license {
+ header = file('../license/LICENSE')
+ }
+ preBuild.dependsOn licenseFormat
+}
\ No newline at end of file
diff --git a/android/commons/proguard-rules.pro b/android/commons/proguard-rules.pro
new file mode 100644
index 0000000..4acd43d
--- /dev/null
+++ b/android/commons/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/sospartan/sdks/android_sdk20130219/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/android/commons/src/androidTest/java/com/alibaba/weex/commons/ApplicationTest.java b/android/commons/src/androidTest/java/com/alibaba/weex/commons/ApplicationTest.java
new file mode 100644
index 0000000..d8cab6d
--- /dev/null
+++ b/android/commons/src/androidTest/java/com/alibaba/weex/commons/ApplicationTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
diff --git a/android/commons/src/main/AndroidManifest.xml b/android/commons/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..af18743
--- /dev/null
+++ b/android/commons/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.alibaba.weex.commons">
+
+
+
+</manifest>
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/AbstractWeexActivity.java b/android/commons/src/main/java/com/alibaba/weex/commons/AbstractWeexActivity.java
new file mode 100644
index 0000000..8854ce2
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/AbstractWeexActivity.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons;
+
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.support.annotation.CallSuper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.weex.commons.util.AssertUtil;
+import com.alibaba.weex.commons.util.ScreenUtil;
+import com.taobao.weex.IWXRenderListener;
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.common.Constants;
+import com.taobao.weex.common.WXRenderStrategy;
+import com.taobao.weex.utils.WXUtils;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by sospartan on 5/30/16.
+ */
+public abstract class AbstractWeexActivity extends AppCompatActivity implements IWXRenderListener {
+ private static final String TAG = "AbstractWeexActivity";
+
+ private ViewGroup mContainer;
+ private WXSDKInstance mInstance;
+
+ protected WXAnalyzerDelegate mWxAnalyzerDelegate;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ createWeexInstance();
+ mInstance.onActivityCreate();
+
+ mWxAnalyzerDelegate = new WXAnalyzerDelegate(this);
+ mWxAnalyzerDelegate.onCreate();
+ getWindow().setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ protected final void setContainer(ViewGroup container){
+ mContainer = container;
+ }
+
+ protected final ViewGroup getContainer(){
+ return mContainer;
+ }
+
+ protected void destoryWeexInstance(){
+ if(mInstance != null){
+ mInstance.registerRenderListener(null);
+ mInstance.destroy();
+ mInstance = null;
+ }
+ }
+
+ protected void createWeexInstance(){
+ destoryWeexInstance();
+
+ Rect outRect = new Rect();
+ getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);
+
+ mInstance = new WXSDKInstance(this);
+ mInstance.registerRenderListener(this);
+ }
+
+ protected void renderPage(String template,String source){
+ renderPage(template,source,null);
+ }
+
+ protected void renderPage(String template,String source,String jsonInitData){
+ AssertUtil.throwIfNull(mContainer,new RuntimeException("Can't render page, container is null"));
+ Map<String, Object> options = new HashMap<>();
+ options.put(WXSDKInstance.BUNDLE_URL, source);
+ // Set options.bundleDigest
+ try {
+ String banner = WXUtils.getBundleBanner(template);
+ JSONObject jsonObj = JSONObject.parseObject(banner);
+ String digest = null;
+ if (jsonObj != null) {
+ digest = jsonObj.getString(Constants.CodeCache.BANNER_DIGEST);
+ }
+ if (digest != null) {
+ options.put(Constants.CodeCache.DIGEST, digest);
+ }
+ } catch (Throwable t) {}
+ //Set options.codeCachePath
+ String path = WXEnvironment.getFilesDir(getApplicationContext());
+ path += File.separator;
+ path += Constants.CodeCache.SAVE_PATH;
+ path += File.separator;
+ options.put(Constants.CodeCache.PATH, path);
+
+ mInstance.setTrackComponent(true);
+ mInstance.render(
+ getPageName(),
+ template,
+ options,
+ jsonInitData,
+ WXRenderStrategy.APPEND_ASYNC);
+ }
+
+ protected void renderPageByURL(String url){
+ renderPageByURL(url,null);
+ }
+
+ protected void renderPageByURL(String url,String jsonInitData){
+ AssertUtil.throwIfNull(mContainer,new RuntimeException("Can't render page, container is null"));
+ Map<String, Object> options = new HashMap<>();
+ options.put(WXSDKInstance.BUNDLE_URL, url);
+ mInstance.setTrackComponent(true);
+ mInstance.renderByUrl(
+ getPageName(),
+ url,
+ options,
+ jsonInitData,
+ WXRenderStrategy.APPEND_ASYNC);
+ }
+
+ protected String getPageName(){
+ return TAG;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if(mInstance!=null){
+ mInstance.onActivityStart();
+ }
+ if(mWxAnalyzerDelegate != null){
+ mWxAnalyzerDelegate.onStart();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if(mInstance!=null){
+ mInstance.onActivityResume();
+ }
+ if(mWxAnalyzerDelegate != null){
+ mWxAnalyzerDelegate.onResume();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if(mInstance!=null){
+ mInstance.onActivityPause();
+ }
+ if(mWxAnalyzerDelegate != null){
+ mWxAnalyzerDelegate.onPause();
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if(mInstance!=null){
+ mInstance.onActivityStop();
+ }
+ if(mWxAnalyzerDelegate != null){
+ mWxAnalyzerDelegate.onStop();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if(mInstance!=null){
+ mInstance.onActivityDestroy();
+ }
+ if(mWxAnalyzerDelegate != null){
+ mWxAnalyzerDelegate.onDestroy();
+ }
+ }
+
+ @Override
+ public void onViewCreated(WXSDKInstance wxsdkInstance, View view) {
+ View wrappedView = null;
+ if(mWxAnalyzerDelegate != null){
+ wrappedView = mWxAnalyzerDelegate.onWeexViewCreated(wxsdkInstance,view);
+ }
+ if(wrappedView != null){
+ view = wrappedView;
+ }
+ if (mContainer != null) {
+ mContainer.removeAllViews();
+ mContainer.addView(view);
+ }
+ }
+
+
+
+ @Override
+ public void onRefreshSuccess(WXSDKInstance wxsdkInstance, int i, int i1) {
+
+ }
+
+ @Override
+ @CallSuper
+ public void onRenderSuccess(WXSDKInstance instance, int width, int height) {
+ if(mWxAnalyzerDelegate != null){
+ mWxAnalyzerDelegate.onWeexRenderSuccess(instance);
+ }
+ }
+
+ @Override
+ @CallSuper
+ public void onException(WXSDKInstance instance, String errCode, String msg) {
+ if(mWxAnalyzerDelegate != null){
+ mWxAnalyzerDelegate.onException(instance,errCode,msg);
+ }
+ }
+
+ @Override
+ @CallSuper
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return (mWxAnalyzerDelegate != null && mWxAnalyzerDelegate.onKeyUp(keyCode,event)) || super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (mInstance != null) {
+ mInstance.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/SimpleWeexActivity.java b/android/commons/src/main/java/com/alibaba/weex/commons/SimpleWeexActivity.java
new file mode 100644
index 0000000..91e0d1a
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/SimpleWeexActivity.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.ViewGroup;
+import com.taobao.weex.WXSDKInstance;
+
+/**
+ * Basic Weex powered Activity.
+ * Created by sospartan on 5/31/16.
+ */
+public abstract class SimpleWeexActivity extends AbstractWeexActivity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContainer((ViewGroup) findViewById(android.R.id.content));
+ }
+
+ @Override
+ public void onRenderSuccess(WXSDKInstance instance, int width, int height) {
+ super.onRenderSuccess(instance,width,height);
+ }
+
+ @Override
+ public void onException(WXSDKInstance instance, String errCode, String msg) {
+ super.onException(instance,errCode,msg);
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/WXAnalyzerDelegate.java b/android/commons/src/main/java/com/alibaba/weex/commons/WXAnalyzerDelegate.java
new file mode 100644
index 0000000..f9ad58e
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/WXAnalyzerDelegate.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.View;
+
+import com.taobao.weex.WXSDKInstance;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * Description:
+ * <p>
+ * Created by rowandjj(chuyi)<br/>
+ * Date: 2016/10/27<br/>
+ * Time: 下午7:01<br/>
+ */
+
+public final class WXAnalyzerDelegate {
+ private Object mWXAnalyzer;
+
+ private static boolean ENABLE = false;
+
+ @SuppressWarnings("unchecked")
+ public WXAnalyzerDelegate(@Nullable Context context) {
+ if(!ENABLE){
+ return;
+ }
+ if(context == null){
+ return;
+ }
+ try {
+ Class clazz = Class.forName("com.taobao.weex.analyzer.WeexDevOptions");
+ Constructor constructor = clazz.getDeclaredConstructor(Context.class);
+ mWXAnalyzer = constructor.newInstance(context);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onCreate() {
+ if (mWXAnalyzer == null) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onCreate");
+ method.invoke(mWXAnalyzer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void onStart() {
+ if (mWXAnalyzer == null) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onStart");
+ method.invoke(mWXAnalyzer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onResume() {
+ if (mWXAnalyzer == null) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onResume");
+ method.invoke(mWXAnalyzer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void onPause() {
+ if (mWXAnalyzer == null) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onPause");
+ method.invoke(mWXAnalyzer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onStop() {
+ if (mWXAnalyzer == null) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onStop");
+ method.invoke(mWXAnalyzer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onDestroy() {
+ if (mWXAnalyzer == null) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onDestroy");
+ method.invoke(mWXAnalyzer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void onWeexRenderSuccess(@Nullable WXSDKInstance instance) {
+ if (mWXAnalyzer == null || instance == null) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onWeexRenderSuccess", WXSDKInstance.class);
+ method.invoke(mWXAnalyzer, instance);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mWXAnalyzer == null) {
+ return false;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onKeyUp", int.class, KeyEvent.class);
+ return (boolean) method.invoke(mWXAnalyzer, keyCode, event);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public void onException(WXSDKInstance instance, String errCode, String msg) {
+ if (mWXAnalyzer == null) {
+ return;
+ }
+ if (TextUtils.isEmpty(errCode) && TextUtils.isEmpty(msg)) {
+ return;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onException", WXSDKInstance.class, String.class, String.class);
+ method.invoke(mWXAnalyzer, instance, errCode, msg);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public View onWeexViewCreated(WXSDKInstance instance, View view) {
+ if (mWXAnalyzer == null || instance == null || view == null) {
+ return null;
+ }
+ try {
+ Method method = mWXAnalyzer.getClass().getDeclaredMethod("onWeexViewCreated", WXSDKInstance.class, View.class);
+ View retView = (View) method.invoke(mWXAnalyzer, instance, view);
+ return retView;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return view;
+ }
+ }
+
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/BlurTool.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/BlurTool.java
new file mode 100644
index 0000000..53eb456
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/BlurTool.java
@@ -0,0 +1,325 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.graphics.Bitmap;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.taobao.weex.utils.WXLogUtils;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Created by rowandjj(chuyi)<br/>
+ */
+
+public class BlurTool {
+
+ public interface OnBlurCompleteListener {
+ /**
+ * blur complete event.(Notice:in sub thread)
+ *
+ * @param bitmap the blurred bitmap
+ * */
+ void onBlurComplete(@NonNull Bitmap bitmap);
+ }
+
+ private static ExecutorService sExecutorService = Executors.newCachedThreadPool(new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ return new Thread(r,"wx_blur_thread");
+ }
+ });
+
+ private static final String TAG = "BlurTool";
+
+ /**
+ * radius in [0,10]
+ * */
+ @NonNull
+ @SuppressWarnings("unused")
+ public static Bitmap blur(@NonNull Bitmap originalImage, int radius) {
+ long start = System.currentTimeMillis();
+ radius = Math.min(10, Math.max(0,radius));//[0,10]
+ if(radius == 0) {
+ return originalImage;
+ }
+ int width = originalImage.getWidth();
+ int height = originalImage.getHeight();
+
+ if(width <= 0 || height <= 0) {
+ return originalImage;
+ }
+
+ double sampling = calculateSampling(radius);
+ int retryTimes = 3;
+ Bitmap sampledImage = Bitmap.createScaledBitmap(originalImage,(int)(sampling*width),(int)(sampling*height),true);
+ for(int i = 0; i < retryTimes; i++) {
+ try {
+ if(radius == 0) {
+ return originalImage;
+ }
+ double s = calculateSampling(radius);
+ if(s != sampling) {
+ sampling = s;
+ sampledImage = Bitmap.createScaledBitmap(originalImage,(int)(sampling*width),(int)(sampling*height),true);
+ }
+
+ Bitmap result = stackBlur(sampledImage,radius);
+ return result;
+ }catch (Exception e) {
+ WXLogUtils.e(TAG, "thrown exception when blurred image(times = " + i + "),"+ e.getMessage());
+ radius -= 1;
+ radius = Math.max(0,radius);
+ }
+ }
+ WXLogUtils.d(TAG, "elapsed time on blurring image(radius:"+ radius + ",sampling: " + sampling + "): " + (System.currentTimeMillis() - start) + "ms");
+ return originalImage;
+ }
+
+ private static double calculateSampling(int radius){
+ double sampling;
+ if(radius <= 3) {
+ sampling = 1/(double)2;
+ }else if(radius <= 8) {
+ sampling = 1/(double)4;
+ }else {
+ sampling = 1/(double)8;
+ }
+
+ return sampling;
+ }
+
+ @SuppressWarnings("unused")
+ public static void asyncBlur(@NonNull final Bitmap originalImage, final int radius, @Nullable final OnBlurCompleteListener listener) {
+ sExecutorService.execute(new Runnable() {
+ @Override
+ public void run() {
+ if(listener != null) {
+ listener.onBlurComplete(blur(originalImage,radius));
+ }
+ }
+ });
+ }
+
+ private static Bitmap stackBlur(Bitmap sentBitmap, int radius) {
+ // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
+ Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
+
+ if (radius < 1) {
+ return (null);
+ }
+
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ int[] pix = new int[w * h];
+ bitmap.getPixels(pix, 0, w, 0, 0, w, h);
+
+ int wm = w - 1;
+ int hm = h - 1;
+ int wh = w * h;
+ int div = radius + radius + 1;
+
+ int r[] = new int[wh];
+ int g[] = new int[wh];
+ int b[] = new int[wh];
+ int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
+ int vmin[] = new int[Math.max(w, h)];
+
+ int divsum = (div + 1) >> 1;
+ divsum *= divsum;
+ int dv[] = new int[256 * divsum];
+ for (i = 0; i < 256 * divsum; i++) {
+ dv[i] = (i / divsum);
+ }
+
+ yw = yi = 0;
+
+ int[][] stack = new int[div][3];
+ int stackpointer;
+ int stackstart;
+ int[] sir;
+ int rbs;
+ int r1 = radius + 1;
+ int routsum, goutsum, boutsum;
+ int rinsum, ginsum, binsum;
+
+ for (y = 0; y < h; y++) {
+ rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
+ for (i = -radius; i <= radius; i++) {
+ p = pix[yi + Math.min(wm, Math.max(i, 0))];
+ sir = stack[i + radius];
+ sir[0] = (p & 0xff0000) >> 16;
+ sir[1] = (p & 0x00ff00) >> 8;
+ sir[2] = (p & 0x0000ff);
+ rbs = r1 - Math.abs(i);
+ rsum += sir[0] * rbs;
+ gsum += sir[1] * rbs;
+ bsum += sir[2] * rbs;
+ if (i > 0) {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ } else {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ }
+ }
+ stackpointer = radius;
+
+ for (x = 0; x < w; x++) {
+
+ r[yi] = dv[rsum];
+ g[yi] = dv[gsum];
+ b[yi] = dv[bsum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+
+ if (y == 0) {
+ vmin[x] = Math.min(x + radius + 1, wm);
+ }
+ p = pix[yw + vmin[x]];
+
+ sir[0] = (p & 0xff0000) >> 16;
+ sir[1] = (p & 0x00ff00) >> 8;
+ sir[2] = (p & 0x0000ff);
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[(stackpointer) % div];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+
+ yi++;
+ }
+ yw += w;
+ }
+ for (x = 0; x < w; x++) {
+ rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
+ yp = -radius * w;
+ for (i = -radius; i <= radius; i++) {
+ yi = Math.max(0, yp) + x;
+
+ sir = stack[i + radius];
+
+ sir[0] = r[yi];
+ sir[1] = g[yi];
+ sir[2] = b[yi];
+
+ rbs = r1 - Math.abs(i);
+
+ rsum += r[yi] * rbs;
+ gsum += g[yi] * rbs;
+ bsum += b[yi] * rbs;
+
+ if (i > 0) {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ } else {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ }
+
+ if (i < hm) {
+ yp += w;
+ }
+ }
+ yi = x;
+ stackpointer = radius;
+ for (y = 0; y < h; y++) {
+ // Preserve alpha channel: ( 0xff000000 & pix[yi] )
+ pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+
+ if (x == 0) {
+ vmin[y] = Math.min(y + r1, hm) * w;
+ }
+ p = x + vmin[y];
+
+ sir[0] = r[p];
+ sir[1] = g[p];
+ sir[2] = b[p];
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[stackpointer];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+
+ yi += w;
+ }
+ }
+
+ bitmap.setPixels(pix, 0, w, 0, 0, w, h);
+
+ return (bitmap);
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/BlurTransformation.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/BlurTransformation.java
new file mode 100644
index 0000000..b530b92
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/BlurTransformation.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.graphics.Bitmap;
+
+import com.squareup.picasso.Transformation;
+
+public class BlurTransformation implements Transformation {
+
+ private int mRadius;
+
+ public BlurTransformation(int radius) {
+ mRadius = radius;
+ }
+
+ @Override public Bitmap transform(Bitmap source) {
+ if(mRadius <= 0) {
+ return source;
+ }
+ Bitmap bitmap;
+ try {
+ bitmap = BlurTool.blur(source, mRadius);
+ }catch (Exception e){
+ bitmap = source;
+ }
+ if(bitmap != source) {
+ source.recycle();
+ }
+ return bitmap;
+ }
+
+ @Override public String key() {
+ return "BlurTransformation(radius=" + mRadius + ")";
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/DefaultWebSocketAdapter.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/DefaultWebSocketAdapter.java
new file mode 100644
index 0000000..22810dc
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/DefaultWebSocketAdapter.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.support.annotation.Nullable;
+
+import com.alibaba.weex.commons.util.WSEventReporter;
+import com.squareup.okhttp.Headers;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+import com.squareup.okhttp.ws.WebSocket;
+import com.squareup.okhttp.ws.WebSocketCall;
+import com.squareup.okhttp.ws.WebSocketListener;
+import com.taobao.weex.appfram.websocket.IWebSocketAdapter;
+import com.taobao.weex.appfram.websocket.WebSocketCloseCodes;
+import com.taobao.weex.http.Status;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import okio.Buffer;
+import okio.BufferedSource;
+
+/**
+ * Created by moxun on 16/12/27.
+ */
+
+public class DefaultWebSocketAdapter implements IWebSocketAdapter {
+
+ private WebSocket ws;
+ private EventListener eventListener;
+ private WSEventReporter wsEventReporter;
+
+ @Override
+ public void connect(String url, @Nullable final String protocol, EventListener listener) {
+ this.eventListener = listener;
+ this.wsEventReporter = WSEventReporter.newInstance();
+ OkHttpClient okHttpClient = new OkHttpClient();
+
+ Request.Builder builder = new Request.Builder();
+
+ if (protocol != null) {
+ builder.addHeader(HEADER_SEC_WEBSOCKET_PROTOCOL, protocol);
+ }
+
+ builder.url(url);
+ wsEventReporter.created(url);
+
+ Request wsRequest = builder.build();
+ WebSocketCall webSocketCall = WebSocketCall.create(okHttpClient, wsRequest);
+
+ try {
+ Field field = WebSocketCall.class.getDeclaredField("request");
+ field.setAccessible(true);
+ Request realRequest = (Request) field.get(webSocketCall);
+ Headers wsHeaders = realRequest.headers();
+ Map<String, String> headers = new HashMap<>();
+ for (String name : wsHeaders.names()) {
+ headers.put(name, wsHeaders.values(name).toString());
+ }
+ wsEventReporter.willSendHandshakeRequest(headers, null);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ webSocketCall.enqueue(new WebSocketListener() {
+ @Override
+ public void onOpen(WebSocket webSocket, Request request, Response response) throws IOException {
+ ws = webSocket;
+ eventListener.onOpen();
+ Headers wsHeaders = response.headers();
+ Map<String, String> headers = new HashMap<>();
+ for (String name : wsHeaders.names()) {
+ headers.put(name, wsHeaders.values(name).toString());
+ }
+ wsEventReporter.handshakeResponseReceived(response.code(),
+ Status.getStatusText(String.valueOf(response.code())),
+ headers);
+ }
+
+ @Override
+ public void onMessage(BufferedSource payload, WebSocket.PayloadType type) throws IOException {
+ if (type == WebSocket.PayloadType.BINARY) {
+ wsEventReporter.frameReceived(payload.readByteArray());
+ } else {
+ String message = payload.readUtf8();
+ eventListener.onMessage(message);
+ wsEventReporter.frameReceived(message);
+ }
+ payload.close();
+ }
+
+ @Override
+ public void onPong(Buffer payload) {
+
+ }
+
+ @Override
+ public void onClose(int code, String reason) {
+ eventListener.onClose(code, reason, true);
+ wsEventReporter.closed();
+ }
+
+ @Override
+ public void onFailure(IOException e) {
+ e.printStackTrace();
+ if (e instanceof EOFException) {
+ eventListener.onClose(WebSocketCloseCodes.CLOSE_NORMAL.getCode(), WebSocketCloseCodes.CLOSE_NORMAL.name(), true);
+ wsEventReporter.closed();
+ } else {
+ eventListener.onError(e.getMessage());
+ wsEventReporter.frameError(e.getMessage());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void send(String data) {
+ if (ws != null) {
+ try {
+ Buffer buffer = new Buffer().writeUtf8(data);
+ ws.sendMessage(WebSocket.PayloadType.TEXT, buffer.buffer());
+ buffer.flush();
+ buffer.close();
+
+ wsEventReporter.frameSent(data);
+ } catch (Exception e) {
+ e.printStackTrace();
+ reportError(e.getMessage());
+ wsEventReporter.frameError(e.getMessage());
+ }
+ } else {
+ reportError("WebSocket is not ready");
+ }
+ }
+
+ @Override
+ public void close(int code, String reason) {
+ if (ws != null) {
+ try {
+ ws.close(code, reason);
+ } catch (Exception e) {
+ e.printStackTrace();
+ reportError(e.getMessage());
+ }
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if (ws != null) {
+ try {
+ ws.close(WebSocketCloseCodes.CLOSE_GOING_AWAY.getCode(), WebSocketCloseCodes.CLOSE_GOING_AWAY.name());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void reportError(String message) {
+ if (eventListener != null) {
+ eventListener.onError(message);
+ }
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/DefaultWebSocketAdapterFactory.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/DefaultWebSocketAdapterFactory.java
new file mode 100644
index 0000000..a2cd4ec
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/DefaultWebSocketAdapterFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import com.taobao.weex.appfram.websocket.IWebSocketAdapter;
+import com.taobao.weex.appfram.websocket.IWebSocketAdapterFactory;
+
+/**
+ * Created by moxun on 16/12/28.
+ */
+
+public class DefaultWebSocketAdapterFactory implements IWebSocketAdapterFactory {
+ @Override
+ public IWebSocketAdapter createWebSocketAdapter() {
+ return new DefaultWebSocketAdapter();
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageAdapter.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageAdapter.java
new file mode 100644
index 0000000..bc4ab42
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageAdapter.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.graphics.Color;
+import android.graphics.drawable.Animatable;
+import android.net.Uri;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.ImageView;
+
+import com.facebook.common.executors.UiThreadImmediateExecutorService;
+import com.facebook.common.internal.Preconditions;
+import com.facebook.common.logging.FLog;
+import com.facebook.common.references.CloseableReference;
+import com.facebook.datasource.BaseDataSubscriber;
+import com.facebook.datasource.DataSource;
+import com.facebook.datasource.DataSubscriber;
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.facebook.drawee.controller.BaseControllerListener;
+import com.facebook.drawee.controller.ControllerListener;
+import com.facebook.drawee.interfaces.DraweeController;
+import com.facebook.drawee.view.DraweeView;
+import com.facebook.imagepipeline.common.ImageDecodeOptions;
+import com.facebook.imagepipeline.core.ImagePipeline;
+import com.facebook.imagepipeline.image.CloseableImage;
+import com.facebook.imagepipeline.image.CloseableStaticBitmap;
+import com.facebook.imagepipeline.image.ImageInfo;
+import com.facebook.imagepipeline.image.QualityInfo;
+import com.facebook.imagepipeline.request.ImageRequest;
+import com.facebook.imagepipeline.request.ImageRequestBuilder;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.adapter.IWXImgLoaderAdapter;
+import com.taobao.weex.common.WXImageStrategy;
+import com.taobao.weex.dom.WXImageQuality;
+
+public class FrescoImageAdapter implements IWXImgLoaderAdapter {
+
+ public FrescoImageAdapter() {
+ }
+
+ @Override
+ public void setImage(final String url, final ImageView view,
+ WXImageQuality quality, WXImageStrategy strategy) {
+
+ WXSDKManager.getInstance().postOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ if (view == null || view.getLayoutParams() == null) {
+ return;
+ }
+ if (TextUtils.isEmpty(url)) {
+ view.setImageBitmap(null);
+ return;
+ }
+ String temp = url;
+ if (url.startsWith("//")) {
+ temp = "http:" + url;
+ }
+ if (view.getLayoutParams().width <= 0 || view.getLayoutParams().height <= 0) {
+ return;
+ }
+
+ Uri uri = Uri.parse(temp);
+
+ ImageDecodeOptions decodeOptions = ImageDecodeOptions.newBuilder()
+ .setBackgroundColor(Color.GREEN)
+ .build();
+
+ ImageRequest request = ImageRequestBuilder
+ .newBuilderWithSource(uri)
+ .setImageDecodeOptions(decodeOptions)
+ .setAutoRotateEnabled(true)
+ .setLocalThumbnailPreviewsEnabled(true)
+ .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)
+ .setProgressiveRenderingEnabled(false)
+ .build();
+
+ if(view instanceof DraweeView){
+ Log.d("FrescoImageAdapter","load: "+url);
+ ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
+ @Override
+ public void onFinalImageSet(
+ String id,
+ @Nullable ImageInfo imageInfo,
+ @Nullable Animatable anim) {
+ if (imageInfo == null) {
+ return;
+ }
+ QualityInfo qualityInfo = imageInfo.getQualityInfo();
+ FLog.d("Final image received! " +
+ "Size %d x %d",
+ "Quality level %d, good enough: %s, full quality: %s",
+ imageInfo.getWidth(),
+ imageInfo.getHeight(),
+ qualityInfo.getQuality(),
+ qualityInfo.isOfGoodEnoughQuality(),
+ qualityInfo.isOfFullQuality());
+ }
+
+ @Override
+ public void onIntermediateImageSet(String id, @Nullable ImageInfo imageInfo) {
+ FLog.d("","Intermediate image received");
+ }
+
+ @Override
+ public void onFailure(String id, Throwable throwable) {
+ FLog.e(getClass(), throwable, "Error loading %s", id);
+ }
+ };
+ DraweeController controller = Fresco.newDraweeControllerBuilder()
+ .setAutoPlayAnimations(true)
+ .setControllerListener(controllerListener)
+ .setUri(uri)
+ .setImageRequest(request)
+ .build();
+ ((DraweeView)view).setController(controller);
+
+ }else {
+ ImagePipeline imagePipeline = Fresco.getImagePipeline();
+ DataSource<CloseableReference<CloseableImage>>
+ dataSource = imagePipeline.fetchDecodedImage(request, new Object());
+ DataSubscriber dataSubscriber =
+ new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
+ @Override
+ public void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
+
+ CloseableReference<CloseableImage> imageReference = dataSource.getResult();
+ if (imageReference != null) {
+ try {
+ // do something with the image
+ Preconditions.checkState(CloseableReference.isValid(imageReference));
+ CloseableImage closeableImage = imageReference.get();
+ if (closeableImage instanceof CloseableStaticBitmap) {
+ CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) closeableImage;
+ view.setImageBitmap(closeableStaticBitmap.getUnderlyingBitmap());
+ // boolean hasResult = null != closeableStaticBitmap.getUnderlyingBitmap();
+ } else {
+ throw new UnsupportedOperationException("Unrecognized image class: " + closeableImage);
+ }
+ } finally {
+ imageReference.close();
+ }
+ }
+ }
+
+ @Override
+ public void onFailureImpl(DataSource dataSource) {
+ }
+ };
+
+ dataSource.subscribe(dataSubscriber, UiThreadImmediateExecutorService.getInstance());
+ }
+ }
+ }, 0);
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageComponent.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageComponent.java
new file mode 100644
index 0000000..56e9a25
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageComponent.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.widget.ImageView;
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.ui.action.BasicComponentData;
+import com.taobao.weex.ui.component.WXImage;
+import com.taobao.weex.ui.component.WXVContainer;
+
+/**
+ * Created by sospartan on 8/19/16.
+ */
+public class FrescoImageComponent extends WXImage {
+
+ public FrescoImageComponent(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) {
+ super(instance, parent, basicComponentData);
+ }
+
+ @Override
+ protected ImageView initComponentHostView(@NonNull Context context) {
+ FrescoImageView view = new FrescoImageView(context);
+ view.setScaleType(ImageView.ScaleType.FIT_XY);
+
+ return view;
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageView.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageView.java
new file mode 100644
index 0000000..9227a90
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/FrescoImageView.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import com.facebook.drawee.view.DraweeView;
+import com.facebook.drawee.view.SimpleDraweeView;
+import com.taobao.weex.ui.view.border.BorderDrawable;
+import com.taobao.weex.ui.view.gesture.WXGesture;
+import com.taobao.weex.ui.view.gesture.WXGestureObservable;
+import com.taobao.weex.utils.WXViewUtils;
+
+/**
+ * Created by sospartan on 8/19/16.
+ */
+public class FrescoImageView extends SimpleDraweeView implements WXGestureObservable {
+ public FrescoImageView(Context context) {
+ super(context);
+ }
+
+ public FrescoImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public FrescoImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public FrescoImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ private WXGesture wxGesture;
+
+ @Override
+ public void registerGestureListener(WXGesture wxGesture) {
+ this.wxGesture = wxGesture;
+ }
+
+ @Override
+ public WXGesture getGestureListener() {
+ return wxGesture;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean result = super.onTouchEvent(event);
+ if (wxGesture != null) {
+ result |= wxGesture.onTouch(this, event);
+ }
+ return result;
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/ImageAdapter.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/ImageAdapter.java
new file mode 100644
index 0000000..77dc4fc
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/ImageAdapter.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.net.Uri;
+import android.os.Looper;
+import android.text.TextUtils;
+import android.widget.ImageView;
+
+import com.squareup.picasso.Callback;
+import com.squareup.picasso.Picasso;
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.adapter.IWXImgLoaderAdapter;
+import com.taobao.weex.common.WXImageStrategy;
+import com.taobao.weex.dom.WXImageQuality;
+import com.taobao.weex.ui.IFComponentHolder;
+
+public class ImageAdapter implements IWXImgLoaderAdapter {
+
+ public ImageAdapter() {
+ }
+
+ @Override
+ public void setImage(final String url, final ImageView view,
+ WXImageQuality quality, final WXImageStrategy strategy) {
+ Runnable runnable = new Runnable() {
+
+ @Override
+ public void run() {
+ if(view==null||view.getLayoutParams()==null){
+ return;
+ }
+ if (TextUtils.isEmpty(url)) {
+ view.setImageBitmap(null);
+ return;
+ }
+ if (null != strategy){
+ recordImgLoadAction(strategy.instanceId);
+ }
+
+ String temp = url;
+ if (url.startsWith("//")) {
+ temp = "http:" + url;
+ }
+
+ if(!TextUtils.isEmpty(strategy.placeHolder)){
+ Picasso.Builder builder=new Picasso.Builder(WXEnvironment.getApplication());
+ Picasso picasso=builder.build();
+ picasso.load(Uri.parse(strategy.placeHolder)).into(view);
+
+ view.setTag(strategy.placeHolder.hashCode(),picasso);
+ }
+
+ Picasso.with(WXEnvironment.getApplication())
+ .load(temp)
+ .transform(new BlurTransformation(strategy.blurRadius))
+ .into(view, new Callback() {
+ @Override
+ public void onSuccess() {
+ if(strategy.getImageListener()!=null){
+ strategy.getImageListener().onImageFinish(url,view,true,null);
+ }
+ recordImgLoadResult(strategy.instanceId,true,null);
+
+ if(!TextUtils.isEmpty(strategy.placeHolder)){
+ ((Picasso) view.getTag(strategy.placeHolder.hashCode())).cancelRequest(view);
+ }
+ }
+
+ @Override
+ public void onError() {
+ if(strategy.getImageListener()!=null){
+ strategy.getImageListener().onImageFinish(url,view,false,null);
+ }
+ recordImgLoadResult(strategy.instanceId,false,null);
+ }
+ });
+ }
+ };
+ if(Thread.currentThread() == Looper.getMainLooper().getThread()){
+ runnable.run();
+ }else {
+ WXSDKManager.getInstance().postOnUiThread(runnable, 0);
+ }
+ }
+ private void recordImgLoadAction(String instanceId){
+ WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
+ if (null == instance || instance.isDestroy()){
+ return;
+ }
+ instance.getApmForInstance().actionLoadImg();
+ }
+
+ private void recordImgLoadResult(String instanceId,boolean succeed,String errorCode){
+ WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
+ if (null == instance || instance.isDestroy()){
+ return;
+ }
+ instance.getApmForInstance().actionLoadImgResult(succeed,errorCode);
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/JSExceptionAdapter.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/JSExceptionAdapter.java
new file mode 100644
index 0000000..3c6c2ff
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/JSExceptionAdapter.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.adapter.IWXJSExceptionAdapter;
+import com.taobao.weex.common.WXJSExceptionInfo;
+import com.taobao.weex.utils.WXLogUtils;
+
+/**
+ */
+
+public class JSExceptionAdapter implements IWXJSExceptionAdapter {
+
+ @Override
+ public void onJSException(WXJSExceptionInfo exception) {
+ if (exception != null && WXEnvironment.isApkDebugable()) {
+ WXLogUtils.d(exception.toString());
+ }
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/PicassoBasedDrawableLoader.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/PicassoBasedDrawableLoader.java
new file mode 100644
index 0000000..a642dc7
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/PicassoBasedDrawableLoader.java
@@ -0,0 +1,108 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.adapter;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.view.Gravity;
+
+import com.squareup.picasso.Picasso;
+import com.squareup.picasso.Target;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.adapter.DrawableStrategy;
+import com.taobao.weex.adapter.IDrawableLoader;
+
+public class PicassoBasedDrawableLoader implements IDrawableLoader {
+
+ private Context mContext;
+
+ public PicassoBasedDrawableLoader(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void setDrawable(final String url,
+ final DrawableTarget drawableTarget,
+ final DrawableStrategy drawableStrategy) {
+ WXSDKManager.getInstance().postOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String temp = url;
+ if (url.startsWith("//")) {
+ temp = "http:" + url;
+ }
+
+ /** This is a hack for picasso, as Picasso hold weakReference to Target.
+ * http://stackoverflow.com/questions/24180805/onbitmaploaded-of-target-object-not-called-on-first-load
+ */
+ class PlaceHolderDrawableTarget extends Drawable implements Target {
+
+ @Override
+ public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
+ bitmapDrawable.setGravity(Gravity.FILL);
+ drawableTarget.setDrawable(bitmapDrawable, true);
+ }
+
+ @Override
+ public void onBitmapFailed(Drawable errorDrawable) {
+
+ }
+
+ @Override
+ public void onPrepareLoad(Drawable placeHolderDrawable) {
+ drawableTarget.setDrawable(this, true);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.UNKNOWN;
+ }
+ }
+ Picasso.
+ with(mContext).
+ load(temp).
+ resize(drawableStrategy.width, drawableStrategy.height).
+ onlyScaleDown().
+ into(new PlaceHolderDrawableTarget());
+ }
+ }, 0);
+
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/util/AssertUtil.java b/android/commons/src/main/java/com/alibaba/weex/commons/util/AssertUtil.java
new file mode 100644
index 0000000..07ec3b9
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/util/AssertUtil.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.util;
+
+/**
+ * Created by sospartan on 5/31/16.
+ */
+public class AssertUtil {
+ public static<T extends Exception> void throwIfNull(Object object,T e) throws T {
+ if(object == null){
+ throw e;
+ }
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/util/RequestIdGenerator.java b/android/commons/src/main/java/com/alibaba/weex/commons/util/RequestIdGenerator.java
new file mode 100644
index 0000000..8f4f169
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/util/RequestIdGenerator.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.util;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Created by moxun on 17/4/20.
+ */
+
+public class RequestIdGenerator {
+ private static final AtomicInteger sIdGenerator = new AtomicInteger(0);
+
+ public static int nextRequestId() {
+ return sIdGenerator.getAndIncrement();
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/util/ScreenUtil.java b/android/commons/src/main/java/com/alibaba/weex/commons/util/ScreenUtil.java
new file mode 100644
index 0000000..e2caed3
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/util/ScreenUtil.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.util;
+
+import android.content.res.TypedArray;
+import android.graphics.Point;
+import android.os.Build;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class ScreenUtil {
+ private static final String TAG = "WXTBUtil";
+
+ private static boolean isSupportSmartBar = false;
+
+ static {
+ isSupportSmartBar = isSupportSmartBar();
+ }
+ public static int getDisplayWidth(AppCompatActivity activity){
+ int width=0;
+ if (activity != null && activity.getWindowManager() != null && activity.getWindowManager().getDefaultDisplay() != null) {
+ Point point=new Point();
+ activity.getWindowManager().getDefaultDisplay().getSize(point);
+ width = point.x;
+ }
+ return width;
+ }
+
+ public static int getDisplayHeight(AppCompatActivity activity) {
+ int height = 0;
+ if (activity != null && activity.getWindowManager() != null && activity.getWindowManager().getDefaultDisplay() != null) {
+ Point point=new Point();
+ activity.getWindowManager().getDefaultDisplay().getSize(point);
+ height=point.y;
+ }
+
+ Log.e(TAG, "isSupportSmartBar:" + isSupportSmartBar);
+
+ if (isSupportSmartBar) {
+ int smartBarHeight = getSmartBarHeight(activity);
+ Log.e(TAG, "smartBarHeight:" + smartBarHeight);
+ height -= smartBarHeight;
+ }
+
+ if (activity.getSupportActionBar() != null) {
+ int actionbar= activity.getSupportActionBar().getHeight();
+ if(actionbar==0){
+ TypedArray actionbarSizeTypedArray=activity.obtainStyledAttributes(new int[]{android.R.attr.actionBarSize});
+ actionbar= (int) actionbarSizeTypedArray.getDimension(0,0);
+ }
+ Log.d(TAG, "actionbar:" + actionbar);
+ height -= actionbar;
+ }
+
+ int status = getStatusBarHeight(activity);
+ Log.d(TAG, "status:" + status);
+
+ height -= status;
+
+ Log.d(TAG,"height:"+height);
+ return height;
+ }
+
+ private static int getStatusBarHeight(AppCompatActivity activity) {
+ Class<?> c;
+ Object obj;
+ Field field;
+ int x;
+ int statusBarHeight = 0;
+ try {
+ c = Class.forName("com.android.internal.R$dimen");
+ obj = c.newInstance();
+ field = c.getField("status_bar_height");
+ x = Integer.parseInt(field.get(obj).toString());
+ statusBarHeight = activity.getResources().getDimensionPixelSize(x);
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ return statusBarHeight;
+ }
+
+ private static int getSmartBarHeight(AppCompatActivity activity) {
+ ActionBar actionbar = activity.getSupportActionBar();
+ if (actionbar != null)
+ try {
+ Class c = Class.forName("com.android.internal.R$dimen");
+ Object obj = c.newInstance();
+ Field field = c.getField("mz_action_button_min_height");
+ int height = Integer.parseInt(field.get(obj).toString());
+ return activity.getResources().getDimensionPixelSize(height);
+ } catch (Exception e) {
+ e.printStackTrace();
+ actionbar.getHeight();
+ }
+ return 0;
+ }
+
+ private static boolean isSupportSmartBar() {
+ try {
+ final Method method = Build.class.getMethod("hasSmartBar");
+ return method != null;
+ } catch (final Exception e) {
+ return false;
+ }
+ }
+}
diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/util/WSEventReporter.java b/android/commons/src/main/java/com/alibaba/weex/commons/util/WSEventReporter.java
new file mode 100644
index 0000000..aba09c1
--- /dev/null
+++ b/android/commons/src/main/java/com/alibaba/weex/commons/util/WSEventReporter.java
@@ -0,0 +1,210 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex.commons.util;
+
+import android.support.annotation.Nullable;
+import android.util.Pair;
+
+import com.taobao.weex.devtools.inspector.network.NetworkEventReporter;
+import com.taobao.weex.devtools.inspector.network.NetworkEventReporterManager;
+import com.taobao.weex.devtools.inspector.network.SimpleBinaryInspectorWebSocketFrame;
+import com.taobao.weex.devtools.inspector.network.SimpleTextInspectorWebSocketFrame;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by moxun on 17/4/20.
+ */
+
+public class WSEventReporter {
+
+ private String requestId;
+ private NetworkEventReporter reporter;
+ private WSRequest request;
+
+ public static WSEventReporter newInstance() {
+ return new WSEventReporter();
+ }
+
+ private WSEventReporter() {
+ requestId = String.valueOf(RequestIdGenerator.nextRequestId());
+ reporter = NetworkEventReporterManager.get();
+ }
+
+ public void created(String url) {
+ if (reporter != null) {
+ reporter.webSocketCreated(requestId, url);
+ }
+ }
+
+ public void closed() {
+ if (reporter != null) {
+ reporter.webSocketClosed(requestId);
+ }
+ }
+
+ public void willSendHandshakeRequest(Map<String, String> headers, @Nullable String friendlyName) {
+ if (reporter != null) {
+ request = new WSRequest(requestId, friendlyName, headers);
+ reporter.webSocketWillSendHandshakeRequest(request);
+ }
+ }
+
+ public void handshakeResponseReceived(int code, String phrase, Map<String, String> responseHeaders) {
+ if (reporter != null) {
+ reporter.webSocketHandshakeResponseReceived(new WSResponse(requestId, code, phrase, responseHeaders, request));
+ }
+ }
+
+ public void frameSent(String frame) {
+ if (reporter != null) {
+ reporter.webSocketFrameSent(new SimpleTextInspectorWebSocketFrame(requestId, frame));
+ }
+ }
+
+ public void frameSent(byte[] frame) {
+ if (reporter != null) {
+ reporter.webSocketFrameSent(new SimpleBinaryInspectorWebSocketFrame(requestId, frame));
+ }
+ }
+
+ public void frameReceived(String frame) {
+ if (reporter != null) {
+ reporter.webSocketFrameReceived(new SimpleTextInspectorWebSocketFrame(requestId, frame));
+ }
+ }
+
+ public void frameReceived(byte[] frame) {
+ if (reporter != null) {
+ reporter.webSocketFrameReceived(new SimpleBinaryInspectorWebSocketFrame(requestId, frame));
+ }
+ }
+
+ public void frameError(String msg) {
+ if (reporter != null) {
+ reporter.webSocketFrameError(requestId, msg);
+ }
+ }
+
+ private static class WSRequest extends WSHeaderCommon implements NetworkEventReporter.InspectorWebSocketRequest {
+
+ private String id;
+ private String name;
+
+ public WSRequest(String id, String name, Map<String, String> headers) {
+ attachHeaders(headers);
+ this.id = id;
+ this.name = name;
+ if (this.name == null) {
+ this.name = "WS Connection " + id;
+ }
+ }
+
+ @Override
+ public String id() {
+ return id;
+ }
+
+ @Override
+ public String friendlyName() {
+ return name;
+ }
+ }
+
+ private static class WSResponse extends WSHeaderCommon implements NetworkEventReporter.InspectorWebSocketResponse {
+
+ private String id;
+ private int code;
+ private String phrase;
+ private WSHeaderCommon headers;
+
+ public WSResponse(String id, int code, String phrase, Map<String, String> responseHeaders, WSHeaderCommon headers) {
+ attachHeaders(responseHeaders);
+ this.id = id;
+ this.code = code;
+ this.phrase = phrase;
+ this.headers = headers;
+ }
+
+ @Override
+ public String requestId() {
+ return id;
+ }
+
+ @Override
+ public int statusCode() {
+ return code;
+ }
+
+ @Override
+ public String reasonPhrase() {
+ return phrase;
+ }
+
+ @Nullable
+ @Override
+ public NetworkEventReporter.InspectorHeaders requestHeaders() {
+ return headers;
+ }
+ }
+
+ private static class WSHeaderCommon implements NetworkEventReporter.InspectorHeaders {
+
+ private List<Pair<String, String>> headerList = new ArrayList<>();
+
+ public void attachHeaders(Map<String, String> headers) {
+ for (Map.Entry<String, String> entry : headers.entrySet()) {
+ headerList.add(new Pair<>(entry.getKey(), entry.getValue()));
+ }
+ }
+
+ public void addHeader(String key, String value) {
+ headerList.add(new Pair<>(key, value));
+ }
+
+
+ @Override
+ public int headerCount() {
+ return headerList.size();
+ }
+
+ @Override
+ public String headerName(int index) {
+ return headerList.get(index).first;
+ }
+
+ @Override
+ public String headerValue(int index) {
+ return headerList.get(index).second;
+ }
+
+ @Nullable
+ @Override
+ public String firstHeaderValue(String name) {
+ for (Pair<String, String> pair : headerList) {
+ if (pair.first.equals(name)) {
+ return pair.second;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/android/commons/src/main/res/values/strings.xml b/android/commons/src/main/res/values/strings.xml
new file mode 100644
index 0000000..be8deae
--- /dev/null
+++ b/android/commons/src/main/res/values/strings.xml
@@ -0,0 +1,23 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<resources>
+ <string name="app_name">My Module</string>
+</resources>