Quikapp快應用開發入門

快應誕生背景

微信的小程序使得不少原來須要調動APP的場景不復存在,正式因爲微信小程序的衝擊,3月20日,華爲聯手九大手機廠商,共同舉辦了「快應用」標準啓動發佈會。「快應用」是幾家手機廠商基於硬件平臺共同推出的新型應用生態,用戶沒必要下載安裝,即點即用,可以享受到原生應用的性能體驗。「快應用」使用前端技術棧開發與原生渲染,兼具H5頁面和原生應用的雙重優勢。javascript

快應用使用場景

進入小米應用商店,搜索「餓了麼」:html

點擊「秒開」就可使用快應用了前端

在華爲應用市場搜索「快應用」:java

點擊查看更多:node

能夠看到一些快應用app已經上線了,使用起來體驗也不錯,體積也至關小webpack

微信小程序VS快應用

微信小程序推出後,儘管前期受到了很多質疑,但卻一直髮展很是穩健。騰訊3月21日剛剛公佈的2017年整年財報中披露,自2017年1月推出小程序以來,截至2018年1月已推出58萬個小程序,日活躍帳戶超過1.7億個。張小龍也曾經表示,將來兩年內,小程序將取代80%的應用市場。若是該目標達成,這意味着微信小程序創建起一個強大的超級生態,極大擠壓了國產手機廠商應用分發和數字廣告業務的成長空間。所以,國產手機廠商的「快應用」主要針對微信小程序,與後者爭搶用戶和流量。web

那麼快應用要和微信小程序去競爭,它們各自又有什麼優缺點,誰又會更佔優點呢?我我的總結以後列出了以下幾點:正則表達式

微信小程序shell

優勢:npm

  • 微信小程序已經在市場上取得了必定的規模效益,搶佔了市場先機
  • 微信自帶用戶流量,用戶黏度較高,經過微信打開小程序很是方便
  • 微信小程序支持iOS和安卓兩大操做系統,覆蓋了全部的用戶羣體,不一樣操做系統用戶之間數據共享方便,好比iOS用戶能夠經過一個微信連接響安卓用戶發送一個微信小程序連接

缺點:

  • 微信小程序基於系統上層進行的封裝,在性能上和原生app差距較大

快應用

優勢:

  • 基於系統層開發,將腳本轉化爲原生組件,運行效率更接近原聲app,用戶體驗會更加好

缺點:

  • 只支持安卓系統,在用戶羣體上受到限制,也沒法在安卓和iOS系統之間作到數據共享
  • 幾大廠商合做,可能會產生分歧,如何去協調各大廠商,以及後期的利益分配等是一個大問題
  • 缺少用戶粘性和使用場景,若是每次打開其餘應用都要去應用商店搜索快應用app的話顯然不如微信小程序方便

總結:

從快應用的誕生,咱們可以看到國內手機硬件廠商開始反思本身在安卓生態中的地位,尋求轉型和突破以爭取更大的話語權和利益。這個方向顯然是對的,可是對比微信小程序,較好的性能幾乎成了快應用的惟一優點,可是隨着如今手機性能不斷加強以及微信小程序的不斷優化,這個問題將變得忽略不計,何況如今不少微信小程序用戶流暢度意境作的至關不錯了,而在用戶羣體、使用方便性等幾大方面,微信小程序佔據着絕對優點,並且快應用因爲自生的缺陷沒法彌補這幾方面的劣勢,因此說快應用幾乎沒法撼動微信小程序的地位,更不用說戰勝小程序,不過若是快應用可以在應用分發市場上對微信造成必定威脅而且從中分得一杯羹的話,那也可以證實快應用取得了成功。

環境配置

6.0版本以上NodeJS,官方推薦 v6.11.3 LTS

安裝hap-toolkit:npm install -g hap-toolkit(幫助開發者經過命令行工具來完成工程的建立等工做),在命令行中執行hap -V會輸出版本信息表示hap-toolkit安裝成功,以下命令所示:

    hap -V

建立項目

建好環境後,開發者就能夠利用全局hap命令建立一個項目模板,以下所示,其中<ProjectName>爲自定義的項目名稱

hap init <ProjectName>

命令執行後,會在當前目錄下建立<ProjectName>文件夾,並做爲項目根目錄

這個項目已經包含了項目配置與簡單頁面的初始代碼,項目根目錄結構以下:

