Quikapp快應用開發入門


快應誕生背景

微信的小程序使得很多原來需要調動APP的場景不復存在,正式由於微信小程序的沖擊,3月20日,華為聯手九大手機廠商,共同舉辦了“快應用”標准啟動發布會。“快應用”是幾家手機廠商基於硬件平台共同推出的新型應用生態,用戶不必下載安裝,即點即用,能夠享受到原生應用的性能體驗。“快應用”使用前端技術棧開發與原生渲染,兼具H5頁面和原生應用的雙重優點。

快應用使用場景

進入小米應用商店,搜索“餓了么”:

點擊“秒開”就可以使用快應用了

在華為應用市場搜索“快應用”:

點擊查看更多:

可以看到一些快應用app已經上線了,使用起來體驗也不錯,體積也相當小

微信小程序VS快應用

微信小程序推出后,盡管前期受到了不少質疑,但卻一直發展非常穩健。騰訊3月21日剛剛公布的2017年全年財報中披露,自2017年1月推出小程序以來,截至2018年1月已推出58萬個小程序,日活躍賬戶超過1.7億個。張小龍也曾經表示,未來兩年內,小程序將取代80%的應用市場。如果該目標達成,這意味着微信小程序建立起一個強大的超級生態,極大擠壓了國產手機廠商應用分發和數字廣告業務的成長空間。因此,國產手機廠商的“快應用”主要針對微信小程序,與后者爭搶用戶和流量。

那么快應用要和微信小程序去競爭,它們各自又有什么優缺點,誰又會更占優勢呢?我個人總結之后列出了如下幾點:

微信小程序

優點:

  • 微信小程序已經在市場上取得了一定的規模效益,搶占了市場先機
  • 微信自帶用戶流量,用戶黏度較高,通過微信打開小程序非常方便
  • 微信小程序支持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文件,應用調試器聯系起腳本及安卓系統進行調試工作,具體流程圖如下:

參考資料

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM