Giter VIP home page Giter VIP logo

appcan-android's Introduction

appcan-android

appcan-android引擎

参考 http://newdocx.appcan.cn/

QQ交流群:173758265

生成引擎包步骤:

  1. 新建Android Studio工程Engine_AppCan

  2. clone 引擎代码到工程Engine_AppCan

    git clone https://github.com/AppCanOpenSource/appcan-android.git
  3. 编辑工程根目录下的settings.gradle,在下面添加一行:

    include ':appcan-android:Engine'
  4. 按需修改引擎代码

  5. 编辑appcan-android/en_baseEngineProject/androidEngine.xml里面的description信息,其他的不要改动

  6. 在Android Studio自带的Terminal输入

    gradle buildEngine
  7. 编译完成后,生成的引擎包在appcan-android/Engine/build/outputs/engine目录下

目录结构

├── Engine 
│   ├── Engine.iml
│   ├── build
│   ├── build.gradle
│   ├── libs  公用lib
│   ├── proguard.pro  混淆文件
│   ├── project.properties
│   └── src
├── LICENSE
├── README.md
├── appcan-android.iml
├── en_baseEngineProject
│   ├── WebkitCorePalm 
│   └── androidEngine.xml
└── gradle-plugin
    └── appcan-build-engine.jar

Engine:引擎工程,该工程的最终作用就是生成引擎的jar

当有除了java代码之外的改动,如添加图片资源,添加或修改布局文件,都需要同步改动到WebkitCorePalm(重要)

en_baseEngineProject/WebkitCorePalm:最终打包使用的工程,除了上面说的需要从Engine工程同步的内容,其他信息不要改动,

Engine/build:目录结构如下

├── appcan
│   ├── crosswalk
│   ├── x5
│   └── system
├── generated
├── intermediates
├── outputs
│   ├── engine
│   ├── jar
│   ├── aar 
│   ├── logs
│   └── mapping
└── tmp

appcan:生成引擎时产生的临时文件

outputs/engine:引擎输出目录

outputs/jar:Enginemoudle编译出来的jar,以-un-proguard.jar结尾的为未混淆的jar,其他为混淆过的jar

outputs/aar:Enginemodule生成的aar

关于混淆

  • 混淆文件为:appcan-android/Engine/proguard.pro
  • 混淆只用于混淆Engine中的java文件 排除混淆

排除混淆

  • 提供给JS调用的接口,请在方法添加@AppCanAPI注解,混淆时会排除
  • 提供给插件调用或不希望被混淆的,请添加@Keep注解,混淆时会排除

AppCan Gradle插件

一般情况下生成引擎只需要调用gradle buildEngine 就可以生成所有的引擎包,如果有其他需要可以调用其他的task。目前提供的task有:

  • build{Flavor}Engine:生成对应flavor的引擎

    如输出crosswalk引擎

    gradle buildCrosswalkEngine

    输出所有flavor的引擎

    gradle buildEngine
  • build{Flavor}JarTemp:生成对应flavor的jar,不进行混淆

    如输出crosswalk引擎的jar

    gradle buildCrosswalkJarTemp

    如果要输出所有flavor的jar

    gradle buildJarTemp
  • build{Flavor}Jar:生成对应flavor的jar,并且进行混淆

    如输出混淆过的crosswalk引擎jar

    gradle buildCrosswalkJar

    如果要输出所有flavor的jar

    gradle buildJar 
  • build{Flavor}Aar:生成对应flavor的aar

    如输出混淆过的System引擎aar

    gradle buildSystemAar

    如果要输出所有flavor的aar

    gradle buildAar 

    说明:生成aar需要将Engine目录下的build.gradle文件中的

    apply plugin: 'com.android.application'

    替换成

    apply plugin: 'com.android.library'

    并注释掉

    applicationId 'org.zywx.wbpalmstar.widgetone.uex'

已经适配到AndroidStudio3.5.0开发环境

后续更高的gradle版本,升级原理相同,本文档更新不及时的话,开发者可以自行更新工程配置。但是gradle版本更新过高可能会导致引擎出包脚本使用的gradle插件不兼容,需要等待后续进行适配。目前经过完整测试的是可以适配到3.5.0。

在3.5.0遇到Gradle插件和脚本运行出错,是因为工程中的AppCanGradle插件未做高版本的适配。有两种方式解决:

1. 降级gradle

