title: 手机信号质量检测

date: June 17, 2015 12:12 AM
categories: android
tags: android


本文介绍了如何检测手机信号质量

Read more   2015/6/25 posted in  Android

GreenDao学习

准备工作

github下载工程

https://github.com/greenrobot/greenDAO

android studio导入DaoExampleGenerator

下载所需的jar包

http://search.maven.org/#search%7Cga%7C1%7CgreenDao
下载greendao-generator-1.3.0.jar 和greendao-1.3.7.jar
http://mvnrepository.com/artifact/org.freemarker/freemarker
下载freemarker-2.3.20.jar

Read more   2015/6/25 posted in  Android

登陆框 UI

实现功能

1.账号自动登陆
2.输入密码时,有全清按钮
3.账号输入失败 > N次,要求用户输入验证码验证

Read more   2015/6/23 posted in  Android

EventBus 学习

一.概述

EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。

实现主要有3个元素组成
1.事件:event
2.发布者:发出消息的一方
3.订阅者:接受并处理消息

Read more   2015/6/22 posted in  Android

取消软键盘自动弹出

在实际操作过程中,edittext会自动获取焦点,导致软键盘自动弹出。虚拟机则不会,做如下修改

在AndroidMainfest.xml中对应的Activity中加入以下属性

Read more   2015/6/19 posted in  Android

日记

宿舍断网一天,感觉人都放空了。开启沉思模式,回顾半个月以来工作。

  • 搭建了这个博客,遇到的问题太多了,以前也没接触过JS、CSS什么的,中国局域网坑了我很久。hexo的3.0版本和之前的配置环境也不一样,用github搭建博客 —> 用hexo生成静态网页 —> clone主题 —> 加入duoshuo评论 —> 动态识别UA。最终弄完还是蛮有成就感的。看代码、写代码、再自己总结一遍。确实是三种不同的境界。

Read more   2015/6/17 posted in  balabala

jni 学习

JNI介绍

JNI概念

Java本地接口,Java Native Interface, 它是一个协议, 该协议用来沟通Java代码和外部的本地C/C++代码, 通过该协议 Java代码可以调用外部的本地代码, 外部的C/C++ 代码可以调用Java代码;

NDK与JNI区别

  • NDK: NDK是Google开发的一套开发和编译工具集, 主要用于Android的JNI开发;
  • JNI : JNI是一套编程接口, 用来实现Java代码与本地的C/C++代码进行交互;

JNI编程步骤:

  • 声明native方法 : 在Java代码中声明 native method()方法;
  • 实现JNI的C/C++方法 : 在JNI层实现Java中声明的native方法, 这里使用javah工具生成带方法签名的头文件, 该JNI层的C/C++代码将被编译成动态库;
  • 加载动态库 : 在Java代码中的静态代码块中加载JNI编译后的动态共享库;

NDK 工具下载

下载地址
https://developer.android.com/ndk/downloads/index.html
Mac下执行

$ chmod a+x android-ndk-r10c-darwin-x86_64.bin
$ ./android-ndk-r10c-darwin-x86_64.bin

创建android工程

声明native方法

native 方法在java中是没有实现的,需要在jni使用c实现

package usbprinter;

/**
 * Created by xuyushi on 15/7/15.
 */
public class usbprinter
{
    public native byte[] read();

}

利用脚本生成头文件

jni目录中添加 xxxx.sh脚本文件

#!/bin/sh
javah -o usbprinter.h -jni -classpath ../src/main/java/ usbprinter.usbprinter

javah -o 生成头文件名.h -jni -classpath 目录名 包名.类名

给脚本添加可执行权限

$ chmod 777 xxxx.sh

执行脚本

./xxxx.sh
执行完毕后会在jni目录下生成 .h文件,如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class usbprinter_usbprinter */

