参考:contentprovider的学习实例总结 http://www.cnblogs.com/chenglong/articles/1892029.html
Android学习十九:ContentProvider初步 http://blog.sina.com.cn/s/blog_5688414b0100xagp.html
android 自定义 Content Provider示例 http://byandby.iteye.com/blog/837466
实例源码下载:http://download.csdn.net/detail/yang_hui1986527/4430639
Profile.java
package com.snowdream.contentprovider;
import android.net.Uri;
public class Profile {
/**
* 表格名称
*/
public static final String TABLE_NAME = "profile";
/**
* 列表一,_ID,自动增加
*/
public static final String COLUMN_ID = "_id";
/**
* 列表二,名称
*/
public static final String COLUMN_NAME = "name";
public static final String AUTOHORITY = "com.snowdream.provider";
public static final int ITEM = 1;
public static final int ITEM_ID = 2;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.snowdream.profile";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.snowdream.profile";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTOHORITY + "/profile");
}
package com.snowdream.contentprovider;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
/**
* 数据库名称
*/
private static final String DATABASE_NAME = "test.db";
/**
* 数据库版本
*/
private static final int DATABASE_VERSION = 1;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) throws SQLException {
//创建表格
db.execSQL("CREATE TABLE IF NOT EXISTS "+ Profile.TABLE_NAME + "("+ Profile.COLUMN_ID +" INTEGER PRIMARY KEY AUTOINCREMENT," + Profile.COLUMN_NAME +" VARCHAR NOT NULL);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLException {
//删除并创建表格
db.execSQL("DROP TABLE IF EXISTS "+ Profile.TABLE_NAME+";");
onCreate(db);
}
}
MyProvider.java
package com.snowdream.contentprovider;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class MyProvider extends ContentProvider {
DBHelper mDbHelper = null;
SQLiteDatabase db = null;
private static final UriMatcher mMatcher;
static{
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mMatcher.addURI(Profile.AUTOHORITY,Profile.TABLE_NAME, Profile.ITEM);
mMatcher.addURI(Profile.AUTOHORITY, Profile.TABLE_NAME+"/#", Profile.ITEM_ID);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
switch (mMatcher.match(uri)) {
case Profile.ITEM:
return Profile.CONTENT_TYPE;
case Profile.ITEM_ID:
return Profile.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Unknown URI"+uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
long rowId;
if(mMatcher.match(uri)!=Profile.ITEM){
throw new IllegalArgumentException("Unknown URI"+uri);
}
rowId = db.insert(Profile.TABLE_NAME,null,values);
if(rowId>0){
Uri noteUri=ContentUris.withAppendedId(Profile.CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
mDbHelper = new DBHelper(getContext());
db = mDbHelper.getReadableDatabase();
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
Cursor c = null;
switch (mMatcher.match(uri)) {
case Profile.ITEM:
c = db.query(Profile.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
break;
case Profile.ITEM_ID:
c = db.query(Profile.TABLE_NAME, projection,Profile.COLUMN_ID + "="+uri.getLastPathSegment(), selectionArgs, null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Unknown URI"+uri);
}
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
MainActivity.java
package com.snowdream.contentprovider;
import com.snowdream.contentprovider.R;
import android.app.ListActivity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.widget.SimpleCursorAdapter;
public class MainActivity extends ListActivity {
private SimpleCursorAdapter adapter= null;
private Cursor mCursor = null;
private ContentResolver mContentResolver = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
initAdapter();
}
public void initData(){
mContentResolver = getContentResolver();
//填充数据
for (int i = 0; i < 100; i++) {
ContentValues values = new ContentValues();
values.put(Profile.COLUMN_NAME, "张三"+i);
mContentResolver.insert(Profile.CONTENT_URI, values);
}
}
public void initAdapter(){
//查询表格,并获得Cursor
//查询全部数据
mCursor = mContentResolver.query(Profile.CONTENT_URI, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, null, null, null);
//查询部分数据
//String selection = Profile.COLUMN_ID + " LIKE '%1'";
//mCursor = mContentResolver.query(Profile.CONTENT_URI, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, selection, null, null);
//查询一个数据
//Uri uri = ContentUris.withAppendedId(Profile.CONTENT_URI, 50);
//mCursor = mContentResolver.query(uri, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, null, null, null);
startManagingCursor(mCursor);
//设置adapter
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, mCursor, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, new int[]{android.R.id.text1,android.R.id.text2});
setListAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
预览效果:
当我们渲染一个完全封闭的物体的时候,多边形的背面都是隐藏的,我们无法看见。但是如果这个物体有一些空洞,那么一些背面就可以被看见了。然而因为这些多边形的法向量的方向在这个时候不是正确的,所以会渲染出错误的结果。为了合理的渲染这些背面,我们必须反转法向量,然后基于这些反转的法向量来计算光照。
下图显示了一个采用Phong光照模型绘制茶壶使用双面渲染与否的结果对比:
图一 使用双面渲染与不使用的效果对比
一、固定管线OpenGL实现双面渲染
在固定管线中,我们需要用一个函数来启用双面光照:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
这样,OpenGL将会反转表面的法线的方向,表示背面多边形的法线。
实例:
void GLWidget::initLight()
{
GLfloat light_ambient[]={0.7,0.8,0.9,1.0};
GLfloat light_diffuse[]={1.0,1.0,1.0,1.0};
GLfloat light_specular[]={1.0,1.0,1.0,1.0};
GLfloat light_position[]={2.0,2.0,2.0,0.0};
GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};
glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
glLightfv(GL_LIGHT0,GL_POSITION,light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
//glEnable(GL_CULL_FACE);
//启用双面光照
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);
}效果:
二、可编程管线OpenGL实现双面渲染
假设我们的光照(采用Phong光照模型)计算是基于顶点的。在顶点着色器中,我们需要为每个顶点分别计算两次:front face和back face。两次计算采用的法向量不同。
#version 400
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
out vec3 FrontColor;
out vec3 BackColor;
struct LightInfo{
vec4 Position;
vec3 La;
vec3 Ld;
vec3 Ls;
};
uniform LightInfo Light;
struct MaterialInfo{
vec3 Ka;
vec3 Kd;
vec3 Ks;
float Shininess;
};
uniform MaterialInfo Material;
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 MVP;
//转化到视空间
void getEyeSpace(out vec3 tnorm,out vec4 eyeCoords)
{
//convert normal and position to eye coords
tnorm = normalize(NormalMatrix * VertexNormal);
eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0);
}
//计算Phong光照模型
vec3 phongModel(vec4 eyeCoords,vec3 tnorm)
{
vec3 s = normalize(vec3(Light.Position - eyeCoords));
vec3 v = normalize(-eyeCoords.xyz);
vec3 r = reflect(-s,tnorm);
vec3 ambient = Light.La * Material.Ka;
float sDotN = max(dot(s,tnorm),0.0);
vec3 diffuse = Light.Ld * Material.Kd * sDotN;
vec3 specular = vec3(0.0);
if(sDotN > 0)
specular = Light.Ls * Material.Ks *
pow(max(dot(r,v),0.0),Material.Shininess);
return (ambient + diffuse + specular);
}
void main()
{
vec3 tnorm;
vec4 eyeCoords;
getEyeSpace(tnorm,eyeCoords);
FrontColor = phongModel(eyeCoords,tnorm);
BackColor = phongModel(eyeCoords,-tnorm);
gl_Position = MVP * vec4(VertexPosition,1.0);
}在片断着色器中,我们根据关键字gl_FrontFacing的值来为片断赋予颜色值。
gl_FrontFacing是GLSL内置的关键字,它代表图元是面向光源还是背向光源。
片断着色器 twosided.frag:
#version 400
in vec3 FrontColor;
in vec3 BackColor;
layout (location = 0) out vec4 FragColor;
void main()
{
if(gl_FrontFacing)
{
FragColor = vec4(FrontColor,1.0);
}
else
{
FragColor = vec4(BackColor,1.0);
}
}
//The font information include:
//Ex, 4E00 is the chinese character “一”
bbw=16, bbh=16, bbx=0, bby=0, width=16
//Comments: we can image the screen is big area, a font will take a rectangular
//which have start coordination< x,y >, with and height. the font are a series binary data which 1 is
//showing a point in current screen, 0 is showing nothing on the screen on the 16X16 screen erea.
0x0000, //16 bit size
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0xfffe,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
u4E00_4E5A_font_offset.h //Just include the value of a series font offset from 0X4E00~0X4E5A.
// Ex,
11904, /* (0x4e00) */
.....
0 /* (0x4e5a) */ “乙”
u4E00_4E5A_font_width.h //Just include the value of a series font with
16, /* (0x4e00) */
......
8 /* (0x4e5a) */ “乙”T_FontBmInfo MMI_lcd_get_font_Bm_data(UINT16 wUnicode)
{
UINT8 i = 0;
INT32 wOffset = -1;
INT32 wLocalOffset = -1;
T_FontBmInfo tFontBmInfo;
//Please add the detail comments at here!!
for (i = 0; g_tFontTable[i].bCodeType != 0xFF ; i++)
{ //Please add the detail comments at here!!
if (wUnicode >= g_tFontTable[i].bCodeStart && wUnicode <= g_tFontTable[i].bCodeEnd)
{
//Please add the detail comments at here!!
wOffset = wUnicode - g_tFontTable[i].bCodeStart;
if(g_tFontTable[i].bdwOffset[wOffset]) //check all table until find it.
{
break;
}
else
{ //Please add the detail comments at here!!
wOffset = -1;
}
}
else
{ //Please add the detail comments at here!!
wOffset = -1;
}
}
if (-1 == wOffset)
{
wOffset = 32;
i = 0;
}
wLocalOffset = g_tFontTable[i].bdwOffset[wOffset]-g_tFontTable[i].bdwOffset[0];
tFontBmInfo.bWidth = g_tFontTable[i].baWidth[wOffset];
tFontBmInfo.pwFontBm = (UINT16 *)(&g_tFontTable[i].baFontRowData[wLocalOffset]);
tFontBmInfo.bHeight = LCD_DEFAULT_FONT_HEIGHT;
return tFontBmInfo;
}void MMI_lcd_show_font_Bm(UINT16 wShowPos, T_FontBmInfo *ptFontBmInfo, UINT16 wFwdColor, UINT16 wBackColor)
{
UINT8 bLoopHeight = 0;
UINT8 bLoopWidth = 0;
UINT8 i = 0;
UINT16 wFontword;
UINT16 wOffset = 0;
UINT16 wLcdPointIndex = wShowPos;
T_ALLCDRect tRect;
//write font bitmap to lcd
//Please add the detail comments at here!!
for (bLoopHeight = 0; bLoopHeight < ptFontBmInfo->bHeight; bLoopHeight++)
{ //Please add the detail comments at here!!
for (bLoopWidth = 0; bLoopWidth < ptFontBmInfo->bWidth; bLoopWidth+=16)
{ //Please add the detail comments at here!!
wFontword = ptFontBmInfo->pwFontBm[wOffset];
//Please add the detail comments at here!!
for (i = 0; i < min(16, ptFontBmInfo->bWidth-bLoopWidth); i++)
{ //Please add the detail comments at here!!
if (((wLcdPointIndex) > (AL_PLCD_MAX_WIDTH * AL_PLCD_MAX_HEIGHT - 1)) || (wLcdPointIndex < 0))
{
return;
}
if (wFontword & 0x8000)//Please add the detail comments at here!!
{
g_waLcdPanelBuf[wLcdPointIndex] = wFwdColor;
}
else
{
if (wFwdColor != wBackColor)
{
g_waLcdPanelBuf[wLcdPointIndex] = wBackColor;
}
}
wFontword <<= 1;
wLcdPointIndex++;
}// for (i = 0; i < min(16, ptFontBmInfo->bWidth-bLoopWidth); i++)
wOffset++;
}// for (bLoopWidth = 0; bLoopWidth < ptFontBmInfo->bWidth; bLoopWidth+=16)
wLcdPointIndex += (AL_PLCD_MAX_WIDTH - ptFontBmInfo->bWidth);
}// for (bLoopHeight = 0; bLoopHeight < ptFontBmInfo->bHeight; bLoopHeight++)
//Please add the detail comments at here!!
Mmi_lcd_request_refresh(tRect);
}