目前,本工程的默认配置为适配AS3.5.0,Gradle版本为5.4.1,AndroidGradle构建插件版本为3.5.0。如果开发者没有升级AndroidStudio,按照以下操作降级:

  • 修改Engine/gradle/wrapper/gradle-wrapper.properties,其中版本改为4.1;

  • 修改build.gradle中的classpath 'org.appcan.gradle.plugins:appcan-gradle-plugin:2.3.1',其中2.3.1修改为2.2.4。

  • 经过以上操作后,理论上可以编译通过。不过还是建议升级AS。

2. 依赖新版AppCanGradle插件

  1. 修改Engine/gradle/wrapper/gradle-wrapper.properties,其中版本改为5.4.1;

  2. 修改Engine/build.gradle文件中。其中,repositories增加一个github的maven库,dependencies中将原来的依赖本地的gradle插件改为依赖线上的,版本目前是2.4.0,相关仓库见文档后面。修改部分参考下面:

buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://raw.githubusercontent.com/android-plugin/mvn-repo/master/'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
//        classpath fileTree(dir: '../gradle-plugin', include: '*.jar')
        classpath 'org.appcan.gradle.plugins:appcan-gradle-plugin:2.4.0'
    }
}
  1. dependencies中com.android.tools.build:gradle设置为3.0.1或更高版本之后,需要在所有的repositories中增加google(),否则会找不到Android新版的官方gradle相关插件库而报错;

  2. 若buildToolsVersion改为26或更高后,还会要求修改flavor的定义,如下修改即可:

    //声明flavorDimension
    flavorDimensions "kernel"

    productFlavors {
        crosswalk {
            dimension "kernel"
        }
        system {
            dimension "kernel"
        }
        x5 {
            dimension "kernel"
        }
    }
  1. 关于此,如果仍有问题,欢迎在提issue或者QQ群中互相讨论,或者关注这个issue:#136

插件开发gradle依赖引擎配置

  1. repositories中增加下面的maven地址:
repositories {
    maven {
        url 'https://raw.githubusercontent.com/android-plugin/mvn-repo/master/'
    }
}
  1. dependencies中增加引擎的远程依赖包。注意:远程引擎包不会经常更新,仅当有涉及插件接口变化的重大更新时才会更新对应的调试版本仅用于插件开发调试使用,无关紧要的小bug不一定会更新在此处。使用正式引擎还需要通过AppCan官方的打包服务。
dependencies {
    //implementation 'org.appcan:engine:4.0.0'
    //implementation 'org.appcan:engine:4.3.23'
    //implementation 'org.appcan:engine:4.4.27'
    implementation 'org.appcan:engine:4.5.30_dev'
}

相关的其他仓库传送门

  1. mvn-repo:用于存放仅供插件开发调试使用的远程依赖引擎包

https://github.com/android-plugin/mvn-repo

  1. gradle-plugin:插件辅助编译gradle脚本

https://github.com/android-plugin/gradle-plugin

  1. appcan-gradle-plugin:引擎辅助编译出包gradle插件源码

https://github.com/sandy1108/appcan-gradle-plugin

大版本更新列举(涉及插件开发的变动)

4.1版本

  1. JS交互逻辑变更,为了适配安全问题。

4.2版本

  1. JS交互逻辑再次变更,修复回调超过10240个字符时会被截断的问题。

4.3版本

  1. 全面增加Android动态权限申请,需要相关插件适配。引擎增加了针对插件申请权限的API。
  2. 补充内置了部分常用的support库,更新版本至26。
  3. minSdkVersion提升至16,targetSdkVersion提升至26

4.4版本

  1. 新增arm64等其他常见架构的libappcan.so库,引擎包基础工程的gradle中进行了过滤(v7和arm64),若有引擎定制需求,建议只需要修改gradle脚本的过滤,无需增删so的架构文件。另外,配合新版打包服务,可以无需定制引擎即可选择架构。
  2. support相关库升级至28。
  3. minSdkVersion提升至18,targetSdkVersion提升至28

4.5版本

  1. minSdkVersion提升至22,targetSdkVersion依然是28
  2. gson库升级至2.8.5,补充大量常用的support库,版本依然是28。(support库最后一个版本就是28,已经成为历史,下一步要迁移为androidx)
  3. 工程配置升级,支持JDK8编译(需要打包服务编译环境配合升级)。compileOptions中指定jdk版本为1.8,com.android.tools.build:gradle升级至3.1.3