#ifndef _Included_usbprinter_usbprinter
#define _Included_usbprinter_usbprinter
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     usbprinter_usbprinter
 * Method:    read
 * Signature: ()[B
 */
JNIEXPORT jbyteArray JNICALL Java_usbprinter_usbprinter_read
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

编写 .c 实现文件

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "usbprinter.h"

#define BUFF_LENTH (1024*10)


JNIEXPORT jbyteArray JNICALL Java_usbprinter_usbprinter_read
  (JNIEnv *env, jobject this)
{
    //具体实现代码
}
  • JNIEnv参数 : 代表的是Java环境, 通过这个环境可以调用Java里面的方法;
  • jobject参数 : 调用C语言方法的对象, thiz对象表示当前的对象, 即调用JNI方法所在的类;

编写Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
TARGET_PLATFORM := android-19
LOCAL_MODULE    := j
LOCAL_SRC_FILES := usbprinter.c
LOCAL_LDLIBS    := -llog
NDK_APP_DST_DIR := ../src/main/jniLibs/$(TARGET_ARCH_ABI)
include $(BUILD_SHARED_LIBRARY)

````
1. LOCAL_PATH := $(call my-dir) 
一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。
22. include $( CLEAR_VARS)
CLEAR_VARS 由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
3. LOCAL_MODULE :=  HcSyncml
LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包 含任何空格。注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'HcSyncml'的共享库模块,将会生成'libHcSyncml.so'文件。
4. LOCAL_C_INCLUDES :=$(LOCAL_PATH)/extra_inc$(LOCAL_PATH)/main_inc
LOCAL_C_INCLUDES 中加入所需要包含的头文件路径
5. LOCAL_SRC_FILES
LOCAL_SRC_FILES中加入源文件路径(需要编译的文件),多个文件用 ‘\’ 隔开
6. LOCAL_LDLIBS+= -L$(SYSROOT)/usr/lib –llog
表示允许打印Log

## 编写Application.mk
```java
APP_ABI := armeabi armeabi-v7a x86

编译

NDK解压后的文件目录/ndk-build

$ /Users/xuyushi/Downloads/android-ndk-r10e/ndk-build

会在jniLibs目录下,生成响应的.so文件

Java中加载动态库


public class usbprinter
{
    public native byte[] read();
    //静态代码块加载C语言库文件
    static {
        try {
            Log.e("JNI", "load usbprinter");
            System.loadLibrary("usbprinter");
        }catch(UnsatisfiedLinkError e){
            Log.e("JNI"," load fail " + e.toString());
        }
    }

}

操作过程中遇到的问题

问题1

Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk

c文件中没有导入jni.h的头文件.

问题2

jni/CommonError.c:4:1: error: unknown type name 'JNIEXPORT'
jni/CommonError.c:4:19: error: expected '=', ',', ';', 'asm' or '__attribute__'
before 'JNICALL'
jni/CommonError.c:4:19: error: unknown type name 'JNICALL'

c代码实现的方法没有写形参的名字.

问题3

jni/CommonError.c: In function 'Java_com_ycy_commonerrordemo_MainActivity_
sayHelloInC':
jni/CommonError.c:6:3: error: parameter name omitted
jni/CommonError.c:6:3: error: parameter name omitted
jni/CommonError.c:8:13: error: 'env' undeclared (first use in this function)
jni/CommonError.c:8:13: note: each undeclared identifier is reported only once f
or each function it appears in

调用native方法, 没有加载.so文件.

问题4

java.lang.UnsatisfiedLinkError: Couldn't load libcommonerror.so: findLibrary returned null

当前生成的arm平台下的.so文件, 运行在了x86的平台模拟器下.

问题5

java.lang.UnsatisfiedLinkError: Couldn't load libcommonerror.so: findLibrary returned null

解决方案: 在jni的目录下, 创建一个Application.mk, 内容如下:

  • 生成所有的机器码.
    APP_ABI := all

  • 生成单个平台的机器码
    APP_ABI := x86 armeabi

2015/6/15 posted in  Android

GSON 学习

GSONJava中很常用的json库,它是google自定义的json库,功能很强大,支持泛型,它也可以实现从json到java对象的装换,也可以从java对象转换成json数据。

Read more   2015/6/15 posted in  Android

java 反射学习

概要

反射就是能够根据你给出类名实例化出一个实实在在的对象。所以,对象的实例化就不是写死的了,我们可以根据传入的类名不同,从而可以实例化出不同的对象。这种方式可以和工厂设计模式很好的结合,从而可以更加灵活的创建对象

测试用例

定义一个类

定义一个类,用反射来调用他的成员,方法,构造函数等

package com.example.xuyushi.reflecttest;

import android.util.Log;

/**
 * Created by xuyushi on 15/7/14.
 */
public class student {
    static final String TAG = "student";
    private int age;
    private String name;
    private String addresss;

    public student() {
        Log.d(TAG, "none parameter student constructor");
    }

    public student(int age, String name, String addresss) {
        this.age = age;
        this.name = name;
        this.addresss = addresss;
        Log.d(TAG, "3 parameters student constructor");

    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddresss() {
        return addresss;
    }

    public void setAddresss(String addresss) {
        this.addresss = addresss;
    }

    @Override
    public String toString() {
        return super.toString();
    }

    public void printMessage(int age,String name,String adress){
        Log.d(TAG, "name=" + name + ",age=" + age + ",adress=" + adress);
    }
}

测试用例

public class MainActivity extends Activity {
    static final String TAG = "student";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        testReflect();
    }

    private void testReflect() {
        try {
            /**
             * 1 反射出无参的构造方法并得到对象
             * 注意:
             *      1 在Class.forName()中应该传入含有包名的类全名
             *      2 newInstance()方法的本质是调用类的无参Public构造方法
             */
            String className1="com.example.xuyushi.reflecttest.student";
            Class clazz1=Class.forName(className1);
            Object object1=clazz1.newInstance();


            /**
             * 2 反射出带参数的构造方法并得到对象
             */
            String className2="com.example.xuyushi.reflecttest.student";
            Class clazz2=Class.forName(className2);
            Constructor constructor1=clazz2.getConstructor(int.class,String.class,String.class);
            Object object2=constructor1.newInstance(18,"zhangsan","beijing");
            Log.d(TAG, object2.toString());
            /**
             * 3 获取类的私有字段
             * 注意:
             *      获取共有字段应调用clazz3.getField(name)方法
             */
            String className3="com.example.xuyushi.reflecttest.student";
            Class clazz3=Class.forName(className3);
            Field ageField1=clazz3.getDeclaredField("age");
            Log.d(TAG,"ageField1=" + ageField1);

            /**
             * 4 获取和更改某个对象的私有字段
             *   即模拟get()和set()方法
             */
            String className4="com.example.xuyushi.reflecttest.student";
            Class clazz4=Class.forName(className4);
            Field ageField2=clazz4.getDeclaredField("age");
            Object object4=constructor1.newInstance(19,"wangwu","shanghai");
            //取消访问私有字段的合法性检查
            ageField2.setAccessible(true);
            //获取对象的私有字段
            Object ageObject4=ageField2.get(object4);
            Log.d(TAG, "ageObject4=" + ageObject4);

            //再更改对象的私有字段的值
            ageField2.set(object4, 27);
            //重新获得
            Object ageObject5=ageField2.get(object4);
            Log.d(TAG, "ageObject5=" + ageObject5);

            /**
             * 5 调用对象的带参数的方法
             */
            String className5="com.example.xuyushi.reflecttest.student";
            Class clazz5=Class.forName(className5);
            Method method=clazz5.getMethod("printMessage",int.class,String.class,String.class);
            Object object5=clazz5.newInstance();
            method.invoke(object5,50, "lisi","hangzhou");


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

实际用例

开关移动流量需要用到sdk中的隐藏函数,需要利用到反射机制实现

public void toggleMobileData(Context context, boolean enabled) {
        ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        Class<?> conMgrClass = null; // ConnectivityManager类
        Field iConMgrField = null; // ConnectivityManager类中的字段
        Object iConMgr = null; // IConnectivityManager类的引用
        Class<?> iConMgrClass = null; // IConnectivityManager类
        Method setMobileDataEnabledMethod = null; // setMobileDataEnabled方法

        try {
            // 取得ConnectivityManager类
            conMgrClass = Class.forName(conMgr.getClass().getName());
            // 取得ConnectivityManager类中的对象mService
            iConMgrField = conMgrClass.getDeclaredField("mService");
            // 设置mService可访问
            iConMgrField.setAccessible(true);
            // 取得mService的实例化类IConnectivityManager
            iConMgr = iConMgrField.get(conMgr);
            // 取得IConnectivityManager类
            iConMgrClass = Class.forName(iConMgr.getClass().getName());
            // 取得IConnectivityManager类中的setMobileDataEnabled(boolean)方法
            setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
            // 设置setMobileDataEnabled方法可访问
            setMobileDataEnabledMethod.setAccessible(true);
            // 调用setMobileDataEnabled方法
            setMobileDataEnabledMethod.invoke(iConMgr, enabled);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
2015/6/14 posted in  Java

Android 触摸事件传递机制

之前在设置监听事件遇到了一些问题,今天参考学习了一些文档和博客,记录总结view和viewgroup的触摸事件传递

View

常用监听方法

view表示没有子空间的布局,例如textview、button等,MotionEvent分为三种

  • MotionEvent.ACTION_DOWN:按下时候
  • MotionEvent.ACTION_MOVE:滑动时
  • MotionEvent.ACTION_UP:抬起时

常用两种监听事件

Read more   2015/6/14 posted in  Android