├── node_modules
├── sign                      rpk包簽名模塊
│   └── debug                 調試環境
│       ├── certificate.pem   證書文件
│       └── private.pem       私鑰文件
├── src
│   ├── Common                公用的資源文件和組件文件
│   │   └── logo.png          manifest.json中配置的icon
│   ├── Demo                  頁面目錄
│   |   └── index.ux          頁面文件,文件名沒必要與父文件夾相同
│   ├── app.ux                APP文件(用於包括公用資源)
│   └── manifest.json         項目配置文件(如:應用描述、接口申明、頁面路由等)
└── package.json              定義項目須要的各類模塊及配置信息,npm install根據這個配置文件,自動下載所需的運行和開發環境

目錄的簡要說明以下:

  • src:項目源文件夾
  • node_modules:項目的依賴類庫
  • sign:簽名模塊,當前僅有debug簽名,若是內測上線,請添加release文件夾,增長線上簽名;簽名生成方法請參考文檔:編譯工具openssl

編譯項目

安裝npm依賴

在項目根目錄下,運行以下命令安裝依賴包(webpack,babel等)

npm install

編譯項目

在項目的根目錄下,運行以下命令進行編譯打包,生成rpk包

npm run build

編譯打包成功後,項目根目錄下會生成文件夾:build、dist

  • build:臨時產出,包含編譯後的頁面js,圖片等
  • dist:最終產出,包含rpk文件。實際上是將build目錄下的資源打包壓縮爲一個文件,後綴名爲rpk,這個rpk文件就是項目編譯後的最終產出

自動從新編譯

若是但願每次修改源代碼文件後,都自動從新編譯項目,請使用以下命令:

npm run watch

手機安裝調試器

調試器APK是一個Android應用程序,請從站點地址下載

說明以下:

  • 掃碼安裝:配置HTTP服務器地址,下載rpk包,並喚起平臺運行rpk包
  • 本地安裝:選擇手機文件系統中的rpk包,並喚起平臺運行rpk包
  • 在線更新:從新發送HTTP請求,更新rpk包,並喚起平臺運行rpk包
  • 開始調試:喚起平臺運行rpk包,並啓動遠程調試工具

注意:若沒法正常使用調試器,請升級手機系統到最新版本或安裝平臺預覽版

手機安裝平臺預覽版

較新的系統版本中內置平臺正式版,即真實的運行環境。然而,更新平臺正式版的時間週期較長,開發調試平臺新功能可以使用平臺預覽版

平臺預覽版存在如下優缺點:

  • 優勢:迭代速度快,可當即體驗平臺新功能
  • 缺點:實現與真實的運行環境存在差別,對廠商服務和第三方服務的支持存在缺陷

平臺預覽版APK是一個Android應用程序,請從站點地址下載

下載安裝成功後,在調試器中點擊切換運行平臺至...mockup便可在平臺預覽版上運行rpk包

在平臺上運行rpk包

在調試器中喚起平臺打開rpk包有多種途徑,如下二者選其一便可,推薦第一種途徑:

  • HTTP請求:開發者啓動HTTP服務器,打開調試器,點擊掃碼安裝配置HTTP服務器地址,下載rpk包,並喚起平臺運行rpk包
  • 本地安裝:開發者將rpk包拷貝到手機文件系統,打開調試器,點擊本地安裝選擇rpk包,並喚起平臺運行rpk包

1. HTTP請求

啓動HTTP服務器

在終端中新建一個窗口,進入項目的根目錄運行以下命令,啓動本地服務器(默認端口爲12306)

npm run server

自定義端口(如:8080)

npm run server -- --port 8080

在手機上預覽運行效果