4.6版本

  1. minSdkVersion依然22保持不变,targetSdkVersion提升至29,compileSdkVersion也提升至30;
  2. 由于targetSdkVersion升级到30,Android相关新特性和新的适配需要插件开发者关注,比如分区存储权限的变更等;
  3. 由于业内现在的普遍规定,App启动时引擎框架内默认不会强制申请任何权限(4.6以下版本的引擎会强制申请三个权限:WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE, ACCESS_COARSE_LOCATION)。对于原生插件来说,则需要自行检查自己的首次启动的权限申请是否妥当(比如是否缺失了上述三个权限是否会导致应用闪退或者异常,自动申请权限是否提前弹出了对用户友好的引导提示等等);
  4. 工程配置升级,com.android.tools.build:gradle升级至4.1.2

appcan-android's People

Contributors

appcanopensource avatar fred-ye avatar leegq827 avatar pingping-jiang6141 avatar sandy1108 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

appcan-android's Issues

图片路径的问题

你好你们的引擎能否增加一下对这个路径的优化。拍照获取的图片,竟然无法显示。
如下代码,这个最基本的功能,竟然死活实现不了。。

  function APPCAN_openCamera(){
      var self = this
      var comtextareass = 0 // 图片是否压缩,0表示压缩,非0或者不传表示不压缩
      var quality = 50 // 图片压缩质量,comtextareass为0时有效,取值范围[0,100]
      uexCamera.openInternal(comtextareass, quality, function(picPath) {

        alert(picPath)  
       // picPath = "/storage/emulated/0/widgetone/apps/11461287/photo/scan20171120135143.jpg"
        document.querySelector('.thumbImg').src =picPath
      })
    }

适配 AS 3.5.0 相关问题

依赖新版AppCanGradle插件

  1. 修改Engine/gradle/wrapper/gradle-wrapper.properties,其中版本改为5.4.1;

  2. 修改Engine/build.gradle文件中。其中,repositories增加一个github的maven库,dependencies中将原来的依赖本地的gradle插件改为依赖线上的,版本目前是2.3.1,可以在此仓库关注更新 https://github.com/android-plugin/mvn-repo。修改部分参考下面:

buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://raw.githubusercontent.com/android-plugin/mvn-repo/master/'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
//        classpath fileTree(dir: '../gradle-plugin', include: '*.jar')
        classpath 'org.appcan.gradle.plugins:appcan-gradle-plugin:2.3.1'
    }
}

引擎编译不通过问题,错误码如下

你好,按照步骤下载源码后编译不通过,错误:Error:No such property: metadataCharset for class: org.gradle.api.tasks.bundling.Zip_Decorated,请问这种情况如何解决?

编译引擎报错

↑1 AppCanPlugin/Engine_AppCan → ./gradlew buildEngine

Configure project :app
Observed package id 'build-tools;22.0.0' in inconsistent location '/Users/xxx/Work/IDE/android-sdk-macosx/build-tools/android-5.1' (Expected '/Users/xxx/Work/IDE/android-sdk-macosx/build-tools/22.0.0')

FAILURE: Build failed with an exception.

  • What went wrong:
    Task 'buildEngine' not found in root project 'Engine_AppCan'.

  • Try:
    Run gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

  • Get more help at https://help.gradle.org

BUILD FAILED in 1s
↑1 AppCanPlugin/Engine_AppCan →

使用文档里面编译引擎命令如上错误。

入口页面被放大2倍的问题

image
image
如上去,启动后,进入入口页面,然后打开新的页面,
入口页面的scale是2,
新页面的scale是1,

实际的界面也是入口页面被放大了2倍 .

BuildSystemEngine 报错

Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java_lang_String$substring$2.call(Unknown Source)
at com.appcan.AppCanPlugin.getEngineZipVersion(AppCanPlugin.groovy:151)
执行gradle task buildSystemEngine 报错

android 10 H5页面展示出现小窗口问题,展示异常

在android10以下h5页面展示正常,在android 10上页面展示异常:
1.页面中出现小窗口,小窗口可以左右上下滑动;
2.原来是一个页面,现在是一个底层页面,然后内容部分成了小窗口展示;

html 页面中无法展示 https 的图片

问题描述

我在页面中设置 img src 属性的时候,如果图片设置成我们服务器的 https 链接,那么图片就不会显示。代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
	<title>Title Here</title>
	<script type="text/javascript"></script>
</head>
<body>

