常用简单的ContentProvider的实现差不多,整理了个通用的(基于com.example.android.supportv4.app.LoaderThrottleSupport.SimpleProvider修改), 从这个类继承,再重写几个方法就可以了,测试代码见附件。
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.provider.BaseColumns;
import android.support.v4.database.DatabaseUtilsCompat;
import android.text.TextUtils;
/**
*
* @author J
*
*/
public abstract class SimpleContentProvider extends ContentProvider{
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.%s.%s";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.%s.%s";
private final UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//
private HashMap<Integer, String> hash_id_tableName = new HashMap<Integer, String>();
private SQLiteOpenHelper mOpenHelper;
protected abstract String getAuthority();
protected abstract SQLiteOpenHelper createDatabaseHelper(Context context);
protected abstract String[] getTableNames();
protected String getIdName(String tableName){
return BaseColumns._ID;
}
protected String getDefaultSort(String tableName){
return null;
}
/**
* If URI is main table
*/
private boolean isMain(int id){
return id % 2 == 1;
}
/**
* Global provider initialization.
*/
public SimpleContentProvider() {
int id_main = 1, id_row = 2;
String[] tableNames = getTableNames();
for (String tableName : tableNames){
//奇数 for main table, 偶数 for row
mUriMatcher.addURI(getAuthority(), tableName, id_main);
mUriMatcher.addURI(getAuthority(), tableName + "/#", id_row);
hash_id_tableName.put(id_main, tableName);
hash_id_tableName.put(id_row, tableName);
id_main += 2;
id_row += 2;
}
}
@Override
public boolean onCreate() {
mOpenHelper = createDatabaseHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Constructs a new query builder and sets its table name
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
int id = mUriMatcher.match(uri);
String tableName = hash_id_tableName.get(id);
if (tableName != null){
qb.setTables(tableName);
if (isMain(id)){
//qb.setProjectionMap(mNotesProjectionMap);
}
else{
//qb.setProjectionMap(mNotesProjectionMap);
qb.appendWhere(getIdName(tableName) + "=?");
selectionArgs = DatabaseUtilsCompat.appendSelectionArgs(selectionArgs,
new String[] { uri.getLastPathSegment() });
}
}
else{
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (TextUtils.isEmpty(sortOrder)) {
sortOrder = getDefaultSort(tableName);
}
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
/**
* Return the MIME type for an known URI in the provider.
*/
@Override
public String getType(Uri uri) {
int id = mUriMatcher.match(uri);
String tableName = hash_id_tableName.get(id);
if (tableName != null){
if (isMain(id)){
return String.format(CONTENT_TYPE, getAuthority(), tableName);
}
else{
return String.format(CONTENT_ITEM_TYPE, getAuthority(), tableName);
}
}
else{
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
/**
* Handler inserting new data.
*/
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
int id = mUriMatcher.match(uri);
String tableName = hash_id_tableName.get(id);
if (tableName == null || !isMain(id)){
// Can only insert into to main URI.
throw new IllegalArgumentException("Unknown URI " + uri);
}
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
} else {
values = new ContentValues();
}
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = db.insert(tableName, null, values);
// If the insert succeeded, the row ID exists.
if (rowId > 0) {
//Uri noteUri = ContentUris.withAppendedId(MainTable.CONTENT_ID_URI_BASE, rowId);
Uri noteUri = ContentUris.withAppendedId(uri, rowId);
getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
/**
* Handle deleting data.
*/
@Override
public int delete(Uri uri, String where, String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
String finalWhere;
int count;
int id = mUriMatcher.match(uri);
String tableName = hash_id_tableName.get(id);
if (tableName != null){
if (isMain(id)){
count = db.delete(tableName, where, whereArgs);
}
else{
finalWhere = DatabaseUtilsCompat.concatenateWhere(
getIdName(tableName) + " = " + ContentUris.parseId(uri), where);
count = db.delete(tableName, finalWhere, whereArgs);
}
}
else{
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
/**
* Handle updating data.
*/
@Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
String finalWhere;
int id = mUriMatcher.match(uri);
String tableName = hash_id_tableName.get(id);
if (tableName != null){
if (isMain(id)){
// If URI is main table, update uses incoming where clause and args.
count = db.update(tableName, values, where, whereArgs);
}
else{
// If URI is for a particular row ID, update is based on incoming
// data but modified to restrict to the given ID.
finalWhere = DatabaseUtilsCompat.concatenateWhere(
getIdName(tableName) + " = " + ContentUris.parseId(uri), where);
count = db.update(tableName, values, finalWhere, whereArgs);
}
}
else{
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
------- android培训、java培训、期待与您交流! ----------
切水果游戏非常流行哈。在学习box2d的时候了解到重力和施加外力这个内容的时候,突然就想到了切
水果是怎么写出来的。所以自己研究出了一个demon。
大概过程就是有一个小球过一会就从左下角抛出来,然后模拟在现实生活中自由落体的感觉,当然方向是不一样的,如果我的鼠标点中了小球,那么小球就会消失。让过程很简单,但是经过还是充满了探索,主要就是在删除小球的过程中,请仔细看到代码,我有注释。
首先写一个圆类:都是基本的知识,应该很容易理解。
public class MyCircle {
//圆形的宽高与半径
float x, y, r;
public MyCircle(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
//设置圆形的X坐标
public void setX(float x) {
this.x = x;
}
//设置半径的Y坐标
public void setY(float y) {
this.y = y;
}
//绘制圆形
public void draw(Canvas canvas, Paint paint) {
canvas.drawArc(new RectF(x, y, x + 2*r, y + 2*r), 0, 360, true, paint);
}
}
再看看surfaceView界面的代码:根据代码的注释很容易看懂。
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
private Thread th;
private SurfaceHolder sfh;
private Canvas canvas;
private Paint paint;
private boolean flag;
// ----添加一个物理世界---->>
final float RATE = 30;// 屏幕到现实世界的比例 30px:1m;
World world;// 声明一个物理世界对象
AABB aabb;// 声明一个物理世界的范围对象
Vec2 gravity;// 声明一个重力向量对象
float timeStep = 1f / 60f;// 物理世界模拟的的频率
int iterations = 10;// 迭代值,迭代越大模拟越精确,但性能越低
// --->>给第一个Body赋予力
Body body1;
int count=0;//计数器,没过多久就创造一个小球
//定义一个存放该被摧毁的body
Vector<Object> Dbody=new Vector<Object>();
boolean Delete=false;
public MySurfaceView(Context context) {
super(context);
this.setKeepScreenOn(true);
sfh = this.getHolder();
sfh.addCallback(this);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Style.STROKE);
this.setFocusable(true);
// --添加一个物理世界--->>
aabb = new AABB();// 实例化物理世界的范围对象
gravity = new Vec2(0, 10);// 实例化物理世界重力向量对象
aabb.lowerBound.set(-100, -100);// 设置物理世界范围的左上角坐标
aabb.upperBound.set(100, 100);// 设置物理世界范围的右下角坐标
world = new World(aabb, gravity, true);// 实例化物理世界对象
}
public void surfaceCreated(SurfaceHolder holder) {
flag = true;
th = new Thread(this);
th.start();
}
public Body createCircle(float x, float y, float r, boolean isStatic) {
CircleDef cd = new CircleDef();
if (isStatic) {
cd.density = 0;
} else {
cd.density = 1;
}
cd.friction = 0.8f;
cd.restitution = 0.3f;
cd.radius = r / RATE;
BodyDef bd = new BodyDef();
bd.position.set((x + r) / RATE, (y + r) / RATE);
Body body = world.createBody(bd);
body.m_userData = new MyCircle(x, y, r);
body.createShape(cd);
body.setMassFromShapes();
return body;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Body body = world.getBodyList();//如果点击了,就判断点击的地方是否在小球内部,所以要取出所有小球,一个一个与点击的地方比对
for (int i = 1; i < world.getBodyCount(); i++) {
float x=event.getX();
float x1=body.getPosition().x * RATE-10 ;
float x2=body.getPosition().x * RATE+10;
float y=event.getY();
float y1=body.getPosition().y * RATE-10;
float y2=body.getPosition().y * RATE+10;
// System.out.println(" x:"+x+" y:"+y+" body.getPosition().x:"+body.getPosition().x+" body.getPosition().y:"+body.getPosition().y
if(x1<x&&x<x2&&y1<y&&y<y2)
{
Dbody.add(body);
Delete=true;
System.out.println("点准了");
}
body = body.m_next;
}
return super.onTouchEvent(event);
}
public void myDraw() {
try {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
Body body = world.getBodyList();
for (int i = 1; i < world.getBodyCount(); i++) {
((MyCircle) body.m_userData).draw(canvas, paint);
body = body.m_next;
}
}
} catch (Exception e) {
Log.e("Himi", "myDraw is Error!");
} finally {
if (canvas != null)
sfh.unlockCanvasAndPost(canvas);
}
}
public void Logic() {
// --开始模拟物理世界--->>
world.step(timeStep, iterations);// 物理世界进行模拟
if(Delete){//注意所有的删除body操作必须写在world.step的后面。并且要加入到一个集合里面去一次性删除。
System.out.println("开始删");
for(int j=0;j<Dbody.size();++j)
{
Body body2=(Body)Dbody.get(j);
world.destroyBody(body2);
System.out.println("删一个");
}
Dbody.removeAllElements();
Delete=false;
}
++count;
if(count%80==0)
{
int i=(int)(Math.random()*100);
body1 = createCircle(0, 450, 10, false);
Vec2 vForce = new Vec2(i,-350);
body1.applyForce(vForce, body1.getWorldCenter());
}
// 取出body链表表头
Body body = world.getBodyList();
for (int i = 1; i < world.getBodyCount(); i++) {
// 设置MyCircle的X,Y坐标
MyCircle mc = (MyCircle) body.m_userData;
mc.setX(body.getPosition().x * RATE - mc.r);
mc.setY(body.getPosition().y * RATE - mc.r);
// 将链表指针指向下一个body元素
body = body.m_next;
}
}
public void run() {
while (flag) {
myDraw();
Logic();
try {
Thread.sleep((long) timeStep * 1000);
} catch (Exception ex) {
Log.e("Himi", "Thread is Error!");
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
flag = false;
}
}
以及MainActivity.java的代码:注意设置全屏的效果,在很多地方很常用
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//下两句还有显示全屏的代码
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new MySurfaceView(this));
}
}
最后来看一幅效果图
这是小球在空中的情景,我只要去点就可以让其消失。
我相信做到这一步,再接下来做一切扩展就比较容易了。
其实很是很开心的,很有成就感呀
------- android培训、java培训、期待与您交流! ----------
转:ubuntudaily.net/2011/11/how-to-install-google-input-method-in-ubuntu-1004