当前位置:  编程技术>移动开发
本页文章导读:
    ▪AndRootFile 1.1 alpha 首发版本公布        AndRootFile 1.1 alpha 首发版本发布 AndRootFile   The ultimate file manager for root users. It can access the whole of file system and support copy, cut, paste, delete and rename.   Androofile是一个文件管理软件,支持拷贝,剪.........
    ▪ 世博会引见手机软件-红舞姬        世博会介绍手机软件---红舞姬 经过两天,总算是有了一个稳定的版本,今晚就前往上海,去世博会玩。并给其起一个名字红舞姬(来源于前两天看的深海探奇,我们两个都喜欢那个西班牙红.........
    ▪ 透过HAL(硬件抽象层)看顶层API是怎么访问硬件       透过HAL(硬件抽象层)看顶层API是如何访问硬件         文章导读:HAL硬件抽象层的实现及架构、Android API 与硬件平台的衔接、NDK的一些看法。   简介:Hardware Abstraction Layer 硬件抽象层.........

[1]AndRootFile 1.1 alpha 首发版本公布
    来源: 互联网  发布时间: 2014-02-18
AndRootFile 1.1 alpha 首发版本发布

AndRootFile

 

The ultimate file manager for root users.

It can access the whole of file system and support copy, cut, paste, delete and rename.

 

Androofile是一个文件管理软件,支持拷贝,剪贴,粘贴,重命名,删除等,下一个版本将新增一些管理和设置功能。

 

了解更多 http://code.google.com/p/andbox/

 


    
[2] 世博会引见手机软件-红舞姬
    来源: 互联网  发布时间: 2014-02-18
世博会介绍手机软件---红舞姬

经过两天,总算是有了一个稳定的版本,今晚就前往上海,去世博会玩。并给其起一个名字红舞姬(来源于前两天看的深海探奇,我们两个都喜欢那个西班牙红舞姬)。
现把程序先发上来。
列表

内容

下面这个类是列表呈现页面。
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ruyuntao;

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.*; //提供了一个命令类
import javax.microedition.rms.RecordStoreException;
/**
 * @author Administrator
 */
public class expo extends MIDlet implements CommandListener {

    private List mainList;
    Image[] imageArray;
    private Command exitCommand;
    private Display display;
    expoFile m;

    String stringArray[] = {
        "**主题馆",
        "主题馆",
        "城市人馆",
        "城市生命馆",
        "城市地球馆",
        "城市足迹馆",
        "城市未来馆",
        "**A区",
        "中国国家馆",
        "土库曼斯坦馆",
        "日本馆",
        "**中国省区市联合馆",
        "北京馆",
        "天津馆",
        "河北馆",
        "山西馆",
        "内蒙古馆",
        "辽宁馆",
        "吉林馆",
        "黑龙江馆 ",
        "江苏馆",
        "浙江馆 ",
        "安徽馆",
        "福建馆",
        "江西馆 ",
        "山东馆 ",
        "河南馆 ",
        "湖北馆",
        "湖南馆",
        "广东馆",
        "广西馆",
        "海南馆 ",
        "重庆馆",
        "四川馆",
        "贵州馆",
        "云南馆 ",
        "西藏馆",
        "陕西馆 ",
        "甘肃馆",
        "青海馆",
        "宁夏馆",
        "新疆馆 ",
        "上海馆",
        "**A区2",
        "乌兹别克斯坦馆 ",
        "巴基斯坦馆 ",
        "以色列馆",
        "卡塔尔馆 ",
        "印度馆 ",
        "尼泊尔馆 ",
        "台湾馆 ",
        "**亚洲联合馆一",
        "马尔代夫馆 ",
        "东帝汶馆 ",
        "吉尔吉斯斯坦馆",
        "孟加拉国馆 ",
        "塔吉克斯坦馆",
        "蒙古馆",
        "**亚洲联合馆二",
        "也门馆 ",
        "巴林馆 ",
        "巴勒斯坦馆 ",
        "约旦馆",
        "阿富汗馆",
        "叙利亚馆 ",
        "**亚洲联合馆三",
        "老挝馆",
        "伊拉克馆 ",
        "缅甸馆 ",
        "**A区3",
        "伊朗馆 ",
        "沙特阿拉伯馆",
        "阿曼馆",
        "阿联酋馆",
        "哈萨克斯坦馆",
        "香港馆 ",
        "越南馆",
        "斯里兰卡馆",
        "韩国馆",
        "朝鲜馆 ",
        "黎巴嫩馆",
        "摩洛哥馆",
        "澳门馆 ",
        "**B片区",
        "马来西亚馆 ",
        "太平洋联合馆",
        "文莱馆 ",
        "公众参与馆",
        "世界气象馆",
        "世界贸易中心协会馆",
        "生命阳光馆 ",
        "印度尼西亚馆 ",
        "红十字会红新月会会馆",
        "**国际组织联合馆 ",
        "上海合作组织馆 ",
        "公共交通国际联会馆",
        "世界水理事会馆 ",
        "世界自然基金会馆",
        "世界城市和地方政府联合组织馆 ",
        "东南亚国家联盟馆 ",
        "东南非共同市场馆",
        "全球环境基金馆 ",
        "阿拉伯国家联盟馆 ",
        "国际竹藤组织馆 ",
        "国际博物馆协会馆 ",
        "法语国家商务论坛馆",
        "博鳌亚洲论坛馆",
        "**B片区2",
        "国际信息发展网馆",
        "柬埔寨馆",
        "泰国馆",
        "菲律宾馆 ",
        "联合国联合馆",
        "新加坡馆",
        "新西兰馆",
        "澳大利亚馆",
        "**C片区",
        "土耳其馆",
        "比利时-欧盟馆",
        "**中南美洲联合馆",
        "厄瓜多尔馆",
        "乌拉圭馆",
        "巴拉圭馆",
        "巴拿马馆",
        "尼加拉瓜馆",
        "危地马拉馆",
        "多米尼加馆 ",
        "玻利维亚馆",
        "洪都拉斯馆",
        "哥斯达黎加馆",
        "萨尔瓦多馆",
        "**C片区2",
        "丹麦馆 ",
        "乌克兰馆",
        "巴西馆",
        "古巴馆",
        "卢森堡馆",
        "白俄罗斯馆",
        "立陶宛馆",
        "尼日利亚馆 ",
        "加拿大馆",
        "**加勒比共同体联合馆  ",
        "牙买加馆 ",
        "巴巴多斯馆 ",
        "巴哈马馆 ",
        "加勒比开发银行馆 ",
        "加勒比共同体馆",
        "圣文森特和格林纳丁斯馆 ",
        "圣卢西亚馆",
        "圣基茨和尼维斯馆",
        "圭亚那馆 ",
        "多米尼克馆 ",
        "安提瓜和巴布达馆",
        "苏里南馆 ",
        "伯利兹馆",
        "格林纳达馆",
        "特立尼达和多巴哥馆 ",
        "海地馆",
        "**C片区3",
        "西班牙馆",
        "匈牙利馆",
        "冰岛馆",
        "安哥拉馆 ",
        "芬兰馆 ",
        "克罗地亚馆 ",
        "利比亚馆 ",
        "希腊馆 ",
        "阿尔及利亚馆 ",
        "阿根廷馆",
        "拉脱维亚馆",
        "英国馆",
        "**欧洲联合馆一 ",
        "马耳他馆 ",
        "圣马力诺馆 ",
        "列支敦士登馆",
        "塞浦路斯馆 ",
        "**欧洲联合馆二",
        "亚美尼亚馆 ",
        "阿尔巴尼亚馆 ",
        "阿塞拜疆馆 ",
        "保加利亚馆 ",
        "前南斯拉夫马其顿共和国馆",
        "格鲁吉亚馆 ",
        "黑山馆",
        "摩尔多瓦馆",
        "**非洲联合馆",
        "几内亚馆 ",
        "几内亚比绍馆",
        "马达加斯加馆",
        "马里馆",
        "马拉维馆",
        "厄立特里亚馆 ",
        "中非馆",
        "贝宁馆 ",
        "冈比亚馆",
        "毛里求斯馆",
        "毛里塔尼亚馆 ",
        "乌干达馆",
        "布隆迪馆",
        "卢旺达馆 ",
        "乍得馆 ",
        "尼日尔馆",
        "加纳馆",
        "加蓬馆",
        "吉布提馆",
        "刚果(布)馆 ",
        "刚果(金)馆",
        "多哥馆",
        "赤道几内亚馆 ",
        "苏丹馆 ",
        "利比里亚馆",
        "佛得角馆",
        "纳米比亚馆 ",
        "坦桑尼亚馆",
        "非盟馆",
        "肯尼亚馆",
        "科特迪瓦馆",
        "科摩罗馆 ",
        "津巴布韦馆",
        "埃塞俄比亚馆",
        "莱索托馆 ",
        "莫桑比克馆 ",
        "索马里馆",
        "博茨瓦纳馆 ",
        "喀麦隆馆 ",
        "塞内加尔馆",
        "塞舌尔馆 ",
        "塞拉利昂馆 ",
        "赞比亚馆",
        "**欧洲联合馆三",
        "罗马尼亚馆",
        "委内瑞拉馆 ",
        "法国馆 ",
        "波兰馆 ",
        "波黑馆 ",
        "挪威馆 ",
        "南非馆",
        "俄罗斯馆 ",
        "美国馆 ",
        "突尼斯馆 ",
        "埃及馆 ",
        "荷兰馆 ",
        "哥伦比亚馆",
        "秘鲁馆 ",
        "爱尔兰馆 ",
        "爱沙尼亚馆 ",
        "捷克馆 ",
        "斯洛文尼亚馆 ",
        "斯洛伐克馆 ",
        "葡萄牙馆 ",
        "智利馆 ",
        "奥地利馆 ",
        "瑞士馆",
        "瑞典馆 ",
        "意大利馆 ",
        "塞尔维亚馆 ",
        "墨西哥馆 ",
        "德国馆 ",
        "摩纳哥馆",
        "**D片区   ",
        "上海企业联合馆 ",
        "太空家园馆 ",
        "日本产业馆 ",
        "中国人保馆 ",
        "中国铁路馆 ",
        "可口可乐馆 ",
        "石油馆 ",
        "国家电网馆 ",
        "思科馆 ",
        "韩国企业联合馆 ",
        "震旦馆",
        "**E片区 ",
        "万科馆",
        "上汽集团-通用汽车馆 ",
        "中国航空馆 ",
        "中国船舶馆 ",
        "民营企业联合馆 ",
        "远大馆 ",
        "信息通信馆",
        "**城市最佳实践区建设案例(北部) ",
        "宁波案例馆 ",
        "西安案例馆 ",
        "麦加案例馆 ",
        "温哥华案例馆 ",
        "上海案例馆 ",
        "马德里案例馆 ",
        "伦敦案例馆 ",
        "汉堡案例馆 ",
        "阿尔萨斯案例馆",
        "罗纳阿尔卑斯案例馆 ",
        "澳门案例馆 ",
        "成都案例馆 ",
        "欧登塞案例馆 ",
        "罗纳阿尔卑斯灯光案例",
        "城市最佳实践区展馆案例(中部)",
        "城市最佳实践区其他展示案例(南部)",
        "服务支持"
    };
    String pathNameArr[] = {
        "..",
        "zt",
        "csrg",
        "cssmg",
        "csdqg",
        "cszjg",
        "cswlg",
        "..",
        "zggjg",
        "tkmstg",
        "rbg",
        "..",
        "bjg",
        "tjg",
        "hbg",
        "sxg",
        "nmg",
        "lng",
        "jlg",
        "hljg",
        "jsg",
        "zjg",
        "ahg",
        "fjg",
        "jxg",
        "xdg",
        "hng",
        "hubg",
        "hung",
        "gdg",
        "gxg",
        "haing",
        "cqg",
        "scg",
        "gzg",
        "yng",
        "xzg",
        "sxig",
        "gsg",
        "qhg",
        "nxg",
        "xjg",
        "shg",
        "..",
        "wzbkst",
        "bjst",
        "ysl",
        "kte",
        "yd",
        "nbe",
        "tw",
        "..",
        "medf",
        "ddw",
        "jejsst",
        "mjlg",
        "tjkst",
        "mgw",
        "..",
        "ym",
        "bl",
        "blst",
        "yud",
        "afh",
        "xly",
        "..",
        "lwg",
        "ylkg",
        "mdg",
        "..",
        "ylg",
        "stalb",
        "am",
        "alq",
        "hskst",
        "xg",
        "yueng",
        "slnk",
        "hg",
        "cx",
        "lbn",
        "mlg",
        "aom",
        "..",
        "mlxy",
        "tpylhg",
        "wlg",
        "gzcyg",
        "sjqxg",
        "sjmyzx",
        "smyg",
        "ydnxx",
        "hszhxyg",
        "..",
        "shhzzz",
        "ggjtgjlh",
        "sjslsh",
        "sjzrjjh",
        "sjcsdfzf",
        "dnygjlm",
        "..",
        "qqhjjj",
        "albgjlm",
        "gjztzz",
        "gjbwgxh",
        "fygjswlt",
        "bayzlt",
        "..",
        "gjxxfz",
        "jpzg",
        "tgg",
        "flbg",
        "lhglhg",
        "xjpg",
        "xxlg",
        "aodlyg",
        "..",
        "teq",
        "bls",
        "..",
        "egde",
        "wlgg",
        "bng",
        "bnmg",
        "njlg",
        "wdmlg",
        "mjnj",
        "blwy",
        "hdls",
        "gsdlj",
        "sewd",
        "..",
        "dmg",
        "wkl",
        "bx",
        "gb",
        "lsb",
        "bels",
        "ltw",
        "nrly",
        "jld",
        "..",
        "ymj",
        "bbds",
        "bhm",
        "jlbkfyh",
        "jlbgtt",
        "swstglnds",
        "slx",
        "sjsnws",
        "gyn",
        "dmnk",
        "atgbbd",
        "sln",
        "blc",
        "glnd",
        "tlnddbg",
        "hd",
        "..",
        "xby",
        "xyl",
        "bd",
        "agl",
        "flg",
        "kldy",
        "lby",
        "xlg",
        "aejly",
        "agt",
        "ltwy",
        "yg",
        "..",
        "metg",
        "smlr",
        "lzdsd",
        "spls",
        "..",
        "ymny",
        "aebny",
        "asbj",
        "bjly",
        "lslfm",
        "gljy",
        "hs",
        "medw",
        "..",
        "jny",
        "jnybs",
        "mdjsj",
        "ml",
        "mlw",
        "eltly",
        "zf",
        "bn",
        "gby",
        "mlqs",
        "mltny",
        "wgd",
        "bld",
        "lwd",
        "zdg",
        "nre",
        "jn",
        "jp",
        "jbt",
        "ggb",
        "ggj",
        "dg",
        "cdjny",
        "sd",
        "lbly",
        "fdj",
        "nmby",
        "tsny",
        "fm",
        "kny",
        "ktdw",
        "kmlg",
        "jbbw",
        "eseby",
        "lst",
        "msbk",
        "sml",
        "bcwl",
        "kml",
        "snje",
        "sse",
        "slly",
        "zby",
        "..",
        "lmny",
        "wnrl",
        "fg",
        "blg",
        "bh",
        "lw",
        "nf",
        "els",
        "mg",
        "tns",
        "ej",
        "hn",
        "elby",
        "mlgg",
        "eel",
        "esny",
        "jk",
        "slwny",
        "slfk",
        "pty",
        "zl",
        "adl",
        "ss",
        "sdg",
        "ydl",
        "sewy",
        "mxg",
        "dgg",
        "eng",
        "..",
        "shqylh",
        "tkjy",
        "rbcyg",
        "zgrbg",
        "zgtl",
        "kkkl",
        "sy",
        "gjdw",
        "sk",
        "hgqylh",
        "zd",
        "..",
        "wkg",
        "sqty",
        "zghk",
        "zgcb",
        "myqy",
        "ydg",
        "xxtx",
        "..",
        "nbalg",
        "xaalg",
        "mjalg",
        "wghalg",
        "shalg",
        "mdlalg",
        "ldalg",
        "hbalg",
        "aessalg",
        "lnaebsalg",
        "amalg",
        "cdalg",
        "odsnalg",
        "lnaebsdgal",
        "cszjsjz",
        "cszjsjn",
        "server"
    };

    public expo() //类的构造函数
    {
        int length = stringArray.length;
        String titleArray[] = new String[length];
        try {
            Image icon = Image.createImage("/h.png");

            imageArray = new Image[length];
            for (int i = 0; i < length; i++) {
                imageArray[i] = icon;
                String tem = stringArray[i];
                if (tem.length() > 6) {
                    tem = tem.substring(0, 6);
                }
                titleArray[i] = tem;
            }
        } catch (java.io.IOException err) {
            imageArray = null;
        }
        Font font = Font.getFont(Font.FACE_SYSTEM,
                Font.STYLE_PLAIN, Font.SIZE_LARGE);
        mainList = new List("世博会简介", Choice.IMPLICIT, titleArray, imageArray);
        int size = mainList.size();
        for (int i = 0; i < size; i++) {
            mainList.setFont(i, font);
        }
        exitCommand = new Command("退出", Command.EXIT, 1);
        mainList.addCommand(exitCommand);
        mainList.setCommandListener(this);
        display = Display.getDisplay(this);
    }

    protected void startApp() throws MIDletStateChangeException //负责程序的初始化功能
    {
        display.setCurrent(mainList);

    }

    protected void destroyApp(boolean arg0) throws MIDletStateChangeException //程序推出时调用的函数
    {
    }

    protected void pauseApp() //暂停状态时调用的函数
    {
    }

    public void commandAction(Command c, Displayable d) {
        if (c == exitCommand) {
            try {
                destroyApp(false);
            } catch (MIDletStateChangeException ex) {
                ex.printStackTrace();
            }
            notifyDestroyed();
        } else {
            String name = pathNameArr[mainList.getSelectedIndex()];
            if (!"..".equals(name)) {
                try {
                    m = new expoFile(display, mainList, name, stringArray[mainList.getSelectedIndex()]);
                    Display.getDisplay(this).setCurrent(m);
                } catch (RecordStoreException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}


下面这个类是内容显示页面
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ruyuntao;

import java.io.IOException;
import java.io.InputStreamReader;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;

/**
 *
 * @author Administrator
 */
public class expoFile extends Form implements CommandListener {

    private Display display;
    private Displayable displayable;
    private Command cmdBack;
    private Font font;
    public expoFile(Display d, Displayable p, String name,String mpName) throws RecordStoreException,
            RecordStoreFullException, RecordStoreNotFoundException {
        super("世博会");
        display = d;
        displayable = p;
        font = Font.getFont(Font.FACE_SYSTEM,
                Font.STYLE_BOLD, Font.SIZE_LARGE);
        String path = "/text/" + name;
        if(!mpName.equals("服务支持")){
            StringItem item = new StringItem("","场馆:"+mpName);
            item.setFont(font);
            this.append(item);
        }
        font = Font.getFont(Font.FACE_SYSTEM,
                Font.STYLE_PLAIN, Font.SIZE_LARGE);
        try {
            readFile(path);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        cmdBack = new Command("返回", Command.BACK, 1);
        this.addCommand(cmdBack);
        this.setCommandListener(this);
    }

    private void readFile(String filename) throws IOException {
        InputStreamReader reader = new InputStreamReader(
                getClass().getResourceAsStream(filename));
        String line = null;
        while ((line = readLine(reader)) != null) {
            StringItem item = new StringItem("",line);
            item.setFont(font);
            this.append(item);
        }
        reader.close();
    }

    private String readLine(InputStreamReader reader) throws IOException {
        int readChar = reader.read();
        if (readChar == -1) {
            return null;
        }
        StringBuffer string = new StringBuffer("");
        while (readChar != -1 && readChar != '\n') {
            if (readChar != '\r') {
                string.append((char) readChar);
            }
            readChar = reader.read();
        }
        return new String(string.toString().getBytes(), "UTF-8");
    }

    public void commandAction(Command c, Displayable d) {
        try {
            if (c == cmdBack) {
                display.setCurrent(displayable);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}


用了两天写出来的,大部分时间用在了从世博会网站上拷贝文件,里面的代码很多事借鉴网友的无私奉献。现在将我的成果也发布出来。
不过我目前只在诺基亚s40和s60两种类型手机上测试过,希望大家指出哪里不足,也希望能够给需要到世博会去的同仁们带来帮助。
附件里面expo.jar包里面是编译好的,直接拷贝到存储卡里面就可以运行。

    
[3] 透过HAL(硬件抽象层)看顶层API是怎么访问硬件
    来源: 互联网  发布时间: 2014-02-18
透过HAL(硬件抽象层)看顶层API是如何访问硬件


        文章导读:HAL硬件抽象层的实现及架构、Android API 与硬件平台的衔接、NDK的一些看法。

 

简介:Hardware Abstraction Layer 硬件抽象层是一个轻量级(lightweight)的的运行环境,提供了简单的设备驱动程序接口,应用程序使用设备驱动程序与底层硬件之间进行通信。HAL应用程序接口和ANSIC标准库结合在一起,这样用户可以使用C语言库函数来访问Android文件系统。下图是其直观的概念:

 

 

从图中,我们可以看到HAL是基于Linux Kernel与Libraries和Android Runtime之间。也就是说,HAL是底层硬件设备驱动程序暴露给Application Framework (也就是通常我们使用的Android API )的一个接口层。(可以浏览http://hi.baidu.com/aokikyon/blog/item/a66e0f87d8f55326c75cc32b.html HAL分析报告获得更详细的认识)

 

在网上也看到一些朋友写了重力感应器的api使用,那么以重力感应器Sensor为例子,看看重力感应器如何和Applications、Application Framework衔接。

1、下面Sensors.h的定义重力感应器对驱动程序部分的操作:

在源码./platform/hardware/Libardware /Include/Sensors.h目录下

 

#include <...>
__BEGIN_DECLS

/**
 * The id of this module
 */
#define SENSORS_HARDWARE_MODULE_ID "sensors"

/**
 * Name of the sensors device to open
 */
#define SENSORS_HARDWARE_CONTROL    "control"
#define SENSORS_HARDWARE_DATA       "data"

.....

/** convenience API for opening and closing a device */

static inline int sensors_control_open(const struct hw_module_t* module, 
        struct sensors_control_device_t** device) {
    return module->methods->open(module, 
            SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);
}

static inline int sensors_control_close(struct sensors_control_device_t* device) {
    return device->common.close(&device->common);
}

static inline int sensors_data_open(const struct hw_module_t* module, 
        struct sensors_data_device_t** device) {
    return module->methods->open(module, 
            SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);
}

static inline int sensors_data_close(struct sensors_data_device_t* device) {
    return device->common.close(&device->common);
}


__END_DECLS

#endif  // ANDROID_SENSORS_INTERFACE_H
  

 

 2、JNI部分代码

 

    加载该驱动的访问程序./framework/Jni/onLoad.cpp

 

#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"
#include "JNIHelp.h"
namespace android {
...
int register_android_server_SensorService(JNIEnv* env);
...
};

using namespace android;

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("GetEnv failed!");
        return result;
    }
    LOG_ASSERT(env, "Could not retrieve the env!");

    //注册SensorService
    register_android_server_SensorService(env);
  

    return JNI_VERSION_1_4;
}

 

    向Application Framework提供接口部分./framework/Jni/com_android_server_SensorService.cpp

 

 

 

#define LOG_TAG "SensorService"
#define LOG_NDEBUG 0
#include "utils/Log.h"
//加载sensor.h文件
#include <hardware/sensors.h>

#include "jni.h"
#include "JNIHelp.h"

namespace android {

static struct file_descriptor_offsets_t
{
    jclass mClass;
    jmethodID mConstructor;
    jfieldID mDescriptor;
} gFileDescriptorOffsets;

static struct parcel_file_descriptor_offsets_t
{
    jclass mClass;
    jmethodID mConstructor;
} gParcelFileDescriptorOffsets;

static struct bundle_descriptor_offsets_t
{
    jclass mClass;
    jmethodID mConstructor;
    jmethodID mPutIntArray;
    jmethodID mPutParcelableArray;
} gBundleOffsets;

/*
 * The method below are not thread-safe and not intended to be 
 */

static sensors_control_device_t* sSensorDevice = 0;

static jint
android_init(JNIEnv *env, jclass clazz)
{
    sensors_module_t* module;
    if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
        if (sensors_control_open(&module->common, &sSensorDevice) == 0) {
            const struct sensor_t* list;
            int count = module->get_sensors_list(module, &list);
            return count;
        }
    }
    return 0;
}

static jobject
android_open(JNIEnv *env, jclass clazz)
{
    native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
    if (!handle) {
        return NULL;
    }

    // new Bundle()
    jobject bundle = env->NewObject(
            gBundleOffsets.mClass,
            gBundleOffsets.mConstructor);

    if (handle->numFds > 0) {
        jobjectArray fdArray = env->NewObjectArray(handle->numFds,
                gParcelFileDescriptorOffsets.mClass, NULL);
        for (int i = 0; i < handle->numFds; i++) {
            // new FileDescriptor()
            jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
                    gFileDescriptorOffsets.mConstructor);
            env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
            // new ParcelFileDescriptor()
            jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
                    gParcelFileDescriptorOffsets.mConstructor, fd);
            env->SetObjectArrayElement(fdArray, i, pfd);
        }
        // bundle.putParcelableArray("fds", fdArray);
        env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,
                env->NewStringUTF("fds"), fdArray);
    }

    if (handle->numInts > 0) {
        jintArray intArray = env->NewIntArray(handle->numInts);
        env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);
        // bundle.putIntArray("ints", intArray);
        env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,
                env->NewStringUTF("ints"), intArray);
    }

    // delete the file handle, but don't close any file descriptors
    native_handle_delete(handle);
    return bundle;
}

static jint
android_close(JNIEnv *env, jclass clazz)
{
    if (sSensorDevice->close_data_source)
        return sSensorDevice->close_data_source(sSensorDevice);
    else
        return 0;
}

static jboolean
android_activate(JNIEnv *env, jclass clazz, jint sensor, jboolean activate)
{
    int active = sSensorDevice->activate(sSensorDevice, sensor, activate);
    return (active<0) ? false : true;
}

static jint
android_set_delay(JNIEnv *env, jclass clazz, jint ms)
{
    return sSensorDevice->set_delay(sSensorDevice, ms);
}

static jint
android_data_wake(JNIEnv *env, jclass clazz)
{
    int res = sSensorDevice->wake(sSensorDevice);
    return res;
}

//提供给顶层实现的访问函数
static JNINativeMethod gMethods[] = {
    {"_sensors_control_init",     "()I",   (void*) android_init },
    {"_sensors_control_open",     "()Landroid/os/Bundle;",  (void*) android_open },
    {"_sensors_control_close",     "()I",  (void*) android_close },
    {"_sensors_control_activate", "(IZ)Z", (void*) android_activate },
    {"_sensors_control_wake",     "()I", (void*) android_data_wake },
    {"_sensors_control_set_delay","(I)I", (void*) android_set_delay },
};

int register_android_server_SensorService(JNIEnv *env)
{
    jclass clazz;

    clazz = env->FindClass("java/io/FileDescriptor");
    gFileDescriptorOffsets.mClass = (jclass)env->NewGlobalRef(clazz);
    gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");

    clazz = env->FindClass("android/os/ParcelFileDescriptor");
    gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>",
            "(Ljava/io/FileDescriptor;)V");

    clazz = env->FindClass("android/os/Bundle");
    gBundleOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gBundleOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
    gBundleOffsets.mPutIntArray = env->GetMethodID(clazz, "putIntArray", "(Ljava/lang/String;[I)V");
    gBundleOffsets.mPutParcelableArray = env->GetMethodID(clazz, "putParcelableArray",
            "(Ljava/lang/String;[Landroid/os/Parcelable;)V");

    return jniRegisterNativeMethods(env, "com/android/server/SensorService",
            gMethods, NELEM(gMethods));
}

}; // namespace android

 

    到了这里文件系统中底层的部分算是完成了。对于下层类库而言,我们可以通过HAL的方式建立android Api 和硬件设备驱动连接的桥梁。针对不同的硬件平台需要用户自己编写这几个函数的实现方式并通过android kernel里的驱动(当然有部分驱动可能位于文件系统中)来控制硬件行为。对于上层而言,可以看做是给顶层Java实现Android API提供一个访问接口。由于该文件是编译成系统 的*.so库文件,这与NDK中的为系统加载一个*.so相似。

 

 3、Application Framework层是如何监听Sensor的物理数据

    到了这里,用NDK的编程经验,我们可以通过system.load("*.so")获得某个库的访问,并使用里面的函数,进行想要的操作。而Google为了方便用户操作,用Java语言提供一些便捷访问的Application Framework将底层的c/c++实现的驱动或者其他细节封装起来,也就是我们所说的API(\(^o^)/~个人理解)。

    

    终于到了熟悉的Android API 层了。

    对于重力感应器,Android在./framework/base/service/java/com/android/server/SensorsService.java

 

import android.content.Context;
import android.hardware.ISensorService;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.IBinder;
import android.util.Config;
import android.util.Slog;
import android.util.PrintWriterPrinter;
import android.util.Printer;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;

import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;


/**
 * Class that manages the device's sensors. It register clients and activate
 * the needed sensors. The sensor events themselves are not broadcasted from
 * this service, instead, a file descriptor is provided to each client they
 * can read events from.
 */

class SensorService extends ISensorService.Stub {
    static final String TAG = SensorService.class.getSimpleName();
    private static final boolean DEBUG = false;
    private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
    private static final int SENSOR_DISABLE = -1;
    private int mCurrentDelay = 0;
    
    /**
     * Battery statistics to be updated when sensors are enabled and disabled.
     */
    final IBatteryStats mBatteryStats = BatteryStatsService.getService();

    private final class Listener implements IBinder.DeathRecipient {
        final IBinder mToken;
        final int mUid;

        int mSensors = 0;
        int mDelay = 0x7FFFFFFF;
        
        Listener(IBinder token, int uid) {
            mToken = token;
            mUid = uid;
        }
        
        void addSensor(int sensor, int delay) {
            mSensors |= (1<<sensor);
            if (delay < mDelay)
            	mDelay = delay;
        }
        
        void removeSensor(int sensor) {
            mSensors &= ~(1<<sensor);
        }

        boolean hasSensor(int sensor) {
            return ((mSensors & (1<<sensor)) != 0);
        }

        public void binderDied() {
            if (localLOGV) Slog.d(TAG, "sensor listener died");
            synchronized(mListeners) {
                mListeners.remove(this);
                mToken.unlinkToDeath(this, 0);
                // go through the lists of sensors used by the listener that 
                // died and deactivate them.
                for (int sensor=0 ; sensor<32 && mSensors!=0 ; sensor++) {
                    if (hasSensor(sensor)) {
                        removeSensor(sensor);
                        deactivateIfUnusedLocked(sensor);
                        try {
                            mBatteryStats.noteStopSensor(mUid, sensor);
                        } catch (RemoteException e) {
                            // oops. not a big deal.
                        }
                    }
                }
                if (mListeners.size() == 0) {
                    _sensors_control_wake();
                    _sensors_control_close();
                } else {
                    // TODO: we should recalculate the delay, since removing
                    // a listener may increase the overall rate.
                }
                mListeners.notify();
            }
        }
    }

    @SuppressWarnings("unused")
    public SensorService(Context context) {
        if (localLOGV) Slog.d(TAG, "SensorService startup");
        _sensors_control_init();
    }
    
    public Bundle getDataChannel() throws RemoteException {
        // synchronize so we do not require sensor HAL to be thread-safe.
        synchronized(mListeners) {
            return _sensors_control_open();
        }
    }

    public boolean enableSensor(IBinder binder, String name, int sensor, int enable)
            throws RemoteException {
        
        if (localLOGV) Slog.d(TAG, "enableSensor " + name + "(#" + sensor + ") " + enable);

        if (binder == null) {
            Slog.e(TAG, "listener is null (sensor=" + name + ", id=" + sensor + ")");
            return false;
        }

        if (enable < 0 && (enable != SENSOR_DISABLE)) {
            Slog.e(TAG, "invalid enable parameter (enable=" + enable +
                    ", sensor=" + name + ", id=" + sensor + ")");
            return false;
        }

        boolean res;
        int uid = Binder.getCallingUid();
        synchronized(mListeners) {
            res = enableSensorInternalLocked(binder, uid, name, sensor, enable);
            if (res == true) {
                // Inform battery statistics service of status change
                long identity = Binder.clearCallingIdentity();
                if (enable == SENSOR_DISABLE) {
                    mBatteryStats.noteStopSensor(uid, sensor);
                } else {
                    mBatteryStats.noteStartSensor(uid, sensor);
                }
                Binder.restoreCallingIdentity(identity);
            }
        }
        return res;
    }

    private boolean enableSensorInternalLocked(IBinder binder, int uid,
            String name, int sensor, int enable) throws RemoteException {

        // check if we have this listener
        Listener l = null;
        for (Listener listener : mListeners) {
            if (binder == listener.mToken) {
                l = listener;
                break;
            }
        }

        if (enable != SENSOR_DISABLE) {
            // Activate the requested sensor
            if (_sensors_control_activate(sensor, true) == false) {
                Slog.w(TAG, "could not enable sensor " + sensor);
                return false;
            }

            if (l == null) {
                /*
                 * we don't have a listener for this binder yet, so
                 * create a new one and add it to the list.
                 */
                l = new Listener(binder, uid);
                binder.linkToDeath(l, 0);
                mListeners.add(l);
                mListeners.notify();
            }

            // take note that this sensor is now used by this client
            l.addSensor(sensor, enable);

        } else {

            if (l == null) {
                /*
                 *  This client isn't in the list, this usually happens
                 *  when enabling the sensor failed, but the client
                 *  didn't handle the error and later tries to shut that
                 *  sensor off.
                 */
                Slog.w(TAG, "listener with binder " + binder +
                        ", doesn't exist (sensor=" + name +
                        ", id=" + sensor + ")");
                return false;
            }

            // remove this sensor from this client
            l.removeSensor(sensor);

            // see if we need to deactivate this sensors=
            deactivateIfUnusedLocked(sensor);

            // if the listener doesn't have any more sensors active
            // we can get rid of it
            if (l.mSensors == 0) {
                // we won't need this death notification anymore
                binder.unlinkToDeath(l, 0);
                // remove the listener from the list
                mListeners.remove(l);
                // and if the list is empty, turn off the whole sensor h/w
                if (mListeners.size() == 0) {
                    _sensors_control_wake();
                    _sensors_control_close();
                }
                mListeners.notify();
            }
        }

        // calculate and set the new delay
        int minDelay = 0x7FFFFFFF;
        for (Listener listener : mListeners) {
            if (listener.mDelay < minDelay)
                minDelay = listener.mDelay;
        }
        if (minDelay != 0x7FFFFFFF) {
            mCurrentDelay = minDelay;
            _sensors_control_set_delay(minDelay);
        }

        return true;
    }

    private void deactivateIfUnusedLocked(int sensor) {
        int size = mListeners.size();
        for (int i=0 ; i<size ; i++) {
            if (mListeners.get(i).hasSensor(sensor)) {
                // this sensor is still in use, don't turn it off
                return;
            }
        }
        if (_sensors_control_activate(sensor, false) == false) {
            Slog.w(TAG, "could not disable sensor " + sensor);
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        synchronized (mListeners) {
            Printer pr = new PrintWriterPrinter(pw);
            int c = 0;
            pr.println(mListeners.size() + " listener(s), delay=" + mCurrentDelay + " ms");
            for (Listener l : mListeners) {
                pr.println("listener[" + c + "] " +
                        "sensors=0x" + Integer.toString(l.mSensors, 16) +
                        ", uid=" + l.mUid +
                        ", delay=" +
                        l.mDelay + " ms");
                c++;
            }
        }
    }

    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
    //JNI提供的访问函数,将Application Framework和驱动衔接起来。
    private static native int _sensors_control_init();
    private static native Bundle _sensors_control_open();
    private static native int _sensors_control_close();
    private static native boolean _sensors_control_activate(int sensor, boolean activate);
    private static native int _sensors_control_set_delay(int ms);
    private static native int _sensors_control_wake();
}
 

   接下来就是Core提供给我们使用的API了,这部分不在详解。

   总结一下:对于NDK也不在啰唆,它和HAL一样,一个是提供商业保密程序,一个是google应厂商要求不希望公开源码。对于HAL的分析,我们也可以看到它大致的开发流程,也隐隐约约看到NDK的影子。若NDK涉及到硬件平台,它又该如何考虑夸平台呢?

 

 

1 楼 sharp_lover 2011-01-22  
楼主的意思是通过这个来访问google 没有公开的api 吗?
2 楼 地球小野花 2011-03-18  
是的。

    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3