商米方案采购流程-支付开通流程

1、商户版(代理商未申请成为商米收银管家代理商,商户自行通过商米收银管家通道开通支付)

2、代理商版(代理商申请成为商米收银管家服务商,通过代理商开通支付的商户,代理商可享有商户日常流水分润)

2.1 聚合扫码/刷卡支付开通流程:

聚合扫码业务、银行卡刷卡业务指引

业务介绍:
1:商米收银台所支持的盛付通支付通道(持有第三方支付牌照,可开展聚合扫码业务,全国范围内的银行卡刷卡业务),可提供:聚合扫码B扫C(包含支付宝、微信扫码)、银行卡刷卡业务;
2:服务商拓展商户,商户可通过服务商提供的商米进件小程序*完成开户进件(*每个服务商都有一个专属小程序,可在服务商后台下载)。进件成功后,商米收银管家运营团队在后台进行参数配置,商户便可通过商米硬件开始收款;
3:商户可在商米收银台中输入金额收款,亦可在SaaS收银软件*中进行点单时,调用商米收银台完成收银。(*SaaS收银软件需与商米收银台完成对接);
4:盛付通扣除商户手续费后,将商户结算款于T+1日结算至商户进件时提供的银行账户中。

商户准入资质及相关:
1:盛付通支付通道接收三类商户的申请:
   1-1:有具体经营行为和消费场景的小微商户(无营业执照),款项默认入经营者名义的银行账户中;
   1-2:持有个体工商户营业执照的商户,款项默认入营业执照上经营者名义的银行账户中;
   1-3:持有企业营业执照的商户,款项默认入企业对公账户,或营业执照上法人名义的银行账户中;
2:上述三类商户的支付限额:
   1-1:小微商户:单笔5千,单日10万;
   1-2:个体工商户:单笔1万,单日20万;
   1-3:企业商户:单笔5万,单日100万;
  如有变更,另行通知;
3:符合要求的餐饮类商户可申请蓝海/绿洲计划,商户可在活动期内享受优惠费率,(蓝海绿洲费率为0.2%),详情可咨询商米收银管家运营团队;
4:如果商户需要开通银行卡刷卡业务,须签署盛付通纸质协议(线下收单服务合作协议),并在进件小程序中拍照上传。请服务商保存一联,定期交至商米收银管家运营团队,服务商可申请空白协议模板(该协议无电子版本)。
5:仅开通聚合扫码业务无需签署盛付通纸质协议;
6:商户打开小程序,选择所属商户类型,即可获知需准备的材料清单。

流程说明:


要点说明:
    1:服务商可在商米后台下载“专属进件二维码”,商户扫描该二维码进件,将自动归属至本服务商名下;
    2:“专属进件二维码”下载地址:商米合作伙伴后台partner.sunmi.com – 商米支付管理 – 基本信息 – 二维码名片(可保存此名片,下方显示服务商名称,可发给商户扫码自助进件);
    3:小程序根据商户选择的开户类型,给出开户所需要的材料清单,并引导商户进行自助申请;
    4:如果商户需要开通银行卡刷卡功能,请商户签署盛付通纸质协议,并在小程序中上传协议照片;
    5:建议服务商:要求商户在小程序中填写资料时,在最后的备注栏中填写设备SN号,以便于后台参数配置(商户可在外包装箱,或设备桌面上-硬件管家中查看SN,该过程将在近期得到优化);
   
6:商户费率暂由商米支付运营团队配置,服务商可提前告知默认费率,以提高进件效率。商户进件完成后,也可申请再次对费率进行调整(该过程将在近期得到优化,后续将支持服务商配参);
    7:在进件资料完整且合规的前提下,商户递交完后1个小时左右即可进行收款,商米支付运营团队会将结果告知服务商,由服务商通知商户收款;
    8:商户需将设备保持在Wifi环境下,使收银台组件能顺利自动安装;
    9:商户可登陆http://msp.shengpay.com进行查账,服务商可在商米后台进行商户交易流水查询;
    10:如有特殊情况请与运营团队联系。

2.2 人脸支付开通流程 :

商米收银管家 – 支付宝刷脸付(商户)签约流程

支付宝刷脸付产品说明:

1:商户如需使用刷脸付,必须先签约当面付,否则将造成交易失败;

2:商户可自行登陆支付宝账户后台签约当面付(标准费率为0.6%),也可委托支付宝官方服务商签约(服务商为其签约费率为0.38%~0.6%);

