2015年7月31日星期五

定制自己的Log日志工具

为了方便调试,编程的时候写入了很多的Log。如果项目完成的时候,一一删除是一个头疼的事情,可是不删除的话又会输出大量我们不愿展现出来的信息,可能会是机密,况且这也很拖累运行效率。

so, what should we do?

Is there anyway to solve this problem?

很简单,把所有的Log都写进一个单独的类中,类中实现自定义方法用于输出,然后项目中再需要打印的时候再调用此类中方法。不用的时候,单独处理此类即可。貌似描述得有点干吧,上代码!

import android.util.Log;

public class LogUtil {
public static final int VERBOSE = 1;
public static final int DEBUG = 2;
public static final int INFO = 3;
public static final int WARN = 4;
public static final int ERROR = 5;
public static final int NOTHING = 6;
public static final int LEVEL = VERBOSE;

public static void v(String tag, String msg) {
if (LEVEL <= VERBOSE) {
Log.v(tag, msg);
}
}

public static void d(String tag, String msg) {
if (LEVEL <= DEBUG) {
Log.d(tag, msg);
}
}

public static void i(String tag, String msg) {
if (LEVEL <= INFO) {
Log.i(tag, msg);
}
}

public static void w(String tag, String msg) {
if (LEVEL <= WARN) {
Log.w(tag, msg);
}
}

public static void e(String tag, String msg) {
if (LEVEL <= ERROR) {
Log.e(tag, msg);
}
}

}

在LogUtil中定义了VERBOSE、DEBUG、INFO、WARN、ERROR、NOTHING这六个整型常量,其对应的值都是递增的。然后定义一个LEVEL常量,其值可以指定为上面六常量之一。

LogUtil实现了v(),d(),i(),w(),e()五个自定义的Log方法,在其内部分别调用Log.v()等来打印日志。在自定义的方法中加入了if条件判断,当LEVEL常量满足某一条件时才会打印。

这就是Log日志工具。

在项目中,当需要打印DEBUG级别的日志时可以这样写,

LogUtil.d("TAG", "debug log");

控制LEVEL的值可以控制日志的打印行为,如将LEVEL定义为VERBOSE可以将所有的日志都打印出来,使其等于WARN可以将警告以上级别的日志打印出来,使其等于NOTHING可以将所有的日志都屏蔽掉,这就解决了文前提高的问题。

LOL !




Android中的context浅析

在Android系统中,有很多的service。我们的程序如果用到系统功能,一般都是调用服务间接完成的。也就是在Android系统中存在许多C/S架构。context的作用,就是android应用连接service的桥梁。比如Activity中有一个方法,getSystemService()。这个方法调到最后,实际上是调用的ContextImpl的getSystemService()方法,而ContextImpl是对Context的实现

      Context不是函数而是一个类——如果不太了解面向对象,可以把“类”看做一种数据类型,就像int,不过类型为“类”的数据(称为对象)可能储存远比int多的信息,比如这里的类型为Context的对象就储存关于程序、窗口的一些资源

        有些函数调用时需要一个Context参数,比如Toast.makeText,因为函数需要知道是在哪个界面中显示的Toast

        再比如,Button myButton = new Button(this); 这里也需要Context参数(this),表示这个按钮是在“this”这个屏幕中显示的

        Android开发使用(纯粹的)面向对象语言,一切都是对象,就连我们写的函数都是对象的函数。

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toast.makeText(this,
                "OK!",
                Toast.LENGTH_LONG).show();
        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(new Button.OnClickListener(){
            public void onClick(View v)
            {
                Toast.makeText(MainActivity.this,
                        "Hello, world!",
                        Toast.LENGTH_LONG).show();
            }
        });
    }
}
      这里OnCreate就是MainActivity的对象的函数(MainActivity是类),所以这个函数中的this就表示当前的、包含这个函数的MainActivity对象。

      MainActivity extends Activity,意思是MainActivity 继承 Activity,即MainActivity 是 Activity 的一种,所有的MainActivity 都是 Activity。同样,在Android文档中Activity继承ContextThemeWrapper,ContextThemeWrapper继承ContextWrapper,ContextWrapper继承Context。所以this这个MainActivity也是Context,把this传入Toast.makeText表示“OK!”是在当前的MainActivity对象(也是Context)中显示的。

      对于显示"Hello, world!"的Toast.makeText,这个函数在onClick中,而onClick是new Button.OnClickListener(){...}这个没有名字的类的函数,this表示匿名类的对象,不表示MainActivity对象,所以这里用MainActivity.this,强制选择外面一层MainActivity的this



2015年7月30日星期四

调用手机光照传感器测光强

娘希匹的,昨天就写好了这个blog,发布的时候翻墙失败,也没保存成功,现在重写。

简单调用手机的光照传感器来检测环境的光强,很easy哒。

Android的每个传感器的用法都很相似,首先要获取SensorManager的实例,

1.获取SensorManager实例

SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

2.调用具体的传感器

