在QT pro文件中使用 PKGCONFIG

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

使用Android接口描述语言(AIDL)

AIDL简介

Andorid提供了一种轻量级的进程间通信机制:接口描述语言(Android Interface Definition Language),简称AIDL。进程间使用AIDL通信跟使用Intent通信的最大区别在于:前者是同步通信,而后者是异步通信。AIDL的语法与JAVA中的Interface十分相似,对数据类型的支持方面有一些差别,目前AIDL支持的数据类型有:

  • Java中的基本数据类型
  • String
  • List
  • CharSequence
  • Map
  • 其他AIDL生成的接口
  • 实现了Parcelable接口并通过值传递的自定义类型

使用AIDL的步骤

  1. 创建.aidl文件,在文件中声明远程服务的接口
  2. 在.java文件中实现.aidl中声明的方法
  3. 在AndroidMainifest中注册上面创建的服务
  4. 客户端请求绑定服务成功后就可以调用.aidl中声明的方法了

示例解析

项目目录结构: alt none

  1. 在项目src文件夹下创建IAddService.aidl文件,在aidl声明了一个addOne方法,这个方法简单的把传入的值加上一。

    IAddService.aidl:

    package net.lnmcc.aidltest.aidl;
       
    interface IAddOneService {
    	int addOne(int value);
    }
    

    保存.aidl文件后,Eclipse将会自动在gen/文件夹下生成一个IAddService.java文件,在后面实现远程服务的时候会使用到其中的抽象类Stub。

  2. 创建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 。
  3. 创建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();
    	}
    }
    
    1. 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

sqlite的基本用法

介绍

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

Android 增加 Happy Touch 触摸屏支持

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触摸屏设置方法请点击 这里

为Android APP添加最终用户许可协议

对一个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();
	}
}