(支付宝账户后台地址:https://b.alipay.com)

3:如商户需解约当面付,需自行电话至支付宝客户进行解约申请;

(支付宝客服电话:0571-88158090 工作时间9:00-22:00)

4:商户签约刷脸付为免费,商户在刷脸付交易过程中,交易手续费费率随当面付费率。

签约时效说明:

1:当面付的签约时效一般为1~2个工作日;

2:刷脸付的签约时效一般为1~2个工作日;

3:支付宝官方拥有签约时效的最终解释权。

商户需要准备资料:

1:商户需签约刷脸付的支付宝账户;

2:清晰的营业执照照片(个体工商户或企业);

3:清晰的门头照片和门店内景照片;

4:特定行业需提供特定资质(资质明细:https://cshall.alipay.com/enterprise/knowledgeDetail.htm?knowledgeId=201602066235

5:联系人姓名、手机号码、邮箱(用于接收支付宝签约通知)

6:商户支付宝账户合作伙伴身份(PID),(可登陆此链接获取:https://openhome.alipay.com/platform/keyManage.htm?keyType=partner

7:商户处设备SN号

服务商获得(上方)商户资料后:

点击下方链接,登记《刷脸付商户登记表》:https://jinshuju.net/f/QvGMyM

注意事项:

1:商户必须持有个体工商户或企业营业执照,且申请的支付宝账户主体需与营业执照经营主体一致,目前不受理无营业执照的商户申请;

2:如果企业法人的支付宝账户未做企业认证,则视为个人支付宝账户,目前不可签约刷脸付;

3:商米收银管家运营团队不负责为真实经营的商户代签约当面付,服务商可通过申请成为支付宝官方服务商、或委托其他服务商帮商户代签约当面付。

(申请支付宝官方服务商入口:https://open.alipay.com/

4:服务商只可为本渠道下设备申请绑定支付功能。

打印服务开发文档

商米收银管家FAQ

问:商米收银管家能为软件商做什么?

答:商米收银管家封装了一个标准的支付SDK接口,方便软件商与支付通道做对接。一次对接后,即可适配商米全系列安卓收银设备。

 

问:商米收银管家目前能提供哪些支付方式?

答:目前可提供聚合扫码B扫C(微信扫码和支付宝扫码)、支付宝人脸支付、银联卡刷卡。将陆续开放更多支付方式。

 

问:商米收银管家目前有哪些支付通道?

答:目前商米收银管家已经接入盛付通通道,以及支付宝刷脸付官方通道。未来将接入更多其他支付通道。

 

问:对上述支付通道,商米收银管家目前能提供什么费率?

答:根据软件商选择不同的支付通道,商米收银管家提供的费率也有所不同。具体费率详情请与商米收银管家BD联系。

 

问:商户资金如何结算,由商米公司打款给商户吗?

答:商米公司不会触碰商户资金。所有款项均由持有第三方支付牌照的机构或银行直接结算给商户。

 

问:商米收银管家是否支持公众号支付,小程序支付等线上支付方式?

答:目前尚不支持。公众号、小程序支付、C扫B(码牌),H5支付,web支付,app支付等将在后续陆续上线。

 

问:商米收银管家是否支持即时到账,如何收费?默认到账时效如何?

答:即时到账服务由支付公司提供。不同的支付公司提供即时到账的方式、收费标准不同。目前已经对接的盛付通尚不支持即时到账。后续将开通此项业务。盛付通默认到账时效为T+1。

 

问:商户进件时,商户跟谁签约?软件商(服务商)跟谁签约?

答:商户与持有第三方支付牌照的支付机构签署入网协议(不同通道的协议方式不同);软件商(服务商)与商米公司签约成为商米收银管家服务商。商户与软件商(服务商)的协议由双方自行约定。

 

问:软件商对商米收银管家有合作意愿,业务如何对接?

答:完整的业务合作包括两部分:技术对接与商务协议签署,这两部分可以并行操作。软件商表达合作意愿后,商米收银管家运营将协调商米开发团队与软件商开发团队进行对接(拉微信群)。另外,软件商可以与商米收银管家BD签署“商米收银管家服务商协议“,软件商成为商米收银管家服务商后,可以拓展商户并从交易流水中获得支付分润。

 

问:商户如何进件?是否有自动进件接口?进件时效?

答:目前:软件商(商米收银管家服务商)收集商户进件资料,线下给商米收银管家运营,由商米收银管家运营在支付通道后台进件。如果软件商需要,商米收银管家可提供进件接口给软件商。2月中旬以后,商米收银管家将提供进件资料收集工具(小程序),供商户使用。进件时效依据具体支付通道而定。一般在T+1到T+3之间。

 

问:商户如何对账,软件商是否有后台查看商户交易信息,分润信息?

答:商户进件成功后,支付机构会将后台账户密码发送给商户。商户可以登陆支付机构后台进行交易查询。软件商可登陆商米提供的合作伙伴平台,管理名下商户,查看商户交易,查看服务商分润信息。

 

问:软件商是否能拓展非自身渠道设备的商户?

答:目前,软件商只能拓展本渠道下的商户。商户使用的设备必须隶属于该软件商渠道下,方可开展支付业务。

 

问:软件商与商米收银管家对接后,能否在非商米设备上使用?

答:软件商与商米收银管家对接,商米收银管家为一个独立APK,该APK目前只能在商米设备上运行。

 

问:刷脸付是否可以走自己的支付通道?

答:软件商在商米自助收银设备上使用刷脸付,需要通过商米收银台调用支付宝官方刷脸付通道。

 

问:给商户开通刷脸支付需要提交给商米什么资料?刷脸付支付成功,收到的款项如何流转?

答:商户需提前开通支付宝当面付。开通后,请将该当面付的支付宝账户、联系人姓名、联系人电子邮箱、联系人电话递交给商米公司。刷脸付支付成功后,款项入商户绑定的支付宝账户中。

扫码头返回类型


Number Code Type CodeID Zebra CodeID Newland CodeID Fp/NL Notice   Example  
1 Code128 D j j Newland,Fp/NL:
AIM-128 — f
SETTING 128 — t
     
2 UCC·EAN128(GS1-128)   j u        
3 ISBT
128
D j  j  Zebra:
ISBT 128 Concatenated — D
     
4 EAN8 A d g        
5 EAN13 A d d        
6 UPC-E A c h        
7 UPC-E1 A            
8 UPC-A A c c   Instruction
9 Interleaved
2 of 5(ITF)
F e e Newland,:
ITF-6 —  e
ITF-14 — e 
Fp/NL:
ITF-6 —  r
ITF-14 — q
Head noun Paraphrase Scanner ID
10 Matrix
2 of 5
S v v   Nls NewLand (EM2096) ]N
11 Code39 B b b Zebra:
Trioptic Code 39 — M 
Zebra Zebra (4710) ]Z
12 Codabar C a a   Fp(Falcon) Falcon(BSM1825) ]FN
13 Code93 E i y   NL NewLand(EM1365) ]FN
14 GS1
DataBar(RSS)
R R R        
15 Composite-UCC T     Zebra:
MiroQRTCIF Linked Code 39(TLC 39) — T 
     
16 Composite-UPC              
17 Code11 H H z        
18 ISBN(Bookland
EAN)
L B B   Return: Scanner ID+Code ID  
19 Industrial
2 of 5
  D i        
20 Standard
2 of 5
  s s   Example:
scanner:Zebra
code content:123456
code type:code 128

return:]ZD123456

21 Discrete
2 of 5(DTF)
G            
22 Chinese
2 of 5
U            
23 Korea
3 of 5
V            
24 Plessey   p p Newland:
UK Plessey — p
     
25 MIS-Plessey J m m        
26 Composite
A/B
             
27 Composite
C
             
28 ISSN
EAN
X n n        
29 PDF417 X r          
30 QR
Code
P01 Q          
31 Aztec z            
32 DataMatrix P00 u          
33 HanXin P0H h          
34 MaxiCode P02            
35 AustralinPostal P08            
36 US
Postnet
P03            
37 US
Planet
P04            
38 Uk
Postal
P06            
39 Japan
Postal
P05            
40 Deutsche
12
  l l        
41 Deutsche
14
  w w        
42 Code32 B b b         
43 Netherlands
KIX Code
P08            
44 USPS
4CB/One Code/Intelligent Mail
P0A            
45 UPU
FICS Postal
P0B            
46 Signature
Capture
P0X            
47 Coupon
Code
N            