<div class="uwh-bg umar-r-ect uwh-bg-img" id="imgtest">
	<img class="upimg" id="imgtesta" src="https://172.28.1.209/image......" width="100px" height="100px"/>
</div>

</body>
</html>

不能正确显示来自服务器的图片:

image

我排查后发现这是 https 证书配置问题,错误日志:

I/X509Util: Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

页面中的 https 请求都是没问题的:

appcan.ajax({
            type:"POST",
            url:baseUrl+url,
            data:data
            offline:false,
            expire:1000,
            timeout : 30000,
            dataType: 'json',
            beforeSend:function(xhr){
            },
            success:function(ret,status,xhr){           
            },
           error:function(xhr,type){  
        }
     });

尝试的解决办法

我试着在修改引擎代码,不要去做证书校验,在 org.zywx.wbpalmstar.platform.certificates.Http 中忽略证书校验:

public class Http {

    public static HashMap<String, KeyStore> KEY_STORE = new HashMap<String, KeyStore>();
    public static String algorithm = "X509";
    public static String keyType = "pkcs12";
    /**
     * 是否检查https证书为可信机构颁发
     */
    private static boolean isCheckTrustCert = false;

    private static InputStream getInputStream(String cPath, Context ctx)
            throws IOException, FileNotFoundException {
        InputStream inStream;
        String assertFile = "file:///android_asset/";
        String sdcardFile = "/sdcard/";
        String wgtFile = "widget/";
        String file = "file://";
        if (cPath.contains(assertFile)) {
            cPath = cPath.substring(assertFile.length());
            AssetManager asset = ctx.getAssets();
            inStream = asset.open(cPath);
        } else if (cPath.contains(sdcardFile)) {
            if (cPath.contains(file)) {
                cPath = cPath.substring("file://".length());
            }
            inStream = new FileInputStream(cPath);
        } else if (cPath.startsWith(wgtFile)) {
            AssetManager asset = ctx.getAssets();
            inStream = asset.open(cPath);
        } else {
            inStream = new FileInputStream(cPath);
        }
        return inStream;
    }

    public static javax.net.ssl.SSLSocketFactory getSSLSocketFactoryWithCert(String cPassWord, String cPath, Context ctx) {
        Log.e("httptest", "httptest == getSSLSocketFactoryWithCert(String cPassWord, String cPath, Context ctx)");

        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        TrustManager[] tm = {new HX509TrustManager()};
        try {
            sslContext.init(null, tm, new java.security.SecureRandom());
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslContext.getSocketFactory();
    }

    public static javax.net.ssl.SSLSocketFactory getSSLSocketFactory() {
        Log.e("httptest", "httptest == getSSLSocketFactory()");
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        TrustManager[] tm = {new HX509TrustManager()};
        try {
            sslContext.init(null, tm, new java.security.SecureRandom());
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslContext.getSocketFactory();
    }

    public static HttpsURLConnection getHttpsURLConnection(URL url) throws Exception {
        Log.e("httptest", "httptest == getHttpsURLConnection(URL url)");
        HttpsURLConnection mConnection = null;
        mConnection = (HttpsURLConnection) url.openConnection();
        javax.net.ssl.SSLSocketFactory ssFact = null;
        ssFact = Http.getSSLSocketFactory();
        ((HttpsURLConnection) mConnection).setSSLSocketFactory(ssFact);
        if (!isCheckTrustCert()) {
            ((HttpsURLConnection) mConnection)
                    .setHostnameVerifier(new HX509HostnameVerifier());
        } else {
            ((HttpsURLConnection) mConnection)
                    .setHostnameVerifier(new HX509HostnameVerifier());
        }
        return mConnection;
    }

    public static HttpsURLConnection getHttpsURLConnection(String urlString) throws Exception {
        URL url=new URL(urlString);
        HttpsURLConnection mConnection = getHttpsURLConnection(url);
        return mConnection;
    }

    public static HttpsURLConnection getHttpsURLConnectionWithCert(URL url,
            String cPassWord, String cPath, Context ctx) throws Exception {
        HttpsURLConnection mConnection = null;
        mConnection = (HttpsURLConnection) url.openConnection();
        javax.net.ssl.SSLSocketFactory ssFact = null;
        ssFact = Http.getSSLSocketFactoryWithCert(cPassWord, cPath, ctx);
        ((HttpsURLConnection) mConnection).setSSLSocketFactory(ssFact);
        if (!isCheckTrustCert()) {
            ((HttpsURLConnection) mConnection)
                    .setHostnameVerifier(new HX509HostnameVerifier());
        } else {
            ((HttpsURLConnection) mConnection)
                    .setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
        }
        return mConnection;
    }

    public static boolean isCheckTrustCert() {
        return isCheckTrustCert;
    }

    public static void setCheckTrustCert(boolean isCheckTrustCert) {
        Http.isCheckTrustCert = isCheckTrustCert;
    }
}

但是这并没有解决我们的问题,我在网上搜索之后发现 appcan 类似的问题:https自定义证书如何能通过安全认证,但是也是一直没有解决。

可能的解决方案

网上搜索发现在 onReceivedSslError 方法中接受证书就可以解决问题。

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){
        handler.proceed();
    }
});

