精华内容
下载资源
问答
  • Java实现事件驱动框架(一)

    千次阅读 2018-04-30 21:41:57
    事件驱动框架参照一些消息系统中的模式。我们将进行如下类比。 事件与消息,事件处理器与通道,事件转发器与路由。 一个实例是邮递系统。邮递员有一个背包里面有若干信件,上面有要寄送的地址,邮递员必须将信件寄...

    上一篇文章中,我们介绍了事件驱动的基础组件。本文,我们将开发一个事件驱动的框架。

    消息系统

    事件驱动框架参照一些消息系统中的模式。我们将进行如下类比。 事件与消息,事件处理器与通道,事件转发器与路由。

    一个实例是邮递系统。邮递员有一个背包里面有若干信件,上面有要寄送的地址,邮递员必须将信件寄送到相应的地址。这个过程可以按如下形式描述?

    procedure deliver_letters(satchel):
      repeat
        letter := next_letter(satchel)
        for home in homes do:
          if letter.destination == home:
            deliver_letter(home)
          end if
        end for
      until satchel is empty
    end procedure

    这个例子可以使用事件驱动编程建模。接下来我们将以最抽象的形式来开发一个框架,来对系统建模。

    消息

    每个消息有一个具体的类型,通过类型将消息与处理器相关联。消息接口定义如下。

    public interface Message {
      public Class<? extends Message> getType();
    }

    管道(Channel)

    管道与某种类型的消息关联。我们将消息派发给每种消息各自的管道进行处理。

    public interface Channel<E extends Message> {
      public void dispatch(E message);
    }

    动态路由

    消息系统的交互是通过路由完成。路由负责将给定的消息转发到具体的通道上。初始化阶段,路由会注册消息与其关联的通道。随后,由路由转发的消息会自动匹配消息类型及关联的管道,并将消息路由到关联的管道中。

    public interface DynamicRouter<E extends Message> {
      public void registerChannel(Class<? extends E> contentType,
          Channel<? extends E> channel);
      public abstract void dispatch(E content);
    }

    接下来将实现这些接口以便创建一个完整的框架。

    框架实现

    事件

    我们将事件定义为消息的子类。

    import Message;
    
    public class Event implements Message {
      @Override
      public Class<? extends Message> getType() {
        return getClass();
      }
    }

    处理器

    处理器最终接收事件,并处理,这里将实现管道接口。

    import Channel;
    
    public class Handler implements Channel<Event> {
      @Override
      public void dispatch(Event message) {
        System.out.println(message.getClass());
      }
    }

    事件转发器

    事件转发器用来注册消息与通道。本例中,我们注册处理器及其关联的事件类。我们使用HashMap将这件与处理器关联。

    import java.util.HashMap;
    import java.util.Map;
    
    import edu.giocc.util.router.Channel;
    import edu.giocc.util.router.DynamicRouter;
    
    public class EventDispatcher implements DynamicRouter<Event> {
      private Map<Class<? extends Event>, Handler> handlers;
    
      public EventDispatcher() {
        handlers = new HashMap<Class<? extends Event>, Handler>();
      }
    
      @Override
      public void registerChannel(Class<? extends Event> contentType,
          Channel<? extends Event> channel) {
        handlers.put(contentType, (Handler)channel);
      }
    
      @Override
      public void dispatch(Event content) {
        handlers.get(content.getClass()).dispatch(content);
      }
    }

    基本框架完成,接下来进行行测。

    public class Program {
      public static void main(String[] args) {
        EventDispatcher dispatcher = new EventDispatcher();
        dispatcher.registerChannel(Event.class, new Handler());
        dispatcher.dispatch(new Event());
      }
    }

    在应用程序中进行扩展

    现在框架已经建立,通用框架一般应具备下列特征。

    • 控制反转 如同消息系统一样,框架来控制数据流。
    • 扩展性 应用程序可根据使用来进行扩展。
    • 框架代码不可修改 不能修改框架代码。

    上述提到的属性解释了应用如何与框架连接。框架仅仅是架构的一个抽象。

    这里写图片描述

    Handler和Event类是framework层的类。基于框架开发的代码应该位于应用层。框架职责是抽象并提供事件驱动架构的基础工具。

    现在我们可以继承Handler类,来创建我们的事件处理器,继承Event类来创建我们的事件。此外,我们在派发器中注册这些事件处理器与事件。

    下一篇文章中将展示一个框架的具体实现,以便模拟事件驱动系统。

    原文地址

    http://www.giocc.com/writing-an-event-driven-framework-with-java.html

    展开全文
  • 我们就写了6个关键字动作,结果在if-else-if-else中我们需要写好多个判断分支,试想一下,如果按照这个思路,一个项目的自动化,有几百个测试用例,其中一个测试用例有好几个测试场景,那么我们的动作关键字驱动会写...

           在前面几篇文章,我们发现了,如果要运行任何操作,我们需要利用Apache POI去Excel关键字这列拿数据并和代码中相关静态方法去匹配。到目前,我们就写了6个关键字动作,结果在if-else-if-else中我们需要写好多个判断分支,试想一下,如果按照这个思路,一个项目的自动化,有几百个测试用例,其中一个测试用例有好几个测试场景,那么我们的动作关键字驱动会写几千甚至上万个,难道也需要写上万个if判断吗?这样显然不合理,效率太低,代码可维护太差。

     

    使用Java反射类

     

           在Java中利用反射类是可以解决上面提到的问题。反射是一种非常有用的方法,可以在运行时处理Java类,因为它可以用来装载Java类、调用它的方法或者在运行时分析类。(在这里,其实我也不了解什么是Java反射机制)这里我们先不管,按照下面代码进行敲一遍,然后,自己再去百度或者谷歌搜索下java反射机制。

     

            让我来给你用其他方式来解释为什么要用到反射,这样你才能更好第理解。在我们当前的关键字驱动框架中,我们需要在if-else代码中去写上各种动作的关键字代码,让程序去循环判断并执行。前面我们提到,为了避免这个情形,我们需要采用Java的反射机制。反射的作用场景就是这样,当你添加了新的关键字方法代码,反射类会在运行时间加载所有的方式或者动作关键字的类。(我额外添加的,不知道这么去解释是否适合:这个可以利用我们POM中的页面工厂类的初始化作用去理解,只有我们初始化了页面,就自动化初始化了页面的元素和所有页面相关方法。)

     

    ActionsKeywords.java代码不变和前面文章保持一致。调用selenium的driverScript.java的代码我们修改如下

    package executionEngine;
    
    import config.ActionsKeywords;
    import utility.ExcelUtils;
    import java.lang.reflect.Method;
    
    
    /**
     * create by Anthony on 2018/1/30
     */
    public class DriverScript {
    
        // 声明一个public static的类对象,所以我们可以在main方法范围之外去使用。
        public static ActionsKeywords actionKeywords;
        public static String sActionKeyword;
        // 下面是返回类型是方法,这里用到反射类
        public static Method method[];
    
    
        // 这里我们初始化'ActionsKeywords'类的一个对象
        public DriverScript() throws NoSuchMethodException, SecurityException, ClassNotFoundException {
            //actionKeywords = new ActionsKeywords()
            // 原文作者是采用上面这个代码,下面的代码是我查找反射资料,是这么获取class对象的
            Class<?> actionKeywords = Class.forName("config.ActionsKeywords");
            method = actionKeywords.getMethods();
        }
    
        public static void main(String[] args) throws Exception {
            // 由于上面初始化反射类写在构造函数,而main方法是第一个被最新,如果不添加
            // 下面这个当前类的初始化代码,就会报method.length空指针异常,我这里暂时这里处理
            // 原文作者不知道为啥没有报错。
            DriverScript ds = new DriverScript();
            String excel_path = "C:\\Users\\Administrator\\Desktop\\SeleniumKeywordDriverFramework\\src\\dataEngine\\dataEngine.xlsx";
            // 加载读取excel文件
            ExcelUtils.setExcelFile(excel_path, "Test Steps");
    
            for (int iRow = 1; iRow <= 6; iRow++) {
                //3表示excel中keyword对应的列的索引,也就是左边数起第4列
                sActionKeyword = ExcelUtils.getCellData(iRow, 3);
                //调用'execute_Actions'方法
                execute_Actions();
            }
    
        }
    
        private static void execute_Actions() throws Exception {
            //循环遍历每一个关键字驱动方法(在actionskeywords.java中)
            // 下面method.length表示方法个数,method变量表示任何一个关键字方法,例如openBrowser()
            for(int i = 0;i < method.length;i++){
                //开始对比代码中关键字方法名称和excel中关键字这列值是否匹配
                if(method[i].getName().equals(sActionKeyword)){
                    //一但匹配到相关关键字方法,就会调用对应的关键字静态方法
                    method[i].invoke(actionKeywords);
                    //一旦任何关键字被执行,利用break语句去跳出for循环。
                    break;
                }
            }
        }
    
    }
    
           上面原作者采用new的方式去得到反射类的对象,我改成了forName,但是在main方法第一行还是需要添加创建一个当前driverScript类的对象,否则由于代码执行顺序,先执行main方法,然后执行构造方法,这样由于actionKeywords没有初始化,所以声明的类对象method得到是null,从而method.length报空指针错误。

           在使用了Java反射机制之后,上面的代码要比前面一篇那么多if-else if要简洁,好看多了。这样就不用写很多判断分支语句。下面一篇介绍如何把一些常量放在一个类文件,这样就不用在代码中写死,也就是所谓硬编码问题。



    展开全文
  • Java测试框架

    千次阅读 2017-08-31 15:01:01
    前言在项目开发过程中必不可少的会用到测试框架来检查自己的代码逻辑,可能大多数人和我一样从来没有怎么重视过测试代码,认为测试代码存在与否的意义不大。但是,看过很多大牛的项目后,发现他们写的项目中测试用例...

    前言

    在项目开发过程中必不可少的会用到测试框架来检查自己的代码逻辑,可能大多数人和我一样从来没有怎么重视过测试代码,认为测试代码存在与否的意义不大。但是,看过很多大牛的项目后,发现他们写的项目中测试用例的代码远多于实际代码。所以,为了向大牛们看齐,最近又重新学习了一波之前用到过的测试框架,在这里做一个小结。

    1. 常见测试框架

    我在项目开发过程中使用的单元测试框架有Junit、TestNG以及Mockito,Junit和TestNG使用的比较多,Mockito最近才开始使用。对于Junit和TestNG的用法我就不多做介绍了,相信大家都会使TestNG和JUnit是针对Java语言的两个比较常用的测试框架。JUnit出现的比较早,但是早期的JUnit 3对测试代码有非常多的限制,使用起来很不方便,后来的JUnit 4得到很大的改进。TestNG的出现介于JUnit 3和JUnit 4,但是TestNG在很多方面还要优于JUnit 4。下面从整体上对TestNG和JUnit 4进行比较全面的比较。

    TestNG与JUnit的相同点
    1. 使用annotation,且大部分annotation相同。
    2. 都可以进行单元测试(Unit test)。
    3. 都是针对Java测试的工具。

    TestNG与JUnit的不同点:
    1. JUnit只能进行单元测试,TestNG可以进行单元测试,功能测试,端到端测试,集成测试等。
    2. TestNG需要一个额外的xml配置文件,配置测试的class、method甚至package。
    3. TestNG的运行方式更加灵活:命令行、ant和IDE,JUnit只能使用IDE。
    4. TestNG的annotation更加丰富,比如@ExpectedExceptions、@DataProvider等。
    5. 测试套件运行失败,JUnit 4会重新运行整个测试套件。TestNG运行失败时,会创建一个XML文件说明失败的测试,利用这个文件执行程序,就不会重复运行已经成功的测试。

    TestNG比JUnit 4灵活性的体现:
    1. JUnit 4中必须把@BeforeClass修饰的方法声明为public static,这就限制了该方法中使用的变量必须是static。而TestNG中@BeforeClass修饰的方法可以跟普通函数完全一样。
    2. JUnit 4测试的依赖性非常强,测试用例间有严格的先后顺序。前一个测试不成功,后续所有的依赖测试都会失败。TestNG 利用@Test 的dependsOnMethods属性来应对测试依赖性问题。某方法依赖的方法失败,它将被跳过,而不是标记为失败。
    3. 对于n个不同参数组合的测试,JUnit 4要写n个测试用例。每个测试用例完成的任务基本是相同的,只是受测方法的参数有所改变。TestNG的参数化测试只需要一个测试用例,然后把所需要的参数加到TestNG的xml配置文件中。这样的好处是参数与测试代码分离,非程序员也可以修改参数,同时修改无需重新编译测试代码。
    4. JUnit 4的测试结果通过Green/Red bar体现,TestNG的结果除了Green/Red bar,还有test-output文件夹,对测试结果的描述更加详细,方便定位错误。

    相比于Junit和TestNG,mockito的功能是解决units之间由于耦合而难于被单独测试的问题,下面做下简单介绍,具体的用法请参照http://site.mockito.org/

    什么是mock?
    在软件开发的世界之外, “mock”一词是指模仿或者效仿。 因此可以将“mock”理解为一个替身,替代者. 在软件开发中提及”mock”,通常理解为模拟对象或者Fake。

    为什么需要Mock?
    Mock是为了解决units之间由于耦合而难于被测试的问题。所以mock object是unit test的一部分。

    Mock的好处是什么?
    提前创建测试,TDD(测试驱动开发)这是个最大的好处吧。
    如果你创建了一个Mock那么你就可以在service接口创建之前写Service Tests了,这样你就能在开发过程中把测试添加到你的自动化测试环境中了。换句话说,模拟使你能够使用测试驱动开发。

    团队可以并行工作
    这类似于上面的那点;为不存在的代码创建测试。但前面讲的是开发人员编写测试程序,这里说的是测试团队来创建。当还没有任何东西要测的时候测试团队如何来创建测试呢?模拟并针对模拟测试!这意味着当service借口需要测试时,实际上QA团队已经有了一套完整的测试组件;没有出现一个团队等待另一个团队完成的情况。这使得模拟的效益型尤为突出了。

    你可以创建一个验证或者演示程序
    由于Mocks非常高效,Mocks可以用来创建一个概念证明,作为一个示意图,或者作为一个你正考虑构建项目的演示程序。这为你决定项目接下来是否要进行提供了有力的基础,但最重要的还是提供了实际的设计决策。

    为无法访问的资源编写测试
    这个好处不属于实际效益的一种,而是作为一个必要时的“救生圈”。有没有遇到这样的情况?当你想要测试一个service接口,但service需要经过防火墙访问,防火墙不能为你打开或者你需要认证才能访问。遇到这样情况时,你可以在你能访问的地方使用MockService替代,这就是一个“救生圈”功能。

    Mock 可以交给用户
    在有些情况下,某种原因你需要允许一些外部来源访问你的测试系统,像合作伙伴或者客户。这些原因导致别人也可以访问你的敏感信息,而你或许只是想允许访问部分测试环境。在这种情况下,如何向合作伙伴或者客户提供一个测试系统来开发或者做测试呢?最简单的就是提供一个mock,无论是来自于你的网络或者客户的网络。

    隔离系统
    有时,你希望在没有系统其他部分的影响下测试系统单独的一部分。由于其他系统部分会给测试数据造成干扰,影响根据数据收集得到的测试结论。使用mock你可以移除掉除了需要测试部分的系统依赖的模拟。当隔离这些mocks后,mocks就变得非常简单可靠,快速可预见。这为你提供了一个移除了随机行为,有重复模式并且可以监控特殊系统的测试环境。

    其实上面的特点总结成一句话:Mock可以解决测试对象的依赖问题,让测试能够只针对测试对象本身的逻辑,保证测试不受依赖的影响。

    下面有个例子可以清晰的体现这一点,直接上代码:

    public class OrderService {
        private PriceService priceService=new PriceService();
    
        private ProductService productService=new ProductService();
    
        /**
         * 该方法是返回订单信息
         * 依赖价格服务、商品服务
         * @param orderCode
         * @return
         */
        public OrderInfo getOrderInfoByOrderCode(String orderCode){
            PriceInfo priceInfo=priceService.getPriceInfoByProductCode("L3001");
            ProductInfo productInfo=productService.getProductInfoByProductCode("L3001");
            OrderInfo orderInfo=new OrderInfo();
            orderInfo.optionText=productInfo.optionText;
            orderInfo.productCode=productInfo.productCode;
            orderInfo.productName=productInfo.productName;
            orderInfo.price=priceInfo.price;
            return orderInfo;
        }
    }

    对于上面这个方法,在不使用Mockito来进行测试时,需要价格服务的getPriceInfoByProductCode和商品服务的getProductInfoByProductCode方法开发完成才能进行测试,下面是不使用Mockito的测试代码

    public class OrderServiceTestWithJunit {
        private OrderService orderService;
        private ProductService productService;
        private PriceService priceService;
        @Before
        public void setUp() throws Exception {
            orderService=new OrderService();
            productService=new ProductService();
            priceService=new PriceService();
            ReflectionTestUtils.setField(orderService,"productService",productService);
            ReflectionTestUtils.setField(orderService,"priceService",priceService);
        }
    
        @Test
        public void getOrderInfoByOrderCode() throws Exception {
            OrderInfo orderInfo=orderService.getOrderInfoByOrderCode("testCode");
            Assert.assertNotNull(orderInfo);
        }
    
    }

    这样的确可以完成对订单服务的测试,但是前提是产品服务和价格服务已经完成且保证正确性,如果依赖的服务存在异常,这时异常将会从订单服务抛出,那么定位异常将会非常麻烦。因此,对于这种有很多依赖的测试单元,只使用Junit或者TestNG,想要对测试单元本身的逻辑进行测试,几乎是不可能的。

    下面介绍用Mockito的做法

    public class OrderServiceTestWithMock {
        @Mock
        private ProductService productService;
        @Mock
        private PriceService priceService;
        @InjectMocks
        private OrderService orderService;
        @BeforeClass
        public void setUp(){
            MockitoAnnotations.initMocks(this);
            setMockData();
        }
    
        private void setMockData() {
            when(priceService.getPriceInfoByProductCode(anyString())).thenAnswer(invoke->{
                    PriceInfo priceInfo=new PriceInfo();
                    priceInfo.price= BigDecimal.valueOf(100);
                    return priceInfo;
            }
            );
    
            when(productService.getProductInfoByProductCode(anyString())).thenAnswer(invocation -> {
                ProductInfo productInfo=new ProductInfo();
                productInfo.optionText="10支装";
                productInfo.productCode="L3001";
                productInfo.productName="mock商品";
                return productInfo;
            });
        }
    
        @Test
        public void testGetOrderInfoByOrderCode() throws Exception {
           OrderInfo orderInfo=orderService.getOrderInfoByOrderCode("Test");
           Assert.assertNotNull(orderInfo.optionText);
        }
    
    }

    这样就可以去除订单服务的所有依赖,只对订单服务的逻辑进行测试(其实就是可以甩锅!!!)。
    源码见: https://git.oschina.net/F4T/test-demo.git

    2. 在项目中如何选择测试框架?

    JUnit 4 和 TestNG 在表面上是相似的,然而设计 JUnit 的目的是为了分析代码单元,而 TestNG 的预期用途则针对高级测试。对于大型测试套件,我们不希望在某一项测试失败时就得重新运行数千项测试,TestNG 的灵活性在这里尤为有用。这两个框架都有自己的优势,需要按照测试要求来选择,不过对于开发来说其实选择那一个没有什么太大的区别,因为用到的测试框架的功能不多,都是些基本的用法,对于微服务或者多人协作完成一个功能的情况下,Mockito是必须接入。

    3.总结

    其实开发写测试用例是一个不断梳理自己代码逻辑的过程,可能在写的过程中你就发现了逻辑上的漏洞。

    展开全文
  • android驱动框架介绍

    千次阅读 2019-06-28 11:42:46
    android驱动框架介绍 了解android驱动框架: 1.方法1——jni调用底层驱动 在android框架中写入c/c++直接调用底层linux驱动,并向上提供jni接口给应用程序: 优点:简单易行; 缺点:主要在于驱动程序,由于...

    android驱动框架介绍

    了解android驱动框架:

    1.方法1——jni调用底层驱动

     

    在android框架中写入c/c++直接调用底层linux驱动,并向上提供jni接口给应用程序:

    优点:简单易行;

    缺点:主要在于驱动程序,由于在linux中需要遵循GPL协议,需要开源,而许多厂商的一些代码不希望开源。

     

    2.方法2——增加硬件抽象层

    将驱动程序一分为二,一部分开源在内核中,一部分不开源在android框架中:

     

     

    led android驱动:
     

    从这里我们将看到整个应用框架层到底层驱动的走向。首先,无论是哪种方法,我们都需要实现一个linux驱动以供上层访问led资源。

     

    1.linux驱动:

    linux的字符设备驱动编写:

     

    #include#include#include#include#include#include#include#includestatic struct cdev dev;
    static dev_t dev_num;
    
    
    #define GPM4CON 0x110002E0
    #define GPM4DAT 0X110002E4
    
    #define LED_ON _IOW('G',0,int)
    #define LED_OFF _IOW('G',1,int)
    
    static unsigned int *led_con = NULL;
    static unsigned int *led_dat = NULL;
    
    
    static struct class *led_class = NULL;
    
    
    static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    {
    		switch(cmd)
    		{
    				case LED_ON:
    				{
    						writel(readl(led_dat)& ~(0x1<<arg), led_dat);
    						break;		
    				}
    					
    				case LED_OFF:
    				{
    						writel(readl(led_dat)| (0x1<<arg), led_dat);
    						break;		
    				}
    					
    				default:
    				{
    						return -EINVAL;		
    						break;
    				}
    			
    		}
    	
    		return 0;
    }
    
    static struct file_operations led_fops = {
    		.owner = THIS_MODULE,
    		.unlocked_ioctl = led_ioctl,
    };
    
    static void hw_init()//GPM4_0-3
    {
    			//1.2.1 映射地址
    			led_con = ioremap(GPM4CON,4);
    			led_dat = ioremap(GPM4DAT,4);
    			
    			//1.2.2 设置为输出状态
    			writel((readl(led_con)& ~0xffff) | 0x1111, led_con);
    			
    			//1.2.3 设置为高电平
    			writel(readl(led_dat)|0xf, led_dat);
    	
    }
    
    
    static int led_init()
    {
    	  //1.1 cdev字符设备初始化
    		//1.1.1 分配cdev结构(静态分配) 
    		
    		//1.1.2 初始化cdev结构
    		alloc_chrdev_region(&dev_num,0,1,"callon_led");
    		cdev_init(&dev, &led_fops);
    		dev.owner = THIS_MODULE;
    		
    		//1.1.3 注册cdev结构 
    		cdev_add(&dev,dev_num,1);
    		
    		//1.2 硬件初始化
    		hw_init();
    		
    		//1.3 创建设备文件
    		//1.3.1 创建类
    		led_class = class_create(THIS_MODULE,"callon_led");
    		
    		//1.3.2 创建设备
    		device_create(led_class,NULL,dev_num,NULL,"%s","callon_led");
    		
    		printk("init led device is OK!\n");
    		return 0;
    }
    
    static void led_exit()
    {
    		device_destroy(led_class,dev_num);
    		class_destroy(led_class);
    	
    		iounmap(led_dat);
    		iounmap(led_con);
    		
    		cdev_del(&dev);
    		unregister_chrdev_region(dev_num,1);
    }
    
    
    
    
    module_init(led_init);
    module_exit(led_exit);


     

     

     

     

    2 实现第一种方法:

    首先,说明一下为什么使用jni:

    1.基于对代码的保护,java相对容易被反编译,而c/c++库反汇编难度较大;

    2.可以方便地使用现存的开源库;

    3.提高执行效率;

    4.java在某些文件操作方面,找不到相关的API,如此处的ioctl.

    其次,为什么使用ndk?

    ndk提供了一系列的工具,能够帮助开发者快速开发c/c++的动态库,并能自动将.so动态库和java一起打包成apk.

    第一种方法的设计思路如下所示:

    在第一步中想要使用javah命令自动产生头文件需要先编写app程序,但是此时的app程序并不需要很完善,只需要提出一个你想要的native接口就好(但是你的android程序必须要Rebuild正确才会正确产生头文件):

     

    package com.led.ndk.example.callon.ndk_led;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.CheckBox;
    
    public class MainActivity extends Activity {
    
        private CheckBox[] Led = new CheckBox[4];
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Led[0] = (CheckBox)findViewById(R.id.checkbox_led1);
            Led[1] = (CheckBox)findViewById(R.id.checkbox_led2);
            Led[2] = (CheckBox)findViewById(R.id.checkbox_led3);
            Led[3] = (CheckBox)findViewById(R.id.checkbox_led4);
        }
    
        private void SendCmd(View view)
        {
            for(int i =1; i<5; i++)
            {
                if(Led[i].isChecked())
                {
                    cmdLeds(1, i);
                }
                else
                {
                    cmdLeds(0, i);
                }
            }
        }
    
        public native void cmdLeds(int cmd, int arg);
        
    }


    根据如上简单的app,使用命令:

     

     

    javah -d jni -classpath 你的sdk目录/platforms/你的平台名/android.jar:你的应用程序/app/build/intermediates/classes/debug/ 你的包名.主类名

    如:

     

    javah -d jni -classpath /opt/AndroidSDK/platforms/android-23/android.jar:/home/callon/Downloads/callon_ndk_led/ndk_led/app/build/intermediates/classes/debug/ com.led.ndk.example.callon.ndk_led.MainActivity


    此时自动产生出jni文件夹,其中包含头文件com_led_ndk_example_callon_ndk_led_MainActivity.h,头文件比较重要的:

     

     

    JNIEXPORT void JNICALL Java_com_led_ndk_example_callon_ndk_1led_MainActivity_cmdLeds
      (JNIEnv *, jobject, jint, jint);

     

    这也就是我们编写源文件需要实现的方法名,下面直接编写源文件:

     

    #include "com_led_ndk_example_callon_ndk_led_MainActivity.h"
    #include#include#include#include#include#include#include#define LED_ON _IOW('G',0,int)
    #define LED_OFF _IOW('G',1,int)
    
    
    JNIEXPORT void JNICALL Java_com_led_ndk_example_callon_ndk_1led_MainActivity_cmdLeds
      (JNIEnv * env, jobject thiz, jint cmd, jint arg)
    {
    		int fd;
    		int temp_cmd;
    		fd = open("/dev/callon_led",O_WRONLY);
    		
    		if(cmd == 1)
    			temp_cmd = LED_ON;
    		else
    			temp_cmd = LED_OFF;
    			
    		ioctl(fd, temp_cmd, arg);
    		close(fd);
    		  	
    }


    就是一些对内核驱动文件的操作,然后编写Android.mk即makefile:

     

     

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := callon_ndk_led
    LOCAL_SRC_FILES := ndk_led.c
    include $(BUILD_SHARED_LIBRARY)

    此时,在你的jni文件夹应该有这三个文件了,退到jni文件夹之外,使用命令ndk-build即可:

     

     

    callon@ubuntu:~/Downloads/callon_ndk_led/jni$ ls
    Android.mk  com_led_ndk_example_callon_ndk_led_MainActivity.h  ndk_led.c
    callon@ubuntu:~/Downloads/callon_ndk_led/jni$ cd ..
    callon@ubuntu:~/Downloads/callon_ndk_led$ ndk-build 
    [armeabi] Compile thumb  : callon_ndk_led  libs/armeabi/libcallon_ndk_led.so
    callon@ubuntu:~/Downloads/callon_ndk_led$

    最后一步,完善app:

    首先,用Project形式来看我们的app,并在app->src->main下创建一个目录"jniLibs";

    然后,将我们.so所在的armeabi目录拷贝到jniLibs目录下;

    最后在我们的app代码的最后加上:

     

    static
        {
            System.loadLibrary("callon_ndk_led");
        }

    然后Rebuild Project即可!

     

     

    3 实现第二种方法:
    1.HAL程序编写:

    首先在  安卓源代码根目录/hardware/libhardware/modules/下创建自己的hal代码存放路径,如led。

    最终编写的文件为:安卓源代码根目录/hardware/libhardware/modules/led/led_hal.c和Android.mk,安卓源代码根目录/hardware/libhardware/include/hardware/led.h。

     

    #include#include#include#include#include#include#include#include#include#include#define LOG_TAG "callon_led"
    static int fd;
    
    static int led_close(struct hw_device_t *device)
    {
    	struct led_device_t* led = (struct led_device_t*)device;
    	free(led);
    
    	close(fd);
    	return 0;
    }
    
    int led_on(struct led_device_t* dev,int arg)
    {
    	ioctl(fd,LED_ON,arg);
    	return 0;
    }
    
    int led_off(struct led_device_t* dev,int arg)
    {
    	ioctl(fd,LED_OFF,arg);
    	return 0;
    }
    
    static struct led_device_t led_dev = {
    	.led_device = {
    		.tag = HARDWARE_DEVICE_TAG,
    		.close = led_close,
    	},
    	.set_on = led_on,
    	.set_off = led_off,
    };
    
    static int open_led(const struct hw_module_t* module, char const* name,
            struct hw_device_t** device)
    {
    	*device = &led_dev;
    	fd = open("/dev/callon_led",O_RDWR);
    	if(fd < 0)
    	{
    		ALOGD(LOG_TAG, "open device fail!");
    		return -1;
    	}
    	return 0;
    }
    
    static struct hw_module_methods_t led_methods = {
        .open =  open_led,
    };
    
    
    struct hw_module_t HAL_MODULE_INFO_SYM = {
        .tag = HARDWARE_MODULE_TAG,
        .id = "led",
        .methods = &led_methods,
    };


     

     

     

    led.h

     

    #ifndef _HARDWARE_LED_H
    #define _HARDWARE_LED_H
    
    #include#define LED_ON _IOW('G',0,int)
    #define LED_OFF _IOW('G',1,int)
    
    struct led_device_t {
    	struct hw_device_t led_device;
    	int (*set_on)(struct led_device_t* dev,int arg);//means led_number
    	int (*set_off)(struct led_device_t* dev,int arg);
    };
    
    
    
    #endif  // _HARDWARE_LED_H

     

     

    Android.mk

     

     

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := led.default
    
    # HAL module implementation stored in
    # hw/.default.so
    LOCAL_MODULE_RELATIVE_PATH := hw
    LOCAL_C_INCLUDES := hardware/libhardware
    LOCAL_SRC_FILES := led_hal.c
    LOCAL_SHARED_LIBRARIES := liblog
    LOCAL_MODULE_TAGS := eng
    
    include $(BUILD_SHARED_LIBRARY)

    编译则在  安卓源代码根目录下使用

     

    $ . setenv
    $ lunch
    $ mmm hardware/libhardware/modules/led/

    看到

     

     

    target SharedLib: led.default (out/target/product/tiny4412/obj/SHARED_LIBRARIES/led.default_intermediates/LINKED/led.default.so)
    target Symbolic: led.default (out/target/product/tiny4412/symbols/system/lib/hw/led.default.so)
    Export includes file: hardware/libhardware/modules/led/Android.mk -- out/target/product/tiny4412/obj/SHARED_LIBRARIES/led.default_intermediates/export_includes
    target Strip: led.default (out/target/product/tiny4412/obj/lib/led.default.so)
    Install: out/target/product/tiny4412/system/lib/hw/led.default.so
    make: Leaving directory `/opt/Tiny4412/Android/android-5.0.2'
    
    #### make completed successfully (1 seconds) ####

    即可,最后产生的就在out/target/product/tiny4412/system/lib/hw/led.default.so了。

    我们将system.img重做,这里通过一个脚本./gen-img.sh完成。

     

    2.硬件服务编写:

    首先,Service Manager为了解决访问冲突而存在的,在有Service Manager的基础之上,我们的底层需要先编写硬件服务,注册到Service Manager,我们的app才能通过Service Manager获取到服务,操作底层。

     

    由于涉及到许多目录操作,细化操作后为:

     

    1.创建 ILedService.aidl

    仿照 frameworks/base/core/java/android/os/IVibratorService.aidl 

     

    package android.os;
    
    /** {@hide} */
    interface ILedService
    {
        int LedOpen();
        int LedOn(int arg);
        int LedOff(int arg);
    }

     

    2.修改frameworks/base/Android.mk 增加

    core/java/android/os/ILedService.aidl \

    3.自动生成ILedService.java

    mmm frameworks/base/编译自动生成out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/ILedService.java

    4.创建 LedService.java 实现接口函数

    仿照frameworks/base/services/core/java/com/android/server/VibratorService.java 

     

    package com.android.server;
    
    import android.util.Slog;
    import android.os.ILedService;
    
    public class LedService extends ILedService.Stub{
        private static final String TAG = "LedService";
        
    	public LedService() 
    	{
    		Slog.d(TAG,"LedService");
    	}
        	public int LedOpen() throws android.os.RemoteException
    	{
    		return native_LedOpen();
    	}
        	public int LedOn(int arg) throws android.os.RemoteException
    	{
    		return native_LedOn(arg);
    	}
    	public int LedOff(int arg) throws android.os.RemoteException
    	{
    		return native_LedOff(arg);
    	}      
            
    	public static native int native_LedOpen();
    	public static native int native_LedOn(int arg);
    	public static native int native_LedOff(int arg);
    }

     

     

    5.将服务注册到Service Manager当中 修改frameworks/base/services/java/com/android/server/SystemServer.java
    参考vibrator修改的地方

    LedService led = null;

     

    Slog.i(TAG, "Led Service");
                led = new LedService();
                ServiceManager.addService("led", led);


    6.实现com_android_server_LedService.cpp

    为什么需要它?因为我们的hal代码并没有提供jni的接口(这里提供了一种新的方法来提供native方法,之前是自动产生头文件然后来实现的)。

    根据frameworks/base/services/core/jni/com_android_server_VibratorService.cpp

     

    /*
     * Copyright (C) 2009 The Android Open Source Project
     *
     * 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.
     */
    
    #define LOG_TAG "LedService"
    
    #include "jni.h"
    #include "JNIHelp.h"
    #include "android_runtime/AndroidRuntime.h"
    
    #include#include#include#includestruct led_device_t *led_dev;
    
    namespace android
    {
    
    static jint LedOpen(JNIEnv *env, jobject clazz)
    {
    	hw_module_t *module;
    	hw_device_t *device;	
    	hw_get_module("led",(hw_module_t const **)&module);
    
    	module->methods->open(module, NULL, &device);
    	
    	led_dev = (struct led_device_t*)device;
    	return 0;
    }
    
    static jint LedOn(JNIEnv *env, jobject clazz, int arg)
    {
    	led_dev->set_on(led_dev,arg);
    	return 0;
    }
    
    static jint LedOff(JNIEnv *env, jobject clazz, int arg)
    {
        	led_dev->set_off(led_dev,arg);
    	return 0;
    }
    
    static JNINativeMethod method_table[] = {
        { "native_LedOpen", "()I", (void*)LedOpen },
        { "native_LedOn", "(I)I", (void*)LedOn },
        { "native_LedOff", "(I)I", (void*)LedOff}
    };
    
    int register_android_server_LedService(JNIEnv *env)
    {
        return jniRegisterNativeMethods(env, "com/android/server/LedService",
                method_table, NELEM(method_table));
    }
    
    };


     

     

    7.注册native接口

     

    在frameworks/base/services/core/jni/onload.cpp中添加

     

    int register_android_server_LedService(JNIEnv* env);

     

     

    register_android_server_LedService(env);

     

     

    8.修改Android.mk

    在frameworks/base/services/core/jni/Android.mk中加入自己写的com_android_server_LedService.cpp

     

    $(LOCAL_REL_DIR)/com_android_server_LedService.cpp \

     

    9.mmm frameworks/base/services/编译

    Copying: out/target/common/obj/JAVA_LIBRARIES/services_intermediates/classes.dex
    target Jar: services (out/target/common/obj/JAVA_LIBRARIES/services_intermediates/javalib.jar)
    Install: out/target/product/tiny4412/system/framework/services.jar
    make: Leaving directory `/opt/Tiny4412/Android/android-5.0.2'
    
    #### make completed successfully (50 seconds) ####

     

    其中碰到一阵错误,非常无语:

     

    make: Entering directory `/opt/Tiny4412/Android/android-5.0.2'
    make: *** No rule to make target `frameworks/base/services/core/.java', needed by `out/target/common/obj/JAVA_LIBRARIES/services.core_intermediates/classes-full-debug.jar'.  Stop.
    make: Leaving directory `/opt/Tiny4412/Android/android-5.0.2'
    
    #### make failed to build some targets (1 seconds) ####

    直接不往下编译,直接报错,非常难找错误,最后发现由于LedService.java的文件名多了个空格。出现这种错误一定要耐心,一定是某个小地方出错的。
     

     

    最后继续使用./gen-img.sh完成system.img的编译,烧写进开发板,为写应用程序做准备。

     

    3.应用程序设计:

     

    package com.led.hal.example.callon.callonhalled;
    
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.CheckBox;
    import android.os.ILedService;
    import android.os.ServiceManager;
    
    public class MainActivity extends AppCompatActivity {
    
        private CheckBox[] Led = new CheckBox[4];
        private ILedService iLedService = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Led[0] = (CheckBox)findViewById(R.id.checkbox_led1);
            Led[1] = (CheckBox)findViewById(R.id.checkbox_led2);
            Led[2] = (CheckBox)findViewById(R.id.checkbox_led3);
            Led[3] = (CheckBox)findViewById(R.id.checkbox_led4);
            iLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
            try {
                iLedService.LedOpen();
            }catch(RemoteException e){
                e.printStackTrace();
            }
        }
    
        private void SendCmd(View view)
        {
            for(int i =1; i<5; i++)
            {
                if(Led[i].isChecked()) {
                    try {
                        iLedService.LedOn(i);
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                }
                else {
                    try {
                        iLedService.LedOff(i);
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    程序其实很简单,但是涉及到android 中隐藏类的使用,我们的ILedService和ServiceManager其实都是隐藏类,你编译不过去的,添加相应的jar包才可以,参考

     

    http://blog.csdn.net/wukunting/article/details/5788196

    首先拷贝out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar到工程下

    然后AndroidStudio中File->Project Structure点击其中的'+'->选择Import .JAR/.AAR Package->选择classes.jar->Finish

    继续在Project Structure下选择app->Dependencies->选择'+'->Module Dependency->选择'classes'即可。

    这时候整个源码都好了,但是下载速度会很慢,改善基于frameworks设计的app下载和运行速度的方案:

    1.修改build.gradle(Module:app)

     

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.2"
    
        defaultConfig {
            applicationId "com.led.hal.example.callon.callonhalled"
            minSdkVersion 21
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
            multiDexEnabled true
        }
    
        dexOptions {
            javaMaxHeapSize "4g"
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        testCompile 'junit:junit:4.12'
        compile 'com.android.support:appcompat-v7:23.2.0'
        compile project(':classes')
        compile 'com.android.support:multidex:1.0.0'
    }

    2.修改AndroidManifest.xml

     

    在application下增加

    android:name="android.support.multidex.MultiDexApplication"
     

    最后下载运行吧!
     

    展开全文
  • Java 媒体框架 之 JMF

    千次阅读 2012-03-23 22:49:18
    如果想要使用Java中的Swing播放音乐,视频,包括录音,截取录像等等,就要用到Java的媒体框架JMF。 Java媒体框架(JMF)使你能够编写出功能强大的多媒体程序,却不用关心底层复杂的实现细节。JMF API的使用相对...
  • Java常用框架介绍

    万次阅读 多人点赞 2018-11-06 23:08:06
     框架通常是代码重用,而设计模式是设计重用,架构则介于两者之间,部分代码重用,部分设计重用,...设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一...
  • JAVASSM框架面试题

    万次阅读 多人点赞 2017-11-30 23:02:13
    最全ssm框架面试题
  • Apache Isis:领域驱动设计的Java框架

    千次阅读 2013-01-18 17:04:14
    本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2013/01/apache-isis-java-domain-driven近日,Apache发布了Apache Isis,这是个用于快速开发领域驱动应用的Java框架。用户可以将...
  • 什么是Java框架?主要的Java框架有哪些

    千次阅读 多人点赞 2020-01-17 22:18:35
    什么是Java框架?Java框架有哪些?Java框架可以简化开发难度,便于我们更好的开发程序。所以学好Java框架还是比较重要的。下面就简要描述一下Java开发常用的四大框架,以此来分析。 什么是Java框架 JAVA框架就是一些类...
  • java开源框架

    千次阅读 2012-12-25 15:50:17
    Spring Framework 【Java开源 J2EE框架】  Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的...
  • 各种JAVA开发框架

    千次阅读 2010-01-31 22:01:00
    【IT168 文档】Spring Framework 【Java开源JEE框架】 Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring...
  • 关键字驱动框架入门教程-1-介绍

    千次阅读 2018-01-29 22:50:50
    之前在群里,看到很多人在讨论关键字驱动框架,我之前有使用过别人写的关键字驱动框架的经历,其实我是比较不喜欢这个框架的,它更多少是作为一个开发或者测试开发人员,开发的一个框架或者工具,目的是让不懂代码的...
  • Java开源框架Netty

    千次阅读 2014-10-11 16:53:40
     Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说,Netty 是一个基于NIO的客户,服务器端编程框架...
  • Java框架介绍

    千次阅读 2016-05-03 11:49:17
    Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发...
  • 事件驱动框架(二)——状态机

    千次阅读 2016-11-01 13:27:49
    事件驱动框架(二) 说明 本篇接上一篇事件驱动框架之后
  • JavaSSM框架精选50道面试题

    万次阅读 多人点赞 2019-02-13 19:04:43
    1.什么是MVC框架?传统MVC框架存在的问题是什么? MVC框架是为了解决传统MVC模式(Jsp + Servlet + JavaBean)的一些问题而出现的框架。 传统MVC模式存在问题: 1.所有的Servlet和Servlet映射都要配置在web.xml中,...
  • 前面一篇,我们大概了解了什么是关键字驱动框架和它的优点。这篇,我们就来介绍搭建这个关键字驱动框架的步骤的第一个步骤。   我把这个过程分成12个步骤:   1.自动化实现一个端对端的流程 2.区分和实现动作...
  • 基于Java NIO框架区别对比

    千次阅读 2018-05-23 08:58:08
    通信框架流行基于Java NIO通信框架有Mina、Netty、Grizzly等。接下来说下它们之间的对比。二.它们的出身1、Mina出身于开源界的大牛Apache组织;2、Netty出身于商业开源大亨Jboss;3、Grizzly则出身于土鳖Sun公司。三...
  • java流行框架有哪些?

    千次阅读 2015-06-25 08:39:53
    常见JAVA框架 Spring Framework 【Java开源JEE框架】 技术资料下载地址:http://pan.baidu.com/s/1mgiSTYw Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法...
  • 常见JAVA框架

    万次阅读 2013-04-12 15:01:15
    Spring Framework 【Java开源JEE框架】 Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的架构...
  • java开源框架简介

    千次阅读 2008-01-22 10:41:00
    Spring Framework 【Java开源JEE框架】Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的架构基础是基于...
  • Java 十大常用框架

    千次阅读 2019-07-16 07:50:14
    十大常用框架: 一、SpringMVC 二、Spring 三、Mybatis 四、Dubbo 五、Maven ...Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 199,423
精华内容 79,769
关键字:

java驱动框架

java 订阅