磁条卡数据格式

磁条卡数据格式符合ISO7810格式


第1磁道数据格式

数据编码最大记录长度为79个字符,格式如下所示。

字段 长度 内容 说明
起始字符 STX 1 % 第一磁道起始标识
格式代码 FC 1 B 表明格式是B
主账号 PAN <=19   标明可以处理交易的发卡机构(issuer identification)
和持卡者(individual account identification)
字段分隔符 FS 1 分隔符
姓名 NM 2~26   持卡人的姓名
字段分隔符 FS 1 分隔符
失效日期 ED 4 格式YYMM 如不定义失效日期该字段应为一分隔符
服务代码 SC 3   标明银行卡可使用的服务类型,
如不存在或不指定该字段以一个分隔符代替
附加数据 DD 11   存放卡片验证码(CVN)及对发卡机构
有意义的任意数据,应使整个磁道数据
不超过79个字符
结束标识 ETX 1 ? 第一磁道结束标记
纵向冗余校验字符 LRC 1 ‘ ‘  
备用数据 13 空格填充  

第2磁道数据格式

数据编码最大记录长度为40个字符,格式如下表所示。

字段 长度 内容 说明
起始字符 STX 1 第二磁道起始标识
主账号 PAN <=19   标明可以处理交易的发卡机构和持卡者
字段分隔符 FS 1 = 分隔符
失效日期 ED 4 格式YYMM 如不定义失效日期该字段应为一分隔符
服务代码 SC 3   标明银行卡可使用的服务类型,
如不存在或不指定该字段以一个分隔符代替
附加数据 DD 13   存放卡片验证码(CVN)及对发卡机构
有意义的任意数据,应使整个磁道数据
不超过40个字符
结束标识 ETX 1 ? 第二磁道结束标记
纵向冗余校验字符 LRC 1 _  

第3磁道数据格式

共113位,其中107位是银联中三磁道数据最大长度,格式如下表所示。

字段 长度 内容 说明
起始字符 STX 1 第三磁道起始标识
格式代码 FC 2 99  
主账号 PAN 16   16位卡号,
标明可以处理交易的发卡机构和持卡者
字段分隔符 FS 1 = 分隔符
国家代码 CC 3 156 如存在应为CCC格式的3个数字,
标明可以处理由银行卡产生交易的国家
货币代码 3   表明结算时使用的货币类型:3位数字
金额指数 1   决定周期授权量与本周期余额两字段的基值
周期授权量 4   由发卡机构自定授权量,
表示在一个周期内累积交易不能超过的金额
本周期余额 4   当前周期内的可用余额
周期开始日期 4 格式YDDD 表示一个新周期开始的日期
周期长度 2   2位数字,表示所有交易的累积值不能超过授
权量的时间期限
密码重输次数 1   记录允许未成功输入密码的次数
个人授权控制参数 6   提供一种可选择的安全性能
交换控制符 1   标明银行卡适用于交换的范围
PAN的TA和SR 2   定义PAN的账户类型和可提供的服务
SAN-1的TA和SR 2    
SAN-2的TA和SR 2    
失效日期 ED 4 格式YYMM  
卡序列号 1   区别具有相同PAN的卡,由发卡机构定义,
在最初发卡或卡失效后换卡时赋值
卡保密号 1   用于建立磁条所含数据与物理卡的联系
SAN-1 8   标明第一个可选用的辅助账号
(first subsidiary account number)
字段分隔符 FS 1 =  
SAN-2 0   标明第二个可选用的辅助账号
(second subsidiary account number)
字段分隔符 FS 1 =  
传递标志 1   提供可减少传送交换信息长度的功能,
它表明交换信息是否包含附加数据的内容
加密校验数 CCD 6   通过使用加密公式提供一种校验该磁道上
数据完整性的方法
附加数据 DD 8   存放卡片验证码(CVN)及对发卡机构
有意义的任意数据,应使整个磁道数据
不超过113个字符
结束标志 ETX 1 ?  
纵向冗余校验码 LRC 1 ‘ ‘  
备用数据 19 空格填充  
填充数据 6 空格填充至8的倍数位  

自定义客显程序开发说明

更新内容

2018-01-15
  • 去掉常用方法、关键类说明;
  • 更新Demo源码;
  • 更新双屏应用开发调试的方法;

一、简介

T1双屏机器有三种组合:主机、主机+7寸副屏、主机+14寸副屏。主副屏都是运行SUNMI OS定制系统,通过商米已封装好的接口实现通信。主屏主要用来运行业务APP,例如:收银系统。副屏主要面向顾客显示结算、广告内容。

双屏通信原理:

image

从下到上依次为:

  • Driver:该层是最底层的通信协议,开发者无需关注。
  • Service:该层是商米封装的一个通信服务,开发者也无需关注。
  • SDK:该层是T1自带的副显程序使用的通信接口,自定义的客显程序调用的是该层的接口。
  •  APP:指的是开发者自己的业务app和内置的副显程序。

开发者有两种方式实现副屏显示:

  • T1副屏系统内置了默认副屏显示APP,内置多个常用模板。开发者仅需通过商米的SDK向副屏发送正确格式的数据,即可实现副屏显示内容。
  • 开发自己副屏显示APP,需要自行处理数据的收发、内容显示等动作;

虽然商米封装的内置客显程序能满足绝大部分开发者的使用需求,但是考虑业务的多样性,商米秉持开放的原则,支持开发者自己定义副屏显示。

下文将对开发自定义双屏应用进行说明。

二、如何调试应用

由于主副屏是通过USB通信的,当主/副屏插入USB线时,主副屏的连接会断开,导致无法调试设备。商米提供的解决方案是:将开发电脑与将要调试的T1主机处于同一个局域网络环境下,通过网络对设备进行调试。

如何调试:

1、开启USB调试,及调试权限;

    操作说明

2、通过网络对设备进行ADB调试;

    操作说明

三、如何开发自定义双屏应用

(强调:Sunmi OS是基于Android6.0定制,Android6.0+ 要求部分敏感权限需要动态申请)

1、初始化配置

以下将基于Demo讲解自定义双屏应用如何实现。

步骤1:

    下载DoubleAPP资源文件。(源码使用AndroidStudio编写)

步骤2:

    参照Demo源码,直接在Android Studio的app module下的build.gradle文件中声明以下代码。

compile 'com.sunmi:DS_Lib:1.0.9'  //商米提供的lib库,包含已封装好的接口
compile 'com.google.code.gson:gson:2.6.2'  //gson任意版本

