24 Sep 2013
QT : 5.0.2
QT Create : 2.7
如果要在qt项目的pro文件中使用PKGCONFIG参数,必须要先配置CONFIG += link_pkgconfig
。例如:
CONFIG += link_pkgconfig
PKGCONFIG += gtk+-2.0 \
glib-2.0 \
ImageMagick \
MagickWand
24 Sep 2013
AIDL简介
Andorid提供了一种轻量级的进程间通信机制:接口描述语言(Android Interface Definition Language),简称AIDL。进程间使用AIDL通信跟使用Intent通信的最大区别在于:前者是同步通信,而后者是异步通信。AIDL的语法与JAVA中的Interface十分相似,对数据类型的支持方面有一些差别,目前AIDL支持的数据类型有:
- Java中的基本数据类型
- String
- List
- CharSequence
- Map
- 其他AIDL生成的接口
- 实现了Parcelable接口并通过值传递的自定义类型
使用AIDL的步骤
- 创建.aidl文件,在文件中声明远程服务的接口
- 在.java文件中实现.aidl中声明的方法
- 在AndroidMainifest中注册上面创建的服务
- 客户端请求绑定服务成功后就可以调用.aidl中声明的方法了
示例解析
项目目录结构:

-
在项目src文件夹下创建IAddService.aidl文件,在aidl声明了一个addOne方法,这个方法简单的把传入的值加上一。
IAddService.aidl:
package net.lnmcc.aidltest.aidl;
interface IAddOneService {
int addOne(int value);
}
保存.aidl文件后,Eclipse将会自动在gen/文件夹下生成一个IAddService.java文件,在后面实现远程服务的时候会使用到其中的抽象类Stub。
-
创建AddService,AddService是一个bound服务,需要实现onBind()方法,它将返回一个IAddService.Stub实例。IBinder简单的理解成进程间通信的通道,可以通过这个通道来实现数据传输。
AddService.java:
public class AddService extends Service {
IAddService.Stub mBinder;
@Override
public void onCreate() {
super.onCreate();
mBinder = new IAddService.Stub() {
//简单的把参数加 1
@Override
public addOne(int value) throws RemoteException {
return value + 1;
}
};
}
//当客户端请求绑定服务成功后,会调用这个方法,并把mBinder返回,
//mBinder引用了一个IAddService.Stub实例,从而使得客户端可以
//成功调用IAddService.Stub中的方法,于是mBinder成了一个通信通道
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
接下来需要在AndroidManifest.xml中声明service:
<service android:name="net.lnmcc.aidltest.AddService" android:process="net.lnmcc.aidltest.AddService" />
需要说明的是android:process指示把这个service当做一个独立的进程来执行,进程名字即”net.lnmcc.aidltest.AddService”。之所以这么做是因为我们是在一个app中演示进程间通信。当运行本例子的时候,使用ps |
grep aidl命令可以看到有2个进程。但在一般情况下,service和client分属于2个app,自然属于两个不同进程,并不需要声明android:process 。 |
-
创建client端,连接IAddService,连接成功后就可以像调用本地方法一样调用远程方法(这里称AIDL中声明的方法为远程方法)。
public class AddClient extends Activity {
IAddService service;
//myServiceConnection用来管理服务连接,
//服务连接成功后会调用onServiceConnected方法,
//断开连接时会调用onServiceDisconnected方法
myServiceConnection connection;
class myServiceConnection implements ServiceConnection {
//服务连接成功时调用,
//IAddService.Stub.asInterface()是一个辅助方法,
//可以把IBinder类型的变量转换成IAddService类型
@Override
public void onServiceConnected(ComponentName name, IBinder boundservice) {
service = IAddService.Stub.asInterface(boundservice);
Toast.makeText(AddClient.this, "Service connected", Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
service = null;
Toast.makeText(AddClient.this, "Service disconnected", Toast.LENGTH_SHORT).show();
}
}
private void initService() {
connection = new myServiceConnection();
//创建一个action intent, 用来连接到远程服务。
//服务名字必须跟前面在AndroidManifest.xml中注册的一样
Intent i = new Intent();
i.setClassName("net.lnmcc.aidltest", net.lnmcc.aidltest.AddService.class.getName());
//请求绑定到Intent指定的远程服务
//第二个参数是用来具体处理连接的ServiceConnection对象
//BIND_AUTO_CREATE标志表示如果服务不存在,则自动启动
if(!bindService(i, connection, Context.BIND_AUTO_CREATE)) {
Toast.makeText(AddClient.this, "Bind Service Failed", Toast.LENGTH_SHORT).show();
}
}
private void releaseService() {
unbindService(connection);
connection = null;
}
private TextView result;
private EditText value;
private Button btnAdd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//这是app的主activity,布局中包括了一个用于输入值的EditText
//一个显示结果的TextView和一个提交按钮
setContentView(R.layout.activity_main);
result = (TextView)findViewById(R.id.result);
value = (EditText)findViewById(R.id.value);
initService();
btnAdd = (Button)findViewById(R.id.addone);
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int v1, res = 0;
try{
v1 = Integer.parseInt(value.getText().toString());
res = service.addOne(v1);
}catch(RemoteException e) {
e.printStackTrace();
}
result.setText(Integer.valueOf(res).toString());
}
});
}
@Override
protected void onDestroy() {
releaseService();
super.onDestroy();
}
}
-
AndroidManifest.xml:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="net.lnmcc.aidltest.AddClient"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="net.lnmcc.aidltest.AddService" android:process="net.lnmcc.aidltest.AddService" />
</application>
5.activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:text="Android AIDL"
android:textSize="22dp" >
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/addone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+1" />
</LinearLayout>
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="result" />
</LinearLayout>
git clone https://github.com/lnmcc/AIDLTest.git
22 Sep 2013
介绍
SQLite 是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。 与其他数据库管理系统不同,SQLite 的安装和运行非常简单,在大多数情况下只要确保SQLite的二进制文件存在即可开始创建、连接和使用数据库。如果您正在寻找一个嵌入式数据库项目或解决方案,SQLite是绝对值得考虑。
数据库操作
查询已有数据库
$ sqlite > .databases
创建数据库
$ sqlite test.db
如果数据库已经存在了,则打开数据库。
创建表
sqlite> create table mytable(id integer primary key, value text);
sqlite>为sqlite的命令行提示符
查看数据库中存在的表
$ sqlite .tables
往表中插入数据
sqlite> insert into mytable(id, value) values(1, 'Micheal');
sqlite> insert into mytable(id, value) values(2, 'Jenny');
sqlite> insert into mytable(value) values('Francis');
sqlite> insert into mytable(value) values('Kerk');
查询数据
sqlite> select * from test;
输出:
1|Micheal
2|Jenny
3|Francis
4|Kerk
设置格式化查询结果
sqlite> .mode column
sqlite> .header on
sqlite> select * from test;
输出:
id value
----------- -------------
1 Micheal
2 Jenny
3 Francis
4 Kerk
修改表结构
增加列
sqlite> alter table mytable add column email text not null default '' collate nocase;
default : 设置默认值
collate nocase : 设置排序规则,nocase即大小写无关
创建视图
sqlite> create view nameview as select * from mytable;
创建索引
sqlite> create index test_idx on mytable(value);
常用的sqlite命令
查看帮助信息
sqlite> .help
退出sqlite
sqlite> .quit
显示表结构
sqlite> .schema [table]
获取所有表和视图
sqlite > .tables
获取指定表的索引列表
sqlite > .indices [table ]
导出数据库到 SQL 文件
sqlite > .output [filename ]
sqlite > .dump
sqlite > .output stdout
从 SQL 文件导入数据库
sqlite > .read [filename ]
格式化输出数据到 CSV 格式
sqlite >.output [filename.csv ]
sqlite >.separator ,
sqlite > select * from test;
sqlite >.output stdout
从 CSV 文件导入数据到表中
sqlite >create table newtable ( id integer primary key, value text );
sqlite >.import [filename.csv ] newtable
备份数据库
/* usage: sqlite [database] .dump > [filename] */
sqlite mytable.db .dump > backup.sql
恢复数据库
/* usage: sqlite [database ] < [filename ] */
sqlite mytable.db < backup.sql
ref : http://www.oschina.net/question/12_53183
22 Sep 2013
1、在hid-ids.h中加入vid pid
#define USB_VENDOR_ID_HAPPYTOUCH 0x0416
#define USB_DEVICE_ID_HAPPYTOUCH_SCREEN 0x5030
2、在hid-multitouch.c->mt_devices[] 中加入
{ .driver_data = MT_CLS_DEFAULT,
HID_USB_DEVICE(USB_VENDOR_ID_HAPPYTOUCH,
USB_DEVICE_ID_HAPPYTOUCH_SCREEN) }
3、在hid-core.c->hid_have_special_driver[]中加入HID_USB_DEVICE(VID,PID)
{ HID_USB_DEVICE(USB_VENDOR_ID_HAPPYTOUCH,USB_DEVICE_ID_HAPPYTOUCH_SCREEN)}
4、设置kernel编译变量
$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE=arm-eabi-
5、在内核的config文件中,确认驱动中是否添加了hid-multitouch模块
运行make menuconfig后,将HID Multitouch panels选上。
$ make clear
$ make mrproper
$ make menuconfig
Device Drivers --->
HID Devices --->
Special HID Drivers --->
HID Multitouch panels
6、编译hid-multitouch.ko
$ make prepare
$ make scripts
$ make M=drivers/hid
关于如何单独编译kernel驱动的方法,请点击这里。
7、设置触摸屏
Android触摸屏设置方法请点击 这里。
19 Sep 2013
对一个android app来说,加入EULA
已经是一个必不可少的内容了。下面将演示如何创建一个通用的Eula
类。任何一个app都可以使用Eula.show()
来显示自己的EULA,也可以通过实现Eula.OnEulaAgreedTo
接口做进一步处理。
Eula.java
/**
最终用户协议文件名由ASSERT_EULA定义,存放位置为项目的assets目录
*/
public class Eula {
private static final String ASSERT_EULA = "EULA";
private static final String PREFERENCE_EULA_ACCEPTED = "eula.accepted";
private static final String PREFERENCE_EULA = "eula";
/**
当用户选择同意后的回调函数。
*/
static interface OnEulaAgreedTo {
void onEulaAgreedTo();
}
private static void accept(SharedPreferences preferences) {
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true).commit();
}
private static void refuse(Activity activity) {
activity.finish();
}
private static void closeStream(Closeable stream) {
if(null != stream) {
try {
stream.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
private static CharSequence readEula(Activity activity) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(activity.getAssets().open(ASSERT_EULA)));
String line;
StringBuilder buffer = new StringBuilder();
while((line = in.readLine()) != null) {
buffer.append(line).append("\n");
}
return buffer;
} catch(IOException e) {
e.printStackTrace();
return "";
} finally {
closeStream(in);
}
}
static boolean show(final Activity activity) {
final SharedPreferences preferences = activity.getSharedPreferences(PREFERENCE_EULA, Activity.MODE_PRIVATE);
if(!preferences.getBoolean(PREFERENCE_EULA_ACCEPTED, false)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.eula_title);
builder.setCancelable(true);
builder.setPositiveButton(R.string.eula_accept, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
accept(preferences);
if(activity instanceof OnEulaAgreedTo) {
((OnEulaAgreedTo)activity).onEulaAgreedTo();
}
}
});
builder.setNegativeButton(R.string.eula_refuse, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
refuse(activity);
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
refuse(activity);
}
});
builder.setMessage(readEula(activity));
builder.create().show();
return false;
}
return true;
}
}
使用上面的EULA类:
测试的时候,你可能需要删除或者修改/data/目录下app对应的eula.xml
文件,因为这里把用户的授权信息存放在了SharedPreferences
中,而这是个永久存储的方法。
EulaExample.java
public class EulaExample extends Activity implements Eula.OnEulaAgreedTo {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_eula_example);
Eula.show(this);
}
@Override
public void onEulaAgreedTo() {
Toast.makeText(this, "Think you !", Toast.LENGTH_SHORT).show();
}
}