① 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();
}
}
}
}
}