步骤3:

    在清单文件AndroidMainfest.xml的节点下注册广播(开发者可参考Demo源码,自行实现广播类)。

"...广播类...">  //接收数据的广播
"com.sunmi.hcservice"/>
"com.sunmi.hcservice.status"/>

步骤4:

    在适当的位置初始化SDK代码,可以参考Demo源码。

private void initSdk() {
mDSKernel = DSKernel.newInstance();  
mDSKernel.init(this, mIConnectionCallback);  //绑定服务的回调
mDSKernel.addReceiveCallback(mIReceiveCallback);  //双屏通信接收数据回调
}

2、开发双屏应用

参考Demo源码,实现双屏数据交互。具体方法可以自行定义,此处不做示例。

当主屏与副屏的业务逻辑都已经实现了,需要将主屏与副屏的业务代码合在一个apk里(因为应用市场的安装逻辑是将一个应用分别安装到主副屏,故双屏应用只需提交一个APK)。

四、发布应用前的准备

自定义双屏应用已经开发好了,那接下来就要将应用发布至商米应用市场,分发出去。在此之前,需要再做一件重要的步骤,就是让应用市场能够识别该应用是双屏应用。

在应用的AndroidManifest.xml中添加一行标识代码,这样,该应用在应用市场上将显示为双屏应用,安装时,应用市场会将该应用分别安装在主屏和副屏。 "sunmi_dual" android:value="open"/>

调试说明

背景

  • 为什么需要通过网络调试?

    目前T1主屏与副屏通过USB连接通信,主屏作为主设备,副屏作为从设备,USB外设也是从设备。当PC通过USB线连接主屏(或副屏)进行调试时,PC作为主设备,主屏(或副屏)会作为从设备,此时主屏与副屏的通信会断开,外接USB设备的连接也会断开。因此,PC通过连USB线只能单独调试主屏或是副屏,并且会导致USB外设连接断开,也就是无法调试同时用到主副屏的应用,也无法调试使用到USB外设的应用。

  • 商米提供了解决以上问题的解决方案:

    PC通过有线或无线局域网连接T1设备,可以在不影响T1双屏通信及外设使用的情况下,对使用T1双屏或是使用USB外设的应用进行调试。

调试原理

å--å±-ADBè°-è¯-

说明:

  • T1的主副屏已经通过内置USB线连接,无需另外再通过USB线连接;
  • PC需要通过网络连接T1双屏机器(主屏);
  • 调试主屏:PC直接通过WiFi/有线网络调试主屏;
  • 调试副屏:PC先通过网路连接主屏,通过主屏桥接来调试副屏;

前置条件:

  1. WiFi/有线局域网,网络连接正常;
  2. PC与T1主屏在同一个局域网内;
  3. T1双屏系统版本均支持双屏ADB调试;(14主屏:V1.11.4及以上,14寸副屏:V1.8.3及以上)
  4. T1主屏开启USB调试;(T1主屏系统设置-开发者设置-USB调试 开启)
  5. T1双屏机器上不要外接USB调试线;(主屏/副屏外接USB调试线会导致双屏通讯断开,将只能调试其中一块屏幕)
  6. PC支持ADB调试环境;
  7. T1主副屏通讯正常;(打开主屏“副屏设置”,可查看副屏的系统版本信息)

操作步骤:

1.获取主屏IP地址

    在T1主屏系统设置-关于-状态信息查看主屏IP,记录IP地址。

    例如:

192.168.1.12

2.添加终端-主屏

    在PC上打开终端命令行工具,输入以下命令:

adb connect 192.168.1.12:5555

    说明:“192.168.1.12”要替换为记录的主屏IP地址,主屏对应的端口号是“5555”,不可修改。此时应该显示:Connected to 192.168.1.12:5555,表示已连接上主屏。

3.添加终端-副屏接步骤2,输入以下命令:

adb connect 192.168.1.12:5554

    说明:“192.168.1.12”要替换为记录的主屏IP地址,副屏对应的端口号是“5554”,不可修改。此时,应该会显示:Connected to 192.168.1.12:5554,表示已连接上副屏。
强调:必须先连接上主屏,才能连接副屏。

4.查询已添加的终端

    接步骤2或者步骤3,输入以下命令:

adb devices

    说明:此时,应该会显示1~2个终端设备。

5.调试指定终端

    接步骤3,调试主屏需输入以下命令:

adb -s 192.168.1.12:5555 shell ls

    说明:“192.168.1.12”要替换为主屏的IP地址,主屏对应的端口号是“5555”,不可修改。此时,应当显示主屏存储的目录。“shell ls”可以替换为其它的ADB命令。

    接步骤3,调试副屏需输入以下命令:

adb -s 192.168.1.12:5554 shell ls

    说明:“192.168.1.12”要替换为主屏的IP地址,副屏对应的端口号是“5554”,不可修改。此时,应当显示副屏存储的目录。“shell ls”可以替换为其它的ADB命令。

6.断开终端连接

    接步骤3,断开主屏副屏需输入以下命令:

adb disconnect 192.168.1.12:5555

    说明:“192.168.1.12”要替换为主屏的IP地址,主屏对应的端口号是“5555”,不可修改。此时,应当同时断开主屏和副屏的连接。
    强调:断开主屏连接时,会同时断开副屏连接。

示意图

添加终端:

WechatIMG53

调试指定终端-主屏:

WechatIMG39

调试指定终端-副屏:

WechatIMG40

断开终端连接-主屏和副屏:

截图 2017-07-13 12时15分48秒

USB、串口设备使用说明文档

1. 简介:

外设接口 LAN 口,钱箱口, usb2.0 口,串口,耳机孔等通用通信接口。
本文主要介绍钱箱口,usb 口和串口的使用方式。
图片 2

2.接口说明

1)钱箱口: 钱箱口使用RJ12接口。
开发者可以通过向钱箱口发送数据来控制钱箱。 钱箱开发者文档及资源文件 2)串口:  串口使用 RJ11 接口。
开发者可以通过串口的数据发送来控制外设。 由于安全考虑,不支持串口节点遍历,但可以直接打开端口进行通信
(机器底座串口的节点路径/dev/ttyHSL1)  串口参考demo ,JNI参考 通信文档事例:Jaynes 串口电子秤通信文档(不同电子秤通信协议需参考每家厂商提供的
文档)   3) USB 口:  支持 USB2.0 协议的 USB 设备。 USB 通信开发者文档 3.1 获取 USB 设备的 PID/VID 方法1:java代码

try {
//获得外接USB输入设备的信息
Process p=Runtime.getRuntime().exec("cat /proc/bus/input/devices");
BufferedReader in = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String line = null;
while((line = in.readLine())!= null){
}
String deviceInfo = line.trim();
//对获取的每行的设备信息进行过滤,获得自己想要的。
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
*deviceinfo中包含每个设备的pid和vid* 

方法2:adb命令 

adb shell cat /proc/bus/input/devices
图片 1

  3.2 通用 USB 外设

  • HID设备

默认支持 HID 协议设备(鼠标键盘扫码枪等),可即插即用。  HID 扫码枪 HID扫码枪可即插即用:连接商米设备,在商米设备上打开一个可编辑框并获取焦点,扫码。此时编辑框应该被输入条码或者二维码内容。从代码获取扫码内容可参考USB 外设通信谷歌开发者文档

  • U盘

支持的U盘格式:  FAT32:可读可写;NTFS:可读不可写 ;exFAT:不支持

  • 摄像头

商米支持 USB UVC 摄像头 (如LogitechC170) 开发包 Demo源码Github源码地址

  • 商米读写器

侧边栏可接入商米读卡器(刷卡槽接口)

66D031F8-2666-49ED-8E7A-A6C88572BEE7

商米读卡器包含两部分,一部分为磁条卡刷卡,磁条卡刷卡可参考商米读卡器开发包和读卡器demo。另一部分为nfc,nfc为android原生接口,可参考android nfc开发文档

商米读卡器开发包
商米读卡器demo
商米读卡器demo源码
  • 第三方通用读写器

商米目前已经支持四款第三方usb通用读写器,开发者可参考商米提供的demo做读卡写卡操作。

  1. 上海亿矽智能科技有限公司UM002读卡器
  2. 深圳市德卡科技有限公司T10读写器(需支持android版本,电源充电版)
  3. 香港龙杰智能卡有限公司ACR1281U-C1读写器
  4. 香港龙杰智能卡有限公司ACR1281U-K1读写器

开发文档2.0

通用读写器demo

通用读写器demo源码

T1双屏通信接口文档

关键类说明

包 sunmi.ds
DSKernel类:SDK核心类,该类暴露了向副屏发送数据、初始化SDK的函数* newInstance(): DSKernel

说明:实例化DSKernel类的静态函数。

getDSDPackageName(): String

说明:获取副屏接收数据的app包名的静态函数。
返回值:packageName,副屏负责接收数据的App包名

init(Context contetx, IConnectionCallback stateCallback, String vicePackageName): void

说明:初始化SDK。
参数:
contetx:android上下文对象。
stateCallback:与副屏的连接状态回调。
vicePackageName:副屏接收数据的app包名,传null或空字符串则默认接收数据的app为Sunmi的副屏默认App。

init(Context contetx, IConnectionCallback stateCallback): void

说明:初始化SDK。
参数:
contetx:android上下文对象。
stateCallback:与副屏的连接状态回调。

isConnected(): boolean

说明:判断双屏通讯连接是否畅通
返回值:isConn true为畅通,false为断开。

sendData(DataPacket pack): void

说明:发送数据。
参数:
pack:DataPacket类型的对象,封装了要发送的数据。

sendCMD(String recePackageName, String cmd, long fileId, ISendCallback callback): void

说明:发送CMD命令包,可指定要使用的缓存文件id。
参数:
recePackName:接收端包名。
cmd:命令。
fileId:要使用的缓存文件id,如果没有则传0。
callback:发送结果回调。

sendCMD(DataPacket dataPacket): void

说明:发送CMD命令包,可指定要使用的缓存文件id。
参数:
dataPacket:CMD类型数据包。

sendQuery(DataPacket mPack, QueryCallback callback): void

说明:发送数据,向副屏发送查询数据包时使用。
举例:在用户协议层,主屏向副屏发送一个表示查询副屏亮度的Query数据包,副屏App收到后获取亮度再调用
sendResult(long queryId)函数向主屏发回一个携带亮度的结果数据包,此Result数据包的queryId必须与Query
数据包的taskId一致,主屏才能识别到是之前的查询结果。
注意:使用QueryCallback接收结果数据包时,通过addReceiveCallback()注册的回调实例将不会被调用。
参数:
pack:DataPacket类型的对象,封装了要发送的数据。
callback 查询结果回调

sendQuery(String recePackageName, String queryStr, ISendCallback sendCallback, QueryCallback callback): void
说明:发送数据,向副屏发送查询数据包时使用。
举例:在用户协议层,主屏向副屏发送一个表示查询副屏亮度的Query数据包,副屏App收到后获取亮度再调用
sendResult(long queryId)函数向主屏发回一个携带亮度的结果数据包,此Result数据包的queryId必须与Query
数据包的taskId一致,主屏才能识别到是之前的查询结果。
注意:使用QueryCallback接收结果数据包时,通过addReceiveCallback()注册的回调实例将不会被调用。
参数:
recePackageName:接收端包名。
queryStr:要携带的字符串数据
sendCallback:发送结果回调
callback:查询结果回调

sendResult(String recePackageName, String resultStr, long queryId, ISendCallback sendCallback): void

说明:发送Result数据包。
参数:
recePackName:接收端包名。
resultStr:查询结果。
queryId:Query数据包的taskId。
sendCallback:发送结果回调。

sendFile(String recePackName, String filePath, ISendCallback callback): long

说明:发送文件。
参数:
recePackName:副屏接收的app package name。
filePath:文件路径。
callback:发送结果回调。
返回值:taskId,维护此任务Id直至收到发送成功的回调时可以向副屏发送指令对文件做自定义操作,比如:显示图片、打开文件等操作。
注意:文件传输到副屏以后会被缓存起来并且与返回的taskId形成映射关系,若想长期复用该文件则应将taskId持久化维护起来。

sendFile(String recePackName, String msg, String filePath, ISendCallback callback): long

说明:发送一个文件+String类型的数据
参数:
recePackName:副屏接收的app package name。
msg:String类型的数据,例如:一个json格式的字符串、一段文字信息等…
filePath:文件路径。
callback:发送结果回调。
返回值:taskId,维护此任务Id直至收到发送成功的回调时可以向副屏发送指令对文件做自定义操作,比如:显示图片、打开文件等操作。
注意:文件传输到副屏以后会被缓存起来并且与返回的taskId形成映射关系,若想长期复用该文件则应将taskId持久化维护起来。

sendFiles(String recePackName, String msg, List files, ISendFilesCallback callback): long

说明:发送多个文件+String类型的数据
参数:
recePackName:副屏接收的app package name。
msg:String类型的数据,例如:一个json格式的字符串、一段文字信息等…
files:文件路径集合。
callback:多文件发送结果回调。
返回值:taskId,维护此任务Id直至收到发送成功的回调时可以向副屏发送指令对文件做自定义操作,比如:显示图片、打开文件等操作。
注意:文件传输到副屏以后会被缓存起来并且与返回的taskId形成映射关系,若想长期复用该文件则应将taskId持久化维护起来。

checkFileExist(long fileId, final ICheckFileCallback callback): void

说明:检查fileId对应的文件在副屏是否存在
参数:
fileId:文件Id。
callback:检查结果回调

addConnCallback(IConnectionCallback callback): void
说明:注册一个监听连接的回调,可注册多个。
参数:
stateCallback:与副屏的连接状态回调。

removeConnCallback(IConnectionCallback callback): void
说明:移除监听连接的回调。
参数:
stateCallback:与副屏的连接状态回调。

checkConnection(): void
说明:检测与副屏的连接状态,有结果会回调注册的IConnectionCallback。

addReceiveCallback(IReceiveCallback receiveCallback): void
说明:注册数据接收回调,可注册多个。
参数:
receiveCallback:接收端用于接收发送端数据的回调接口。

removeReceiveCallback(IReceiveCallback receiveCallback): void
说明:移除数据接收回调。
参数:
receiveCallback:要注销的回调实例。
FilesManager类:持久化维护缓存接收到的文件,以发送文件任务的taskId为key缓存DSFile、DSFiles。* getFile(Long taskId): DSFile说明:根据任务ID获取文件。
参数:
taskId:文件对应的任务ID。

getFiles(Long taskId): DSFiles说明:根据任务ID获取多个文件。
参数:
taskId:文件对应的任务ID。
—>

包 sunmi.ds.callback
IReceiveCallback类:接收数据时的回调接口。* onReceiveData(DSData data): void说明:接收到数据时的回调。
参数:
data:接收到的数据

onReceiveFile(DSFile file): void说明:接收到单个文件时的回调。
参数:
file:接收到的文件

onReceiveFiles(DSFiles files): void说明:接收到>=1个文件+一段String类型数据时的回调。
参数:
files:接收到的文件+String数据

onReceiveCMD(DSData cmd): void说明:接收到CMD类型数据时的回调。
参数:
cmd:接收到的CMD类型的数据

QueryCallback类:接收到查询结果数据包时的回调。* onReceiveData(DSData data): void说明:接收到结果数据包时的回调。
参数:
data:接收到的数据

IConnectionCallback类:双屏通讯连接状态的回调接口,所有回调函数都运行在子线程。* onDisConnect(): void说明:连接断开时的回调。

onConnected(ConnState state): void说明:连接状态更新时回调。连接状态分为3种:1.与本地service链接正常、2.与副屏service连接正常(处于这种状态下就可以向副屏发送数据了)、3.与副屏APP连接正常。
参数:
state:连接状态

ICheckFileCallback类:检查文件结果回调接口。* onCheckFail(): void说明:检查失败(通讯失败)。

onResult(boolean exist): boolean说明:检查失败(通讯失败)。
参数:
exist:true表示存在,false表示不存在。

IConnectionCallback类:双屏通讯连接状态的回调接口,所有回调函数都运行在子线程。* onDisConnect(): void说明:连接断开时的回调。

onConnected(ConnState state): void说明:连接状态更新时回调。连接状态分为3种:1.与本地service链接正常、2.与副屏service连接正常(处于这种状态下就可以向副屏发送数据了)、3.与副屏APP连接正常。
参数:
state:连接状态

ISendCallback类:发送String数据或单个文件的回调接口,所有回调函数都运行在子线程。* onSendSuccess(long taskId): void说明:发送成功时的回调。
taskId:任务Id,对应发送的数据或文件

onSendFail(int errorId, String errorInfo): void说明:发送失败时的回调。
参数:
errorId:错误识别码。
errorInfo:错误描述。

onSendProcess(long totle, long sended): void说明:发送进度的回调。
参数:
totle:数据的总大小,单位:byte。
sended:已发送的数据大小,单位:byte

ISendFilesCallback类:发送>=1个文件+String数据的回调接口,所有回调函数都运行在子线程。* onAllSendSuccess(long fileId): void说明:多个文件都发送成功时的回调。
fileId:任务Id也是缓存在副屏文件对应的fileId。

onSendSuccess(String path, long taskId): void说明:某一个文件发送成功时的回调。
taskId:任务Id,发送多个文件都属于同一任务所以taskId都相同。

onSendFail(int errorId, String errorInfo): void说明:发送String数据失败时的回调,String数据发送失败后不会继续发送文件。
参数:
errorId:错误识别码。
errorInfo:错误描述。

onSendFileFaile(String path, int errorId, String errorInfo): void说明:发送某一个文件失败时的回调。
参数:
path:发送失败对应的文件路径。
errorId:错误识别码。
errorInfo:错误描述。

onSendProcess(String path, long totle, long sended): void说明:发送某个文件的进度回调。
参数:
path:对应的文件路径。
totle:数据的总大小,单位:byte。
sended:已发送的数据大小,单位:byte
—>
<— 包 sunmi.ds.data *DataPacket类:封装了发送数据和发送回调,调用DSKernel类的sendData(DataPacket pack)函数时需要的参数实体类。DataPacket.Builder类:DataPacket的builder类。 Builder(DSData.DataType dataType)说明:构造函数。
参数:
dataType:要build的数据类型。

recPackName(String recPackName): Builder说明:指定接收数据的app包名。
参数:
recPackName:接收数据的app包名。
返回值:Builder实例

data(String data): Builder说明:指定要发送的数据。
参数:
data:要发送的String数据。
返回值:Builder实例

taskId(long taskId): Builder说明:指定任务Id,不指定则自动生成。
参数:
taskId:任务Id。
返回值:Builder实例

fileId(long fileId): Builder说明:指定缓存文件Id。
参数:
fileId:缓存文件Id。
返回值:Builder实例

queryId(long queryId): Builder说明:指定Query数据包的Id。
参数:
fileId:Query数据包的Id。
返回值:Builder实例

isReport(boolean isReport): Builder说明:指定是否需要结果回调。
参数:
isReport:是否需要结果回调。
返回值:Builder实例

addCallback(ISendCallback callback): Builder说明:设置发送结果的回调实例。
参数:
callback:发送结果的回调实例。
返回值:Builder实例

build(): DataPacket说明:build一个DataPacket实例。
返回值:DataPacket实例

DSData类:双屏通讯的数据封装。* sender: String说明:发送端app包名。

taskId: long说明:任务Id。

fileId: long说明:缓存文件Id。

queryId: long说明:Query数据包的任务Id。

dataType: DataType说明:数据类型。

data: String说明:要发送的数据。

DSData.DataType枚举类:数据类型描述封装。* DATA: DataType说明:表示数据。

FILE: DataType说明:表示文件。

CMD: DataType说明:表示命令。

typeCode: int说明:类型code。

DSFile类:接收端接收的文件类。* sender: String说明:发送端app包名。

path: String说明:接收到的文件路径。

taskId: long说明:任务Id。

DSFiles类:接收端接收的多文件类。* filesDescribe: FilesDescribe说明:封装了接收到的String数据与文件数量。

sender: String说明:发送端app包名。

files: List说明:接收到的文件路径集合。

taskId: long说明:任务Id。

FilesDescribe类:封装了接收到的String数据与文件数量。* msg: String说明:接收到的String数据。

fileCount: int说明:文件数量。

T1 自定义副显程序开发

【提示:在开发之前,请认真阅读文档中的内容,如有疑问可以联系商米技术支持咨询。】

注:插入usb调试线,会导致主副屏断开。

关于T1双屏

 

商米T1有两种双屏配置:

 

1. 主屏14寸,副屏7寸。

注:7寸副屏仅支持浏览,不支持触控,不支持安装app。用户如需要修改副屏界面,请参考内置副显程序对接文档

Ouk69hAZ0gIkhS99

2. 主屏14寸,副屏14寸,副屏可触摸。

2


详细的硬件说明,请查看官网介绍,设备主副屏运行的都是SUNMI OS系统,相互通过商米封装好的接口实现通信。

注:不要把sunmi的有关代码混淆,混淆可能造成组件无法工作

#sunmi

-keep class com.luedongtech.kr3000.sunmi.** {*;}

-keep class sunmi.ds.**{*;}

-keep class com.sunmi.**{*;}

-keep class sunmi.sc.**{*;}

-keep class com.google.gson.**{*;}

通常开发者的业务app运行在主屏,同时需要副屏显示清单信息、宣传图片,视频等内容,有时还需要实现简单的交互操作。开发者有两种方式使用T1副屏显示内容:

 

    1. 使用T1副屏系统内置的显示程序。只要主屏app遵照商米的规范,向副显程序发特定格式的数据就可让副显程序显示内容(开发成本低,推荐)。

   

    2. 开发者自己写副屏显示app(开发成本高,自由度高)。

 

虽然商米封装的副显程序能满足绝大部分的开发者对于副屏显示内容的需求,但是业务是多样的,商米始终秉持开放原则,支持开发者自己写副显程序。下面将对自己写副显程序做详细的说明。

  • 副显app的分发

我们规定,只要在您的主屏业务App的AndroidManifest.xml中添加一行配置(文档最后讲),业务App在通过应用市场安装到主屏的同时,也会在副屏上安装,也就是说,您的主屏App同时也是副屏App,这里需要您在代码中进行首页显示内容的控制 。

进入正题

 

自定义副显程序开发的核心问题是主副屏的通信,实现了主副屏通信后,您可以把副屏当成是普通的平板电脑开发相关的副屏app。这里有必要先了解一下双屏的通信方式,我们通过一张图片向您直观展示T1双屏的通信协议。

 

 

prototype1


T1的通信协议,从下到上依次包括:

 

    1. Driver层,该层是最底层的通信协议,开发者无需关注。

    2. Service层,该层是商米封装的一个通信服务,开发者也无需关注。

    3. SDK层,该层是T1自带的副显程序使用的通信接口,自定义的副显程序调用的也是这层的接口

    4. APP层,指的是开发者自己的业务app和内置的副显程序。

 

  • 如果使用的是T1内置副显程序,数据通信方式如上图所示,开发者的主屏业务App只要调用商米的SDK按照商米规定好的数据格式向副显发数据,剩下的交给系统处理即可。
  • 如果您自己开发副显程序,就要自己处理数据的收发,内容显示等动作,如果您没有强烈的自定义需求,我们建议您使用T1自带的副显程序显示内容,可以节约很多的人力,物力成本。

 

开始开发

我们给开发者准备了一个双屏通信的Demo,您可以下载副显程序开发资源,参照Demo中的代码实现您自己的副显app,请按照下面的流程部署该Demo:

 

    1. 将资源文件中的HCService.apk安装到模拟主副屏通信的两台设备上,资源中包含两个HCService的apk,请先安装release版本,如果安装失败请尝试安装unsigned版本的apk。


    2. 主副屏上分别运行这个程序,在第一台设备上输入自己的IP地址,勾选”作为主屏”,点击确定。


    3. 在另一台设备上输入主屏机器的IP地址,点击确定(不要勾选‘作为主屏’),可以看到屏幕中弹出toast提示“与主/副屏连接”,就代表主副屏能通信了,如果没有弹出提示,请在设置中的应用程序管理中找到HCService程序 (进入设置->应用->点击右上角的更多->点击显示系统进程,才能看到HCService),强制停止主副屏上的HCService服务,再重复上面的步骤试试。


    4. 将MyDSD项目导入到AndroidStudio中,如果报错了请检查您的编译环境的版本是否兼容demo,可以自己做相关的调整。注:我们不建议您使用eclipse开发副显程序,目前没有提供相关的eclipse资


    5. 这里请修改AndroidManifest.xml中的启动页面为MainScreenActivity,然后将项目部署到主屏设备中,运行。


    6. 再修改启动页面为ViceScreenActivity,然后将项目部署到副屏设备中,运行。


    7.在主屏上点击发送文字的按钮,查看副屏显示内容的变更,然后可以发送图片给副屏查看显示情况。


在这个Demo中包含了主副屏相互发送字符数据的方法,发送单个文件的方法和发送多个文件的方法。以下我们将基于Demo讲解主副屏通信的开发流程:

1. 在build.gradle中添加以下依赖:

dependencies {
    compile files('libs/commons-codec-1.9.jar')
    provided files('libs/framework.jar')
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile 'com.sunmi:DS_Lib:latest.release'
    compile 'com.google.code.gson:gson:2.6.2'
}
 
 

需要添加的权限:(强调:Sunmi OS是基于Android6.0定制,Android6.0+ 要求部分敏感权限需要动态申请)

 

还有一个广播接收器,注意,这个是固定的写法,不要做修改哦。

"sunmi.ds.MsgReceiver">
    
        "com.sunmi.hcservice" />
        "com.sunmi.hcservice.status" />
    

 

2. 初始化,您可以在Application中初始化SDK的代码,也可以在任何您想要的地方初始化:

private void initSDK() {
    mDSKernel = DSKernel.newInstance();
    mDSKernel.init(this, mConnCallback);
}

以上DSKernel类是SDK中的核心类,几乎所有双屏通信相关的方法都在这个类中。在初始化后需要添加两个监听类:

//添加主副屏连接状态的监听
mDSKernel.addConnCallback(new IConnectionCallback(){
                        @Override
                        public void onConnected(ConnState arg0) {
                        //连接上了回调
                        }

                        @Override
                        public void onDisConnect() {
                        //断开连接的回调
                        }
                        
                });

//添加接收到数据的回调                
mDSKernel.addReceiveCallback(new IReceiveCallback(){

                        @Override
                        public void onReceiveCMD(DSData arg0) {
                          //收到命令      
                        }

                        @Override
                        public void onReceiveData(DSData arg0) {
                           //收到数据
                        }

                        @Override
                        public void onReceiveFile(DSFile arg0) {
                           //收到单个文件
                        }

                        @Override
                        public void onReceiveFiles(DSFiles arg0) {
                           //收到多个文件
                        }
             
                        
                });   



以上我们完成了初始化,通信当然会分信息的发送和接收了,主副屏可以相互发送接收数据。可以看到在MyDSD里面,MainScreenActivity中包含很多发数据的方法,在ViewScreenActiivty中包含很多接收数据的方法。

所有的方法可以在DSKernel类中查看到,详情可以查看 T1双屏通信接口文档 ,以下我们将讲解部分接口的使用:

1.发送字符数据,副屏接收显示

DataPacket packet = UPacketFactory.buildShowText(DSKernel.getDSDPackageName(), "成功接收字符数据!",null);
mDSKernel.sendData(packet);//参数DataPacket是双屏通信数据打包类,请参照Demo生成该数据
 

接收的方法是在IReceiveCallback接口的onReceiveData(DSData data)中:

@Override
public void onReceiveData(DSData data) {
    Log.d(TAG, "获取到数据:" + data.data);//将接收到的数据打印出来
}


2.发送指令的方法:

String json = UPacketFactory.createJson(DataModel.QRCODE, "");
//三个参数:1.接收指令的副屏app的包名;2.要发送的指令,这里可以参照Demo;3.发送结果回调
mDSKernel.sendCMD(DSKernel.getDSDPackageName(), json.toString(), l,null);

 

接收指令的方法:

@Override
public void onReceiveCMD(DSData cmd) {
     Log.d(TAG, "获取到数据:" + cmd.data);//将接收到的数据打印出来
}
 

指令的使用场景举例:图片视频等的显示需要先将文件发送到副屏,副屏会返回一个文件的id给主屏,然后向副屏发送指令显示指定id的图片或视频。

3.发送单个文件的方法:

//该方法有三个参数:1.接收端app的包名;2.文件在本地存储中的路径;3.发送结果回调
mDSKernel.sendFile(PACKAGE_OF_VICE, Environment.getExternalStorageDirectory().toString()+"/"+videoInAsserts,
      new ISendCallback() {
         public void onSendSuccess(long l) {
            Log.i("sunmi", "这里表示发送成功" + l);
            showVideo(l);
         }

      
         public void onSendFail(int i, String s) {
            //tv_show_id.setText("fail:" + s);
            Log.i("sunmi", "---:" + s);
         }

         public void onSendProcess(long l, long l1) {
            //发送进度的方法
         }
      });

 

接收单个文件的方法,IReceiveCallback接口的onReceiveFile(DSFile file) 中通过调用FilesManager.saveFile(DSFile file)将文件保存在本地:

@Override
public void onReceiveFile(DSFile file) {
   Log.i(TAG,"接收到的单个文件的路径:"+file.path);
   Log.i(TAG,"接收到的单个文件的taskId:"+file.taskId);
    mFilesManager.saveFile(file);
}
 

4.发送多个文件的方法

mDSKernel.sendFiles(PACKAGE_OF_VICE, json.toString(), paths, new ISendFilesCallback(){
   @Override
   public void onAllSendSuccess(long l) {
     //所有文件发送成功
   }
   @Override
   public void onSendFaile(int arg0, String arg1) {}
   @Override
   public void onSendFileFaile(String arg0, int arg1, String arg2) {}
   @Override
   public void onSendProcess(String arg0, long arg1, long arg2) {}
   @Override
   public void onSendSuccess(String arg0, long arg1) {
   }
   
});

 

多个文件的接收方法:

@Override
public void onReceiveFiles(DSFiles dsFiles) {
            mFilesManager.saveFiles(dsFiles);
        }

 

5.启动指定应用的方法

 

参照Demo生成数据,向副屏发指令,该代码需要DSD程序的支持,可以在下载的资源文件中找到该apk,安装在副屏。

DataPacket dsPacket   = UPacketFactory.buildOpenApp(PACKAGE_OF_VICE, null);
//PACKAGE_OF_VICE为要启动的副屏指定应用的包名,如:com.sunmi.mydsd
mDSKernel.sendCMD(dsPacket);

 

以上介绍了一些基本接口的使用,更多的接口请参看DSKernel中的代码注释。

 

 

应用的发布

主副屏的应用都开发好了,当然是通过商米应用市场将该应用大规模分发出去了,上面我们讲了,只要在应用的AndroidManifest.xml中添加一行配置,该应用通过应用市场在主屏安装的时候,只要双屏通信畅通,就会在副屏上同时安装该应用(必须通过应用市场安装才能生效)。主屏和副屏程序是写在一个应用里的,所以需要您在入口类中添加相关的判断逻辑,这就是运行Demo时您需要修改启动页的原因,具体判断主副屏的代码可以参考Demo。




"sunmi_dual" android:value="open"/>