① android Deep Link 深度链接,看看你在第几层
简单来说,App 深度链接(Deep Link)是一项基础的 App 优化方法,通过技术手段缩短了用户操作路径,从而优化了产品服务的用户体验,最终帮助实现了转化率提升、用户增长等业务目标。
一键跳转是深度链接比较重要的使用场景,但它的能力不仅于此,主要包括以下几种:
这两个场景分别对应用户已安装 App 和未安装 App 的两种情况,在此基础上, 还可以衍生出其他一些业务化的场景:
在深度链接的工作流程需要 Wap 端、客户端和服务端协同配合,整体的数据流转示意图如下:
在用户已安装 App 的情况,可以通过标准的协议实现一键拉起 App 并传递深度链接参数,目前主要有以下三种协议:
这里我们主要介绍 Android 端的实现,主要分为以下几个步骤:
自定义 Scheme 协议本质上就是定义一套标识 App 行为的规则,实践中采用的 URI(Uniform Resource Identifier,统一资源标识符) 方案,下图是 URI 的通用格式:
实践中的设计过程多少会带点 Restful API 的风格。Restful 本身是接口命名的一种规范,用 URI 标识一种资源,再用 HTTP 方法来定义对资源的操作。比如定义 /goods/{goodsId} 是商品的路径,那么对于商品这个资源的操作可以分为以下几种:
把 Restful API 这套理论带到 App 这边,是不是也适用呢?比如以下行为是不是也可以用 Restful API 的风格表示:
既然在 App 端对资源的访问行为只有 GET,那么就可以省略掉 GET 这个元素。再考虑到链接需要跨平台,还有多参数等因素,链接模板需要再进一步改进。一般推荐采用这种格式的 URI: scheme://host/path?query 。 例如,链接 xiaopeng://www.myapp.com/goods/?goodsId=123456&size=1 打开商品详情页,并且选择 size=1 的规格。
这里需要注意下几个细节:
在 PC 端,浏览器是用户流量的主要入口,但在移动端,用户的流量(使用时间)被分散到大大小小的 APP 上,而不再是浏览器。用户感兴趣的内容分散在各个 APP 里,当用户想在 APP 上找到某个感兴趣的页面时,深度链接(Deeplink)是一个可以从任何地方将用户带到应用内容页的简单方式。你用起来了吗?
② Android页面跳转协议_URL Scheme详解
android中的scheme是一种页面内跳转协议,是一种非常好的实现机制,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面;通过scheme协议,服务器可以定制化告诉App跳转那个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转页面等。
客户端应用可以在服务端注册一个URL Scheme,该Scheme用于从浏览器或其他应用启动本应用。通过指定的URL字段,可以让应用在被调起后直接打开某些特定界面,比如商品详情页,活动详情页等。也可以执行某些特定的动作,如完成支付等。也可以在应用内通过html页来直接调用显示app内的某个界面。综上URL Schema使用场景大致分以下几种:
一个完整的Scheme的协议格式由 scheme、userInfo、host、port、path、query和fragment 组成。结构如下:
scheme://是固定的格式。userInfo@ 可以省略,host 是必须的。port 、query 和 fragment 也是可以省略的。
其中scheme既可以是Android已经定义好的协议,也可使用我们自定义的。Android 常见的scheme 协议有:content 、file、http 等。如果我们自定义协议就可以随意使用一些字符串来限定协议。当然最好是有一定含义的字符串。如下面的协议:
首先配置需要跳转的Activity,Mainifest文件配置如下:
SchemeActivity
在网页中调用:
运行结果如下:
其他运用方式都基于样例,源码地址: URL_SchemeDemo
③ Android socket通信协议的封装和解析
android socket通信协议的封装和解析,其实是和java一样的,都是通过http中的相关知识来封装和解析,主要是通过多次握手,如下代码:
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
importjava.io.PrintWriter;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassMain{
privatestaticfinalintPORT=9999;
privateList<Socket>mList=newArrayList<Socket>();
privateServerSocketserver=null;
=null;//threadpool
publicstaticvoidmain(String[]args){
newMain();
}
publicMain(){
try{
server=newServerSocket(PORT);
mExecutorService=Executors.newCachedThreadPool();//createathreadpool
System.out.println("服务器已启动...");
Socketclient=null;
while(true){
client=server.accept();
//把客户端放入客户端集合中
mList.add(client);
mExecutorService.execute(newService(client));//
}
}catch(Exceptione){
e.printStackTrace();
}
}
{
privateSocketsocket;
privateBufferedReaderin=null;
privateStringmsg="";
publicService(Socketsocket){
this.socket=socket;
try{
in=newBufferedReader(newInputStreamReader(socket.getInputStream()));
//客户端只要一连到服务器,便向客户端发送下面的信息。
msg="服务器地址:"+this.socket.getInetAddress()+"cometoal:"
+mList.size()+"(服务器发送)";
this.sendmsg();
}catch(IOExceptione){
e.printStackTrace();
}
}
@Override
publicvoidrun(){
try{
while(true){
if((msg=in.readLine())!=null){
//当客户端发送的信息为:exit时,关闭连接
if(msg.equals("exit")){
System.out.println("ssssssss");
mList.remove(socket);
in.close();
msg="user:"+socket.getInetAddress()
+"exittotal:"+mList.size();
socket.close();
this.sendmsg();
break;
//接收客户端发过来的信息msg,然后发送给客户端。
}else{
msg=socket.getInetAddress()+":"+msg+"(服务器发送)";
this.sendmsg();
}
}
}
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*循环遍历客户端集合,给每个客户端都发送信息。
*/
publicvoidsendmsg(){
System.out.println(msg);
intnum=mList.size();
for(intindex=0;index<num;index++){
SocketmSocket=mList.get(index);
PrintWriterpout=null;
try{
pout=newPrintWriter(newBufferedWriter(
newOutputStreamWriter(mSocket.getOutputStream())),true);
pout.println(msg);
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}