问题

  1. 我该如何在 appcan 项目中配置 https 证书呢?

  2. 或者我该如何让我的 appcan 项目里全局请求网络的时候忽略校验证书呢?

PS:项目已整体迁移到 Android Studio 中了。

适配AS3.0.1相关问题

依赖新版AppCanGradle插件(beta版)

  1. 修改Engine/gradle/wrapper/gradle-wrapper.properties,其中版本改为4.1;

  2. 修改Engine/build.gradle文件中。其中,repositories增加一个github的maven库,dependencies中将原来的依赖本地的gradle插件改为依赖线上的,版本目前是2.2.3,可以在此仓库关注更新 https://github.com/android-plugin/mvn-repo
    修改部分参考下面:

buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://raw.githubusercontent.com/android-plugin/mvn-repo/master/'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
//        classpath fileTree(dir: '../gradle-plugin', include: '*.jar')
        classpath 'org.appcan.gradle.plugins:appcan-gradle-plugin:2.2.3'
    }
}
  1. dependencies中com.android.tools.build:gradle设置为3.0.1之后,需要在所有的repositories中增加google(),否则会找不到Android新版的官方gradle相关插件库而报错;

  2. 若buildToolsVersion改为26或更高后,还会要求修改flavor的定义,如下修改即可:

    //声明flavorDimension
    flavorDimensions "kernel"

    productFlavors {
        crosswalk {
            dimension "kernel"
        }
        system {
            dimension "kernel"
        }
        x5 {
            dimension "kernel"
        }
    }
  1. 为了方便开发者使用,修改后的gradle文件已经放在了工程根目录,名为build.gradle.3.0.1,由于在实验阶段,没有替换原有的。

Android Studio 打包 AppCan 项目时 assets 目录下文件无法进行加密

问题描述

Android Studio 打包 AppCan 项目时 assets 目录下文件无法进行加密:

因为 AppCan 线上打包速度慢的原因,我们把项目转移到 Android Studio 上了。现在打包 apk 的时候发现 assets 目录下文件都没有加密。

PS:项目中的 config.xml 文件 <obfuscation>false</obfuscation> 改为了 false, 不然 app 运行时会报找不到页面的错误。

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<widget...>
	
	<name>appname</name>
	<description/>
	<author email=""> </author>
	<icon src="icon.png"/>
	<license href=""/>
	<content encoding="utf-8" src="index.html"/>
	<updateurl/>
	<logserverip/> 
	<showmyspace>false</showmyspace>
	<obfuscation>false</obfuscation>
	<bgcolor>#fefefe</bgcolor>
	<orientation>15</orientation>
<debug/>
<partobfuscation/>
<webapp/>
</widget>

Expected Behavior

Android Studio 打包 AppCan 项目后反编译 apk, assets 目录下文件打开都是乱码。

Actual Behavior

Android Studio 打包 AppCan 项目后反编译 apk, assets 目录下文件打开可以看见源码,没有进行任何加密。

问题

我们该如何在 Android StudioAppCan 项目中配置,已达到加密 AppCan 代码( assets 目录下文件)的目的?

屏幕适配的问题

问题是这样的,我们的项目要适配三个屏幕,在 800*1080720*1280 的机器上都显示的很好,但是在另一个 1280*1920 的机器上显示的效果很差,所以我们需要做屏幕适配。我想用 像素密度 适配的方式来适配我们的 AppCan 项目,但是没有任何效果,想请问一下这个方案对于 AppCan 项目来说是否可行?

AppCan 这个框架是如何做屏幕适配的呢?

Originally posted by @aixiaozi in #153 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.