歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> SL4A 之實現原理解析

SL4A 之實現原理解析

日期:2017/3/1 9:48:35   编辑:Linux編程

關於SL4A的簡介和在Android系統的安裝及使用,請參考我的上一篇博文《Android 腳本設計之 SL4A》,本篇來分析其內部的實現機制。

深入理解SL4A

SL4A架構實現了本地腳本和原生態Android程序的內部消息通信,所以任何本地腳本語言,只要實現了這套兼容的JSON RPC通信接口,就可以呼叫SL4A的RPC Server端程序。至於為什麼要選用JSON,及這種格式的優點和特征,此處就不詳細敘述了,大家可以查看JSON官網。

“JavaScript Object Notation (JSON) is a lightweight, text-based,
language-independent data interchange format. It was derived from the
ECMAScript Programming Language Standard. JSON defines a small
set of formatting rules for the portable representation of structured data.
JSON can represent four primitive types (strings, numbers, booleans,
and null) and two structured types (objects and arrays).”

SL4A總體架構

從上圖可以看出,SL4A總體包括Client和Server兩部分來實現通信和整體架構的獨立性,Client端負責解析本地腳本,這樣只要本地腳本實現了兼容的接口,就可以方便實現腳本語言的擴展,而Server端則封裝了Android原生態程序的設計,即使在android底層API發生API變化的時候,Client端也基本不會受到影響,Client把腳本中解析出來的函數調用通過RPC通信,遠程呼叫Server端代理接口,然後由Server調用原生態的Android API(Android Facade架構)來完成具體的功能,在調用結束後,Server端將執行結果反饋給Client端。

整個執行過程如下:

 -­‐-­‐ Script Interpreter
-­‐-­‐-­‐-­‐ Client/Caller/Consumer Script
-­‐-­‐-­‐-­‐-­‐-­‐ "Android" Script Object (locally wraps RPC calls) -­‐ Local Proxy
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ Remote Procedure Calls (RPC) – Exchanges contain a JSON payload
-­‐-­‐-­‐-­‐-­‐-­‐ Android API Java Facade -­‐ Remote Proxy
-­‐-­‐-­‐-­‐ API Server/Provider -­‐ Android Java application
-­‐-­‐ The Android Platform itself

Local Proxy 的實現機制

其實每個本地模塊都封裝實現了一個android實體類,然後開放其調用接口,內部通過RPC與SL4A Server端通信。

Python 模塊(android.py)之實現

# Copyright (C) 2009 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
 
__author__ = 'Damon Kohler <[email protected]>'
 
import collections
import json
import os
import socket
import sys
 
PORT = os.environ.get('AP_PORT')
HOST = os.environ.get('AP_HOST')
HANDSHAKE = os.environ.get('AP_HANDSHAKE')
Result = collections.namedtuple('Result', 'id,result,error')
 
class Android(object):
 
  def __init__(self, addr=None):
    if addr is None:
      addr = HOST, PORT
    self.conn = socket.create_connection(addr)
    self.client = self.conn.makefile()
    self.id = 0
    if HANDSHAKE is not None:
      self._authenticate(HANDSHAKE)
 
  def _rpc(self, method, *args):
    data = {'id': self.id,
            'method': method,
            'params': args}
    request = json.dumps(data)
    self.client.write(request+'\n')
    self.client.flush()
    response = self.client.readline()
    self.id += 1
    result = json.loads(response)
    if result['error'] is not None:
      print result['error']
    # namedtuple doesn't work with unicode keys.
    return Result(id=result['id'], result=result['result'],
                  error=result['error'], )
 
  def __getattr__(self, name):
    def rpc_call(*args):
      return self._rpc(name, *args)
    return rpc_call
Copyright © Linux教程網 All Rights Reserved