配置HTTP服務器地址有兩種方式,如下二者選其一便可:

  • 打開調試器 --> 點擊"掃碼安裝",掃描終端窗口中的二維碼便可完成配置(若掃描不成功,可在瀏覽器中打開頁面:http://localhost:<your port>,掃描頁面中的二維碼)
  • 打開調試器 --> 點擊右上角menu --> 設置,輸入終端窗口中提示的HTTP服務器地址

配置完成後,若沒有自動喚起平臺運行rpk包,點擊在線更新喚起平臺運行rpk包

若提示安裝失敗,請檢查執行npm run server的終端窗口是否正常運行

2. 本地安裝

複製rpk包到手機中

<ProjectName>/dist目錄下編譯產出的rpk包經過USB數據線或其餘方式,複製到手機文件系統中

本地安裝rpk包

打開調試器 --> 點擊"本地安裝",選擇手機文件系統中的rpk包,並自動喚起平臺運行rpk包,查看效果

配置應用基本信息

每一個應用都要有專屬的名稱,圖標等,這些信息都須要在manifest.json文件中配置;詳細信息請參考文檔:manifest文件

應用包名(package)

應用包名,是區別於其餘應用的惟一標識

推薦採用com.company.module的格式,示例以下:

{
  "package": "com.example.demo" } 

應用名稱(name)

應用名稱,6個漢字之內,與應用商店保存的名稱一致;框架提供保存到桌面的功能,桌面上顯示的應用名即爲此屬性

示例以下:

{
  "name": "發票小助手" } 

應用圖標(icon)

規則爲正方形(不能是圓角),且務必無白邊

{
  "icon": "/Common/logo.png" } 

注意:

請使用絕對路徑,其中/對應於路徑<ProjectName>/src/

應用版本名稱、版本號(versionName、versionCode)

應用版本名稱、版本號爲開發者的應用包維護的版本信息

應用版本名稱爲主版本.次版本格式

應用版本號爲整數,從1開始,每次更新上架請自增1

示例以下:

{
  "versionName": "1.0", "versionCode": 1 } 

支持的最小平臺版本號(minPlatformVersion)

支持的最小平臺版本號爲必填項,默認值爲1000,標識開發者的rpk包兼容支持的最小運行平臺版本

當使用了1000以上的平臺版本新增特性時,就必須確保minPlatformVersion最低爲該平臺版本號,避免上線後在更低版本平臺上運行出錯

示例以下:

{
  "minPlatformVersion": "1000" } 

配置接口列表(features)

在使用接口時,須要先在manifest中聲明接口。在每一個接口文檔的頂部,都附有聲明接口的配置代碼

以fetch網絡請求爲例,示例以下:

{
  "features": [ { "name": "system.fetch" } ] } 

配置頁面路由(router)

路由,用於定義頁面的實際地址、跳轉地址。若是ux頁面沒有配置路由,則不參與項目編譯。一個目錄下最多隻能存在一個主頁面文件(不包括組件文件)

首頁名稱(router.entry)

首頁,即應用平臺啓動時默認打開的頁面。首頁需配置爲應用中某頁面的名稱,即在<ProjectName>/src目錄下,頁面目錄的相對路徑

示例以下:

假設工程根目錄以下所示

└── src
    └── Demo                  頁面目錄,存放各自頁面私有的資源文件和組件文件
        └── index.ux          頁面文件,文件名沒必要與父文件夾相同(推薦index.ux)

假設首頁爲Demo目錄下的index.ux文件,則首頁對應的頁面名稱爲Demo

{
  "router": { "entry": "Demo" } } 

頁面路由對象(router.pages)

頁面路由對象,key爲頁面名稱(<ProjectName>/src目錄下,頁面目錄的相對路徑),value爲頁面具體路由配置,key不要重複

頁面具體路由配置(router.pages的value)包括如下屬性:

  • component:頁面對應的ux文件名
  • path:頁面路徑,不填則默認爲頁面名稱(<ProjectName>/src目錄下,頁面目錄的相對路徑)

示例以下:

假設工程根目錄以下所示

└── src
    |── Demo                  頁面目錄,存放各自頁面私有的資源文件和組件文件
    |   └── index.ux         頁面文件,文件名沒必要與父文件夾相同(推薦index.ux)
    └── Doc
        └── Layout            頁面目錄,存放各自頁面私有的資源文件和組件文件
            └── index.ux     頁面文件,文件名沒必要與父文件夾相同(推薦index.ux)

當頁面名稱(router.pages的key)爲Demo時,對應的頁面配置(router.pages的value)包括:

  • component:頁面對應的ux文件名index
  • path:頁面路徑,默認爲頁面名稱Demo
{
  "router": { "pages": { "Demo": { "component": "index" }, "Doc/Layout": { "component": "index" } } } } 

如今,開發者就能夠經過/Demo訪問到Demo目錄下的index.ux頁面了

配置頁面UI顯示(display)

UI顯示,用於定義與UI顯示相關的配置。支持定義:頁面公用的默認UI顯示、頁面私有的UI顯示

頁面公用的默認UI顯示

頁面公用的默認UI顯示,即被全部頁面共享

以標題欄文字的配置爲例:

{
  "display": { "titleBarText": "頁面公用的默認標題" } } 

未配置私有標題的頁面,標題欄文字均將顯示爲頁面公用的默認標題

頁面私有的UI顯示

頁面私有的UI顯示,在display.pages對象下配置:key爲頁面名稱(與路由中的頁面名稱保持一致),value爲頁面私有的UI顯示

以標題欄文字的配置爲例:

{
  "display": { "pages": { "Demo": { "titleBarText": "Demo頁面的標題" } } } }

manifest文件

manifest.json文件中包含了應用描述、接口聲明、頁面路由信息

manifest

屬性
類型
默認值
必填
描述
package String - 應用包名,確認與原生應用的包名不一致,推薦採用com.company.module的格式,如:com.example.demo
name String - 應用名稱,6個漢字之內,與應用商店保存的名稱一致,用於在桌面圖標、彈窗等處顯示應用名稱
icon String - 應用圖標,提供192x192大小的便可
versionName String - 應用版本名稱,如:"1.0"
versionCode Integer - 應用版本號,從1自增,推薦每次從新上傳包時versionCode+1
minPlatformVersion Integer 1000 支持的最小平臺版本號,原理同Android API Level,兼容性檢查,避免上線後在低版本平臺運行並致使不兼容
features Array - 接口列表,絕大部分接口都須要在這裏聲明,不然不能調用,詳見每一個接口的文檔說明
config Object - 系統配置信息,詳見下面說明
router Object - 路由信息,詳見下面說明
display Object - UI顯示相關配置,詳見下面說明

config

用於定義系統配置和全局數據。

屬性
類型
默認值
描述
logLevel String log 打印日誌等級,分爲off,error,warn,info,log,debug
designWidth Integer 750 頁面設計基準寬度,根據實際設備寬度來縮放元素大小
data Object - 全局數據對象,屬性名不能以$或_開頭,在頁面中可經過this進行訪問;若是全局數據屬性與頁面中data屬性重名,則頁面初始化時,全局數據會覆蓋頁面中對應的屬性值

router

用於定義頁面的組成和相關配置信息,若是頁面沒有配置路由信息,則在編譯打包時跳過。

屬性
類型
默認值
描述
entry String - 首頁名稱
pages Object - 頁面配置列表,key值爲頁面名稱(對應頁面目錄名,例如Hello對應'Hello'目錄),value爲頁面詳細配置page,詳見下面說明

router.page

用於定義單個頁面路由信息。

屬性
類型
默認值
必填
描述
component String - 頁面對應的組件名,與ux文件名保持一致,例如'hello' 對應 'hello.ux'
path String /<頁面名稱> 頁面路徑,例如「/user」,不填則默認爲/<頁面名稱>。
path必須惟一,不能和其餘page的path相同。
下面page的path由於缺失,會被設置爲「/Index」:
"Index": {"component": "index"}
filter Object - 聲明頁面能夠處理某種請求

router.page.filter

聲明頁面能夠處理某種請求,頁面能夠從$page獲取打開頁面的參數,參見script腳本。filter的結構以下:

"filter": { "<action>": { "uri": "<pattern>" } } 
屬性
類型
默認值
必填
描述
action String - 請求的動做,目前僅支持view這一種
uri Pattern - 請求的數據的匹配規則。必須是正則表達式。如https?://.*能夠匹配全部http和https類型的網址

能夠處理全部http和https請求的filter定義以下:

"filter": { "view": { "uri": "https?://.*" } } 

display

用於定義與UI顯示相關的配置。

屬性
類型
默認值
描述
backgroundColor String #ffffff 窗口背景顏色
fullScreen Boolean false 是不是全屏模式,默認不會同時做用於titleBar,titleBar須要繼續經過titleBar控制
titleBar Boolean true 是否顯示titleBar
titleBarBackgroundColor String - 標題欄背景色
titleBarTextColor String - 標題欄文字顏色
titleBarText String - 標題欄文字(也可經過頁面跳轉傳遞參數(titleBarText)設置)
menu Boolean false 是否顯示標題欄右上角菜單按鈕
pages Object - 各個頁面的顯示樣式,key爲頁面名(與路由中的頁面名保持一致),value爲窗口顯示樣式,頁面樣式覆蓋default樣式。

示例:

{
  "package": "com.company.unit", "name": "appName", "icon": "/Common/icon.png", "versionName": "1.0", "versionCode": 1, "minPlatformVersion": 1000, "features": [ { "name": "system.network" } ], "permissions": [ { "origin": "*" } ], "config": { "logLevel": "off" }, "router": { "entry": "Hello", "pages": { "Hello": { "component": "hello", "path": "/", "filter": { "view": { "uri": "https?://.*" } } } } }, "display": { "backgroundColor": "#ffffff", "fullScreen": false, "titleBar": true, "titleBarBackgroundColor": "#000000", "titleBarTextColor": "#fffff", "pages": { "Hello": { "backgroundColor": "#eeeeee", "fullScreen": true, "titleBarBackgroundColor": "#0000ff", "titleBarText": "Hello" } } } }

 

源碼文件

APP,頁面和自定義組件均經過ux文件編寫,ux文件由template模板style樣式script腳本3個部分組成

app.ux

當前app.ux編譯後會包含manifest配置信息(能夠在npm run build以後查看文件內容),因此請不要刪除/**manifest**/的註釋內容標識。

您能夠在<script>中引入一些公共的腳本,並暴露在當前app的對象上,以下所示,而後就能夠在頁面ux文件的ViewModel中,經過this.$app.util訪問

<script> import util from './util.js' 
module.exports = { /**manifest**/, util: util }
</script>
頁面路由
導入模塊 import router from '@system.router' 或 var router = require("@system.router")

接口定義

router.push(OBJECT)

跳轉到應用內的某個頁面

參數:

參數
類型
必填
說明
uri String 要跳轉到的uri,能夠是下面的格式:
  1. 包含schema的完整uri;目前支持的schema有tel,sms和mailto,例如tel:10086。
  2. 以‘/’開頭的應用內頁面的路徑;例:/about。
  3. 以非‘/’開頭的應用內頁面的名稱;例:About。
  4. 特殊的,若是uri的值是"/",則跳轉到path爲"/"的頁,沒有則跳轉到首頁
支持包含schema的完整uri。對於帶有schema的uri,處理流程以下:
  1. 查找app下全部page的filter設置來選擇合適的page處理請求(參見[manifest文件](../../framework/manifest.md))
  2. 若是沒有合適的page可以處理請求,會使用默認策略來處理請求。目前默認策略支持對http、https、internal這幾種schema的處理
  3. 若是默認策略也不能處理請求,會嘗試使用系統中的應用來處理請求
  4. 若是沒有系統應用能夠處理請求,會拋棄請求
默認策略的處理邏輯:
  1. 若是schema是http/https,會用內置的web頁面打開網頁
  2. 若是schema是internal(參見[文件組織](../../framework/file-organization.md)),會根據uri的文件擴展名來肯定文件類型,再調用系統中的應用打開文件
params Object 跳轉時須要傳遞的數據,參數能夠在頁面中經過this.param1的方式使用,param1爲json中的參數名,param1對應的值會統一轉換爲String類型

示例:

// launch phone app router.push({ uri: 'tel:10086' }); // open page by path router.push({ uri: '/about', params: {testId:'1'} }); // open page by name router.push({ uri: 'About', params: {testId:'1'} }); // open web page router.push({ uri: 'http://www.example.com' }); // install apk router.push({ uri: 'internal://cache/example.apk' }); 

router.replace(OBJECT)

跳轉到應用內的某個頁面,當前頁面沒法返回

參數:

參數
類型
必填
說明
uri String 要跳轉到的uri,能夠是下面的格式:
  1. 以"/"開頭的應用內頁面的路徑;例:/about。
  2. 以非"/"開頭的應用內頁面的名稱;例:About。
  3. 特殊的,若是uri的值是"/",則跳轉到path爲"/"的頁,沒有則跳轉到首頁
params Object 跳轉時須要傳遞的數據,參數能夠在頁面中經過this.param1的方式使用,param1爲json中的參數名,param1對應的值會統一轉換爲String類型

示例:

router.replace({
  uri: '/test' params: {testId:'1'} }) 

router.back()

返回上一頁面

參數:

示例:

// A頁面 router.push({ uri: 'B' }) // B頁面 router.push({ uri: 'C' }) // C頁面經過back,將返回B頁面 router.back(); // B頁面經過back,將返回A頁面 router.back(); 

router.clear()

清空全部歷史頁面記錄,僅保留當前頁面

參數:

示例:

router.clear()

router.getLength()

獲取當前頁面棧的頁面數量

返回值:

類型
說明
Number 頁面數量

示例:

var length= router.getLength() console.log("pages' length = "length); 

router.getState()

獲取當前頁面狀態

返回參數:

參數名
類型
說明
index Number 當前頁面在頁面棧中的位置
name String 當前頁面的名稱
path String 當前頁面的路徑

示例:

var page = router.getState() console.log("page index = "+page.index); console.log("page name = "+page.name); console.log("page path = "+page.path);

快應用技術架構

快應用經過腳原本編寫組件,安卓內部嵌入一個腳本解析引擎,將腳本轉化爲原生控件,經過編譯生成rpk文件,應用調試器聯繫起腳本及安卓系統進行調試工做,具體流程圖以下:

參考資料

相關文章
相關標籤/搜索