SensorManager是系统所有传感器的管理器,有了它的实例后就可以调用getDefultSensor()方法来得到任意的传感器类型,

Sesnor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);//这里是光照传感器

4.对传感器输出的信号进行监听

private SensorEventListener listener = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};

这里的SensorEventListener接口定义了两个方法,当传感器精度发生变化时调用onAccuracyChanged方法,当传感器检测到的数值变化时调用onSensorChanged()方法。
onSensorChanged()方法传入了一个名为SensorEvent的参数,其中包含了一个values数组,所有传感器的信息都存放在values数组里。

5.注册传感器的监听器

接下来需要调用SensorManager的registerListener()方法来注册SensorEventListener才能使其生效,这里的registerListener()方法接收了三个参数,第一个为SensorEventListener的实例,第二个为Sensor实例,第三个为传感器输出信息的更新速度,有ENSOR_DELAY_UI、SENSOR_DELAY_NORMAL、SENSOR_DELAY_GAME和SENSOR_DELAY_FASTEST四个可选,它们的更新速度依次递增。

sensorManager.registerListener(listener, sensor,
SensorManager.SENSOR_DELAY_NORMAL);

这就是(光线)传感器的简单用法,接下来上实例吧~~

-----------------------------------------------------

1.布局文件只要一个TextView,简单粗暴,能显示光强即可。

    <TextView
        android:id="@+id/light_level"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:layout_centerInParent="true" 
        android:textSize="20sp"/>

2.MainActivity部分代码,

public class MainActivity extends Activity {

private SensorManager sensorManager;

private TextView lightLevel;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lightLevel = (TextView) findViewById(R.id.light_level);// 获取TextView实例
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);// 获取光照传感器实例
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
sensorManager.registerListener(listener, sensor,
SensorManager.SENSOR_DELAY_NORMAL);// 注册光照传感器的监听器
}

@Override
protected void onDestroy() {
super.onDestroy();
if (sensorManager != null) {
sensorManager.unregisterListener(listener);// 释放传感器
}
}

private SensorEventListener listener = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
// values数组中第一个下标的值就是当前的光照强度
float value = event.values[0];
lightLevel.setText("Current light level is " + value + "lx");
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// 当传感器光强变化时调用
}
};
}

注意,这里的values中只有一个值——光强,存储在values[0]中。

3.运行之



595.01lx(勒克斯),这个值是我测到的座位附近最大值,它是不断变化的呦,这个要感谢可爱的onSensorChanged()方法~

LOL !

2015年7月29日星期三

百度地图baidumapSDK入门之地图显示

摸索了半下午的baidumapSDK_v3.1.0的使用。

1.申请API KEY

地址http://lbsyun.baidu.com/apiconsole/key

填写安全码的时候注意下,其格式为SHA1+";"+包名,

在eclipse->preferences->android->build可找到SHAI fingerprint,

2.配置SDK

先下载之http://developer.baidu.com/map/index.php?title=androidsdk/sdkandev-download,建议一键下载,jdk和docs文档和sample都有了,想要啥有啥.....其实我想单选下载的时候老下载不成功

lib中的baidumapapi_v3_1_0.jar即jar文件放入工程的libs中,

libBaiduMapSDK_v3_1_0.so放入libs->armeabi中,注意,armeabi需要我们自己新建

Properties->Jaca Build Path->Libraies->add JARs 添加我们的baidumapapi_v3_1_0.jar

Properties->Jaca Build Path->Order and Export选中baidumapapi_v3_1_0.jar

Project clean -> clean all即可

3.在AndroidManifest.xml的application中添加API Key

   <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <meta-data 
            android:name="com.baidu.lbsapi.API_KEY"

            android:value="xzBRnhNM24BPN8bPBQVvaio2"/>
         .......
    </application>

添加所需权限

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />

触目惊心好多权限.....

4.布局activity_main.xml文件里简单添加一个地图控件mapView,

  <com.baidu.mapapi.map.MapView
     android:id="@+id/map_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"

     android:clickable="true"/>

5.修改MainActivity.java文件

public class MainActivity extends Activity {

private MapView mapView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 在使用SDK各组件之前初始化context信息,传入ApplicationContext
// 注意该方法要在setContentView方法之前实现
// 注意,在SDK各功能组件使用之前都需要调用SDKInitializer.initialize(getApplicationContext())
// 因此我们建议该方法放在Application的初始化方法中
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.map_view);
}

@Override
protected void onResume() {
super.onResume();
// 在activity执行onResume时执行mapView.onResume(),实现地图生命周期管理
mapView.onResume();

}

@Override
protected void onPause() {
super.onPause();
// 在activity执行onPause时执行mapView.onPause(),实现地图生命周期管理
mapView.onPause();

}

@Override
protected void onDestroy() {
super.onDestroy();
// 在activity执行onDestroy时执行mapView.onDestroy(),实现地图生命周期管理
mapView.onDestroy();
}


}

详细的解释我都写在了代码注释里了,真是一个好习惯

6.运行之,


LOL !