PHP、Android、iOS 的恩恩怨怨

黃總發表於2016-03-09

其實應該更多的是互相的磨合與學習,希望身邊的人可以有自己的經驗分享,與理解,互相進步才是大家需要的,作為一個 “年老” (我也是90後) 的開發者,我覺得一代勝一代,未來才有勝算。額,好了,我不充當老師的角色了,去正題。

1. 安卓中 a 標籤的坑

在和客戶端互動的過程中,往往都有跳轉的,而在我們們 Web 開發中,預設的 href 屬性通常是 #,然後通過獲取標籤繫結動作觸發事件,這裡有個坑,在與安卓互動過程中會發現。

<a href="#">click me</a>
// include zepto or jquery or other.
$(function () {
    $(`a`).on(`tap, click`, function () {
        alert(`test`);
        return false;
    });
});

上述程式碼中,會引起安卓互動中的一個坑,就是沒點選一次,安卓都會在計數器上+1, 也就是,點選第一次,彈一次窗,點選第二次,會彈兩次窗,如此類推。

解決方法:

<a href="javascript:void(0);">click me</a>

Fxied!!

2. 安卓中互動的坑

我丟,安卓這個坑爹,在 js 互動中,無法傳遞物件,匿名函式等等的型別。也就是說,如果你的引數是接受一個物件的,你必須將她轉成 String,而且安卓中的返回值也是隻能返回 String,在我們們接受之後需要將字串轉換成物件。

簡單 判斷客戶端型別的:

isiOS: function () {
     if (this.ua.match(/android/i) == "android") {
         return false;
     }
     return true;
 },
 isAndroid: function () {
     if (this.ua.match(/android/i) == "android") {
         return true;
     }
     return false;
 }

解決方法:

encode: function (data) {
     if ("" == data) {
         return {};
     }
     return JSON.stringify(data).replace(/"/g, ```);
 },
 decode: function (data) {
     if ("" == data) {
         return "{}";
     }
     return JSON.parse(data.replace(/`/ig,`"`));
 }

在呼叫 iOS 或者 android 的時候,先將引數傳遞到 encode 處進行過濾。

3. 判斷頁面是否在應用內開啟

其實這個很簡單,經常做 web 開發的都應該知道,我們們每天都與 Http 協議打交道,而在 Http 中,有一個很重的的標識,就是 User-Agent,簡稱 UA,其實這個東西就像我們們的門票一樣,有著各種的資訊在上面,其實就包括了很多的瀏覽器核心資訊,版本資訊,廠商等等……我們們就是從這個地方入手,在客戶端中定義自己的版本資訊,與微信一樣。從此告別什麼 url 上加什麼破引數啊什麼的。

以我的經驗來設計的話,一般按照這個格式:

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5 {company} {appname} [{type}]/{version}

如: 騰訊,微信 [海外版本] 6.0.0

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5 Tencent MicroMessager oversase/6.0.0

因為此處我還沒太多接觸客戶端開發,暫時沒有客戶端程式碼演示.

us: window.navigator.userAgent.toLowerCase(),
is: function (name) {
    return tools.ua.match(eval("/" + name + "/i")) == name ? true : false;
}

Examples:

if (/* Is app inside */) {
    /* Operation */
} else {
    /* Is app outside */
    /* Operation */
}

Combine: In wechat

if (/* In wechat app */) {
    /* open share guide */
} else {
    if (/* In app */) {
        if (/* Is iOS */) {
            /* share iOS sdk */
        } else {
            /* share android sdk */
        }
    } else {
        /* share operation */
    }
}

4. 請善用你的 Http Status Code

曾幾何時,我也是一個懵懂無知的騷年,連線口是幹嘛用的都不知道,大概也在 2014/8 月份左右,我對介面都是一種很敬畏的眼光去看待,直到現在,2016年,我更加視介面是一切資料庫的來源,其價值是最至高無上的。但是由我接觸介面(Application Programing Interface)開發之後,我發現目前的介面有好多問題,一個很明顯的就是,為啥每個介面都是 200,不應該啊,那非 200 響應的應該怎麼辦?有做處理嗎?
直到後來,我推翻了這一現象,也說服了各方的人。我舉一個 Ajax 的例子:

首先我先問一個問題,為何 jquery 和 zepto 的 ajax 中,都有一個 error 回撥?

$.ajax({
    // some code
    success: function () {},
    error: function () {}
});

請不要懷疑設計者的智商與知識,我猜他應該會比你聰明以及牛叉。這麼做,肯定有原因的。其實這裡的 error 就是為了讓非 2xx 狀態的時候進入的操作的。

如示例:

{
    status: 1
    content: {}
}

以上例子本身沒有錯誤,僅以自己看法對上述進行評述

其實我們們應該要善用本身已經有的東西,不需要再重新造多一個,吃力不討好,那你們就開始好好補一補 Http Status code 相關的知識吧。

示例:

Request Method:GET
Status Code:200 OK

200 一般都是成功響應,
3xx
4xx
5xx

根據不同的狀態碼進行不同的處理機制,無需重複再做這一步驟了,其實設計者也很清晰設計出狀態碼的意義,應該善用。

5. 判斷應用是否安裝,如果安裝,則開啟,否則則跳去下載

其實這個有點無理取鬧,但是又不得不去做,首先這個其實原理也是挺繞的

  1. 利用iframe嘗試開啟自定義scheme

  2. 跳轉到下載地址

只是那個判斷……

其實我是建議這些操作統一由一個地方去做,比如定義一個域名叫: down.xxx.com/應用id,後臺讀取應用id 相信資訊,統一由一處轉發。

function open () {
    var ifr = document.createElement(`iframe`);
   ifr.src = url;
   ifr.style.display = `none`;
   document.body.appendChild(ifr);
   window.setTimeout(function(){
       document.body.removeChild(ifr);
   }, 3000);
}

注意 iOS9 對這個有點不相容,所以,謹慎,iOS7,iOS8,安卓均可以實現

獲取版本資訊:

var getVersion = function () {
  if (tools.client.isAndroid()) {
      return parseFloat(tools.ua.match(/Androids(.*?);/i)[1]);
  }

  return parseFloat(tools.ua.match(/OSs(.*?)slike/i)[1].split(`_`).join(`.`));
};

這裡需要判斷系統型別及版本:

if (/* iOS */) {
    if (/* iOS version less than 9.0 */) {
        /* try open scheme */
        /* redirect download link */
    } else {
        /* other operate */
    }
} else {
    /* try open url */
    /* redirect download link */
}

所以,由此可見其實這裡的判斷會很多,很多,很多。所以我牆裂建議都統一到一個地方做分發。

這裡其實還需要判斷是否微信,是否應用內開啟,是否是分享出去的。

結合第 3 點的例子想想,這裡的 if …… 其實還是很恐怖的,我已經無路可退了……

相關文章