
《物联网移动应用开发》课程设计报告
设 计 题 目: 简易的记事本
班 级: 物联网131班
学 号: *********19
姓 名:
* * * ** **
成 绩:
信 息 工 程 学 院
课程设计报告说明
一、写报告前,请认真阅读《课程设计报告说明》。
二、打印装订要求
1、一律用A4纸,双面打印,并左侧装订。报告正文部分均采用宋体小四。《课程设计报告说明》页也打印。
2、课程设计概述部分占一页;课程设计内容长度根据实际需要填写;结论和指导教师评语及成绩单独占一页。保证打印格式工整。
3、指导教师评语及成绩部分由指导教师填写。
三、报告内容要求
1、课程设计目的结合实际自己写,不要雷同。
2、课程设计原理简要说明所完成课程设计项目所涉及的理论知识。
3、课程设计内容 这是课程设计报告极其重要的内容。概括整个课程设计过程。(最好在上述内容基础上画出相应的流图、设计思路和设计方法,再配以相应的文字进行说明。)
一、课程设计概述
1、课程设计目的
Window操作系统的诞生成就了微软帝国,同时也造就了PC时代的繁荣,然而如今,以Android和iPhone手机为代表的智能移动设备的发明与互联网云技术的兴起却敲响了PC时代的丧钟!这也预示着移动互联网时代(3G)已经来临。
在这个互联网繁荣的时代,有一颗超新星,以它独特性能优势与人性化的UI设计使它在短短的几年迅速的占领了智能移动设备的市场份额,它就是Google的Android!这也意味着Google在移动互联网时代开始抢跑并领跑。
| 通过调查显示,大部分消费者都会使用手机记事本功能。随着手机记事本功能的不断加强与完善,手机记事本对于人们的意义,已不仅仅像一般记事簿一样简单记录,而是向着更个性化人性化的方向发展。Android[1]系统是开源的,它以迅猛的姿势已经占领了全球一半多的市场。记事本在生活和工作也日益凸显出它的重要性,它能更好地帮助人们更好地管理自己的工作和生活,极大的方便了人们的生活。因其开源,我们可以在之上开发安卓记事本软件,同时这也符合广大的市场需求。 |
| 2、课程设计要求 设计的最终作品包括设计报告和能成功运行的程序,能够达到设计指标的要求。每个小组在设计完成后,要经指导教师检查。课程设计报告每个学生一份,由学习委员收齐后统一交给指导教师。 按照课程设计的进程,认真完成各个环节,保证质量,达到目标。 |
| 3、课程设计原理 (1) 设计实现添加事件、保存事件、删除事件、导出事件、添加图片等主功能。 (2)利用Android中的一些组件和事件监听解决功能的实现问题。 (3)利用mysql语句来实现数据库的设计为用户保存数据。 (4)使用debug调试来解决程序运行时遇到的问题 |
1、软件功能规划
(1)软件功能
能够提示用户是否有已写记事本,能够进行记事本的标题填写和内容填写,确定后保存。
(2) 界面设计
进入程序提示“您还没有开始写日记呢!点击下边的Menu按钮开始写日记吧!”,点击图片按钮后进入标题和内容的填写界面。
2、程序设计
(1)记事本组件的设计
本项目涉及到以下组件:
TextView:“记事本”,“新建记事”,“编辑记事”等标题。
EditView:“记事本的标题”,“内容”等。
ImageButton:“写事件”,“保存”,“加图片”按钮。
Menu:“编译内容”,“删除当前记事”,“修改当前记事”,“导出当前记事”
“帮助”,“关于”等。
(2)记事本逻辑设计
(i)添加新记事
如果当前没有记事,点击“listview中的事件”后只有一个菜单选项“添加新记事”,写完记事之后,点击“确定”进行保存。
(ii)编辑内容
选中要编辑的那一个记事,然后点击“listview中的事件”菜单,会出现三个选项“新建记事”,“编辑内容”,“删除当前记事”,点击“编辑内容”对被选中的记事进行编辑,然后点击“确定”加以保存。
(iii)删除记事
点击上下键,选中要删除的记事,然后点击“listview中的事件”菜单,然后点击“删除当前记事”,对选中的记事加以删除。
(3)记事本存储实现
Android 中一共提供了5种数据存储方式,但是由于存储的这些数据都是其应用程序私有的,所以如果需要在其他应用程序中使用这些数据,就要使用Android提供的Content Providers。
Content Providers:Android提供的一个特殊的存储数据的类型,它提供了一套标准的接口来获取,操作数据。
Shared Preference:用来存储“key-value paires”格式的数据,它是一个轻量级的键值存储机制,只可以存储基本数据类型。
Files:它通过File Input Stream 和 File Output Stream对文件进行操作,但是在Android中,文件是一个应用程序私有的,一个应用程序无法读写其他应用程序的文件。
SQL ite:Android提供的一个标准的数据库,支持SQL语句。
Network:通过网络来存储和获得数据。
(i)数据存储之SQLite
通过sqlite中的增删改查方法来保存、删除、修改、查找数据。来实现对数据的操作。
代码:
public class DBManage {
private Context mContext = null;
private SQLiteDatabase mSQLiteDatabase = null;//用于操作数据库的对象
private DBHelper dh = null;//用于创建数据库的对象
Cursor namecursor=null;
private String dbName = "notepad.db";
private int dbVersion = 1;
public DBManage(Context context){
mContext = context;
}
/**
* 打开数据库
*/
public void open(){
try{
dh = new DBHelper(mContext, dbName, null, dbVersion);
if(dh == null){
return ;
}
mSQLiteDatabase = dh.getWritableDatabase();
//dh.onOpen(mSQLiteDatabase);
Log.i("log", "DB is opened");
}catch(SQLiteException se){
se.printStackTrace();
Log.i("log", "open DB faile");
}
}
/**
* 关闭数据库
*/
public void close(){
mSQLiteDatabase.close();
dh.close();
Log.i("log", "DB is closed");
}
//获取列表
public Cursor selectAll(){
Cursor cursor = null;
try{
String sql = "select * from travels";
cursor = mSQLiteDatabase.rawQuery(sql, null);
}catch(Exception ex){
ex.printStackTrace();
cursor = null;
}
return cursor;
}
public Cursor selectById(int id){
Cursor cursor = null;
try{
String sql = "select * from travels where _id='" + id +"'";
cursor = mSQLiteDatabase.rawQuery(sql, null);
}catch(Exception ex){
ex.printStackTrace();
cursor = null;}
return cursor;
}
public Cursor selcetPathByName(String name){
Cursor cursor=null;
try{
String sql = "select path from icons where filename='"+ name +"'";
cursor=mSQLiteDatabase.rawQuery(sql, null);
Log.i("log", sql);
}catch(Exception ex){
ex.printStackTrace();
Log.i("log", "select faile");
}
return cursor;
}
//插入数据
public long insert(String title, String content){
Log.i("log", "readyto insert");
long datetime = System.currentTimeMillis();
Log.i("log", "time------>"+datetime);
long l = -1;
try{
ContentValues cv = new ContentValues();
cv.put("title", title);
cv.put("content", content);
cv.put("time", datetime);
Log.i("log", "data----->"+title+content+datetime);
l = mSQLiteDatabase.insert("travels", null, cv);
Log.i("log", cv.toString());
Log.i("log", datetime+""+l);
}catch(Exception ex){
ex.printStackTrace();
l = -1;
}
return l;
}
public long inserticonpath(String filename,String iconpath){
long l=-1;
try{
Log.i("log", "ready to insert icon");
ContentValues cv = new ContentValues();
cv.put("filename",filename);
cv.put("path", iconpath);
l = mSQLiteDatabase.insert("icons", null, cv);
Log.i("log", "insert iconname success");
}catch(Exception ex){
ex.printStackTrace();
l = -1;
}
return l;
}
//删除数据
public int delete(long id){
int affect = 0;
try{
Log.i("log
affect=mSQLiteDatabase.delete("travels
Log.i("log", "delete success");
}catch(Exception ex){
ex.printStackTrace();
affect = -1;
Log.i("log", "delete faile");
}
return affect;
}
//修改数据
public int update(int id, String title, String content){
int affect = 0;
try{
ContentValues cv = new ContentValues();
cv.put("title", title);
cv.put("content", content);
affect=mSQLiteDatabase.update("travels",cv,"_id=?",new String[]{id+""});
}catch(Exception ex){
ex.printStackTrace();
affect = -1;
}
return affect;
}
}
(ii)数据存储之Files
我们可以通过自定义的copyfile()方法来复制数据
代码:
//复制文件
public int copyfile(String from,String into){
try
{
copyfrom=new FileInputStream(from);
copyinto=new FileOutputStream(into);
Log.i("log", "fuck you");
byte[] bt = new byte[1024];
int c;
while((c=copyfrom.read(bt)) > 0){
copyinto.write(bt,0,c);
}
copyfrom.close();
copyinto.close();
Log.i("log", "copy success");
return 1;
}catch (FileNotFoundException e) {
e.printStackTrace();
return -1;
} catch (IOException e) {
e.printStackTrace();
return -1;
}
}
3、程序开发
(1)主activity的设计
当选择“新建记事本”,“编辑内容”,“删除当前记事”等菜单选项时对应的操作
代码:
public void initAdapter(){
dm.open();//打开数据库操作对象
cursor = dm.selectAll();//获取所有数据
cursor.moveToFirst();//将游标移动到第一条数据,使用前必须调用
int count = cursor.getCount();//个数
ArrayList ArrayList for(int i= 0; i < count; i++){ items.add(cursor.getString(cursor.getColumnIndex("title"))); times.add(cursor.getString(cursor.getColumnIndex("time"))); cursor.moveToNext();//将游标指向下一个 } dm.close();//关闭数据操作对象 adapter = new ListViewAdd(this,items,times);//创建数据源 } public class myOnCreateContextMenuListener implements OnCreateContextMenuListener{ public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) { menu.setHeaderTitle(""); //设置选项 Log.i("log", "chooseing menu"); menu.add(0,0,0,"删除"); menu.add(0,1,0,"修改"); menu.add(0,2,0,"查看"); menu.add(0,3,0,"导出到SD卡"); } } public boolean onContextItemSelected(MenuItem item){ AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); dm.open(); switch(item.getItemId()){ case 0://删除 Log.i("log", "selectItem---->"+item.getItemId()); try{ Log.i("log", "cursor ready move "); Log.i("log", "menuInfo position "+menuInfo.position); cursor.moveToPosition(menuInfo.position); Log.i("log", "cursor move success"); adapter.removeListItem(menuInfo.position);//删除数据 adapter.notifyDataSetChanged();//通知数据源,数据已经改变,刷新界面 dm.close(); }catch(Exception ex){ ex.printStackTrace(); } break; case 1://修改 try{ cursor.moveToPosition(menuInfo.position); //用于Activity之间的通讯 Intent intent = new Intent(); //通讯时的数据传送 intent.putExtra("id", cursor.getString(cursor.getColumnIndex("_id"))); intent.putExtra("state", ALERT_STATE); intent.putExtra("title", cursor.getString(cursor.getColumnIndex("title"))); intent.putExtra("time", cursor.getString(cursor.getColumnIndex("time"))); intent.putExtra("content", cursor.getString(cursor.getColumnIndex("content"))); //设置并启动另一个指定的Activity intent.setClass(MainActivity.this, EditTravels.class); MainActivity.this.startActivity(intent); finish(); }catch(Exception ex){ ex.printStackTrace(); } break; case 2://查看 try{ cursor.moveToPosition(menuInfo.position); Intent intent = new Intent(); intent.putExtra("id", cursor.getString(cursor.getColumnIndex("_id"))); intent.putExtra("title", cursor.getString(cursor.getColumnIndex("title"))); intent.putExtra("time", cursor.getString(cursor.getColumnIndex("time"))); intent.putExtra("content", cursor.getString(cursor.getColumnIndex("content"))); intent.setClass(MainActivity.this, CheckTravels.class); MainActivity.this.startActivity(intent); }catch(Exception ex){ ex.printStackTrace(); } break; case 3://导出 try{ cursor.moveToPosition(menuInfo.position); String title=cursor.getString(cursor.getColumnIndex("title")); String content=cursor.getString(cursor.getColumnIndex("content")); HM.htmlmanager(title, content); copyicon(title,content); Toast.makeText(MainActivity.this, "导出成功,快去SD卡的\\" 记事本 \\"里找出来分享吧!!", Toast.LENGTH_LONG).show(); }catch(Exception ex){ Toast.makeText(MainActivity.this, "Sorry!!!导出失败!!", Toast.LENGTH_LONG).show(); ex.printStackTrace(); } break; default:; } dm.close(); return super.onContextItemSelected(item); } (2)修改内容 代码: public class EditTravels extends Activity{ private static final int SELECT_IMAGE =123; int rotate = 0; private EditText titleedit; private EditText travelsedit; private ImageButton save; private ImageButton insertimage; private ImageButton takephoto; private String idString; private int id2; private String title=""; private String travelsdata = ""; private String timeText = ""; public Cursor cursor=null; public String namestr=""; private DBManage dm=null; private Bitmap bitmap = null; private String path = null; private int state =-1; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.edittravels); titleedit=(EditText)findViewById(R.id.titleedit); travelsedit=(EditText)findViewById(R.id.travelsedit); save=(ImageButton)findViewById(R.id.save); save.setOnClickListener(new saveListener()); insertimage=(ImageButton)findViewById(R.id.insertimage); insertimage.setOnClickListener(new insertimageListener()); dm=new DBManage(this); Intent intent = getIntent(); state = Integer.parseInt(intent.getStringExtra("state")); Log.i("log", "state---->"+state); if (state==2) { idString =intent.getStringExtra("id"); Log.i("log", "id---->"+idString); id2 = Integer.parseInt(idString); title = intent.getStringExtra("title"); travelsdata = intent.getStringExtra("content"); timeText = intent.getStringExtra("time"); titleedit.setText(title); dm.open(); int i=0; int start=0; int end=0; String str1=null; String str2="["; String str4="]"; String iconname=null; SpannableString travelsSpan =new SpannableString(travelsdata); for(i=0;i str1=travelsdata.substring(i, i+1); Log.i("log", str1); if(str1.equals(str2)) { start=i+1; } if(str1.equals(str4)) { end=i; namestr=travelsdata.substring(start,end); Log.i("log", namestr); cursor=dm.selcetPathByName(namestr); cursor.moveToFirst(); path=cursor.getString(cursor.getColumnIndex("path")); cursor.close(); namestr=null; Log.i("log", path); if(!(cursor==null)) { int count=cursor.getCount(); Log.i("log", "count----->"+count); BitmapFactory.Options options =new BitmapFactory.Options(); options.inJustDecodeBounds =true; bitmap =BitmapFactory.decodeFile(path, options); //此时返回bm为空 options.inJustDecodeBounds =false; int be = (int)(options.outHeight/ (float)100); if (be <= 0) be = 1; options.inSampleSize = be; bitmap=BitmapFactory.decodeFile(path,options); Drawable drawable = new BitmapDrawable(bitmap); drawable.setBounds(0, 0, 360, 280); ImageSpan span = new ImageSpan(drawable,ImageSpan.ALIGN_BOTTOM); travelsSpan.setSpan(span, start-1,end+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } else { Log.i("log", "insert icon faile"); } } } dm.close(); travelsedit.setText(travelsSpan); } } //保存按钮点击事件 class saveListener implements OnClickListener{ public void onClick(View v) { // TODO Auto-generated method stub title = titleedit.getText().toString(); travelsdata= travelsedit.getText().toString(); Log.i("log Log.i("log", "travels---->"+travelsdata); try{ dm.open(); if(state==1) dm.insert(title, travelsdata); if (state==2) Log.i("log", "ready to alter"); dm.update(id2, title, travelsdata); dm.close(); }catch(Exception ex){ ex.printStackTrace(); } Intent gobackIntent=new Intent(EditTravels.this,MainActivity.class); EditTravels.this.startActivity(gobackIntent); finish(); } } //插入图片点击事件 class insertimageListener implements OnClickListener{ public void onClick(View v) { Intent intent=new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); intent.putExtra("return-data", true); startActivityForResult(intent, SELECT_IMAGE); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { path=getpath(data.getData()); BitmapFactory.Options options =new BitmapFactory.Options(); options.inJustDecodeBounds =true; //获取这个图片的宽和高 bitmap =BitmapFactory.decodeFile(path, options); //此时返回bm为空 options.inJustDecodeBounds =false; //计算缩放比 int be = (int)(options.outHeight/ (float)100); if (be <= 0) be = 1; options.inSampleSize = be; Log.i("log //重新读入图片 bitmap=BitmapFactory.decodeFile(path,options); int bitmapwidth=options.outWidth; int bitmapheight=options.outHeight; //检查图片是否要翻转 try { ExifInterface exifInterface = new ExifInterface(path); int result = exifInterface.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); switch(result) { case ExifInterface.ORIENTATION_ROTATE_90: rotate = 90; Log.i("log", "rotate----->"+rotate); break; case ExifInterface.ORIENTATION_ROTATE_180: rotate = 180; Log.i("log", "rotate----->"+rotate); break; case ExifInterface.ORIENTATION_ROTATE_270: rotate = 270; Log.i("log", "rotate----->"+rotate); break; default: break; } } catch (IOException e) { e.printStackTrace(); } if (rotate!=0&&bitmap!=null) { Matrix matrix=new Matrix(); matrix.reset(); matrix.setRotate(rotate); Bitmap bitmap1=Bitmap.createBitmap(bitmap,0,0, options.outWidth, options.outHeight, matrix, true); bitmap = bitmap1; rotate=0; bitmapwidth=options.outHeight; bitmapheight=options.outWidth; } Drawable drawable = new BitmapDrawable(bitmap); drawable.setBounds(0, 0,bitmapwidth*2,bitmapheight*2); String iconname = path.substring(path.lastIndexOf("/")+1); String iconimfo="["+iconname+"]"; SpannableString spannable = new SpannableString(iconimfo); ImageSpan span = new ImageSpan(drawable,ImageSpan.ALIGN_BOTTOM); spannable.setSpan(span, 0,iconimfo.length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); int select=travelsedit.getSelectionStart(); Editable edit = travelsedit.getEditableText(); edit.insert(select, spannable); try{ dm.open(); dm.inserticonpath(iconname, path); dm.close(); }catch(Exception ex){ ex.printStackTrace(); } } } String getpath(Uri uri) { String[] projection = {MediaColumns.DATA}; Cursor cursor = managedQuery(uri, projection, null, null, null); startManagingCursor(cursor); int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA); // 记录图片的位置 Log.i("log cursor.moveToFirst(); return cursor.getString(column_index); } int poi = 0; @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } public boolean onKeyDown(int KeyCode,KeyEvent event){ if (KeyCode==KeyEvent.KEYCODE_BACK) { Intent goBackToMainIntent=new Intent(EditTravels.this,MainActivity.class); this.startActivity(goBackToMainIntent); finish(); } return false; } } (3)删除记事 代码: Log.i("log", "menuInfo position "+menuInfo.position); cursor.moveToPosition(menuInfo.position); Log.i("log", "cursor move success"); adapter.removeListItem(menuInfo.position);//删除数据 adapter.notifyDataSetChanged();//通知数据源,数据已经改变,刷新界面 dm.close(); (4)查看记事 代码: public class CheckTravels extends Activity{ private TextView title; private TextView time; private TextView travels; public Cursor cursor=null; public String namestr=""; private DBManage dm=null; private Bitmap bitmap = null; private String path = null; private int rotate=0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.checktravels); title=(TextView)findViewById(R.id.checkTitle); time=(TextView)findViewById(R.id.checkTime); travels=(TextView)findViewById(R.id.checkContent); travels.setScroller(null); dm=new DBManage(this); Intent intent = getIntent();//获取启动该Activity的intent对象 String title= intent.getStringExtra("title"); String content = intent.getStringExtra("content"); String time= intent.getStringExtra("time"); long t = Long.parseLong(time); String datetime = DateFormat.format("yyyy-MM-dd kk:mm:ss", t).toString(); this.title.setText(title); this.time.setText(datetime); dm.open(); int i=0; int start=0; int end=0; String str1=null; String str2="["; String str4="]"; SpannableString travelsSpan =new SpannableString(content); for(i=0;i str1=content.substring(i, i+1); //travelsString+=str1; Log.i("log", str1); if(str1.equals(str2)) { start=i+1; } if(str1.equals(str4)) { end=i; namestr=content.substring(start,end); Log.i("log", namestr); cursor=dm.selcetPathByName(namestr); cursor.moveToFirst(); path=cursor.getString(cursor.getColumnIndex("path")); cursor.close(); namestr=null; Log.i("log", path); if(!(cursor==null)) { int count=cursor.getCount(); Log.i("log", "count----->"+count); BitmapFactory.Options options =new BitmapFactory.Options(); options.inJustDecodeBounds =true; bitmap =BitmapFactory.decodeFile(path, options); //此时返回bm为空 options.inJustDecodeBounds =false; int be = (int)(options.outHeight/ (float)100); if (be <= 0) be = 1; options.inSampleSize = be; bitmap=BitmapFactory.decodeFile(path,options); int bitmapwidth=options.outWidth; int bitmapheight=options.outHeight; //检查图片是否要翻转 try { ExifInterface exifInterface = new ExifInterface(path); int result = exifInterface.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); switch(result) { case ExifInterface.ORIENTATION_ROTATE_90: rotate = 90; Log.i("log", "rotate----->"+rotate); break; case ExifInterface.ORIENTATION_ROTATE_180: rotate = 180; Log.i("log", "rotate----->"+rotate); break; case ExifInterface.ORIENTATION_ROTATE_270: (5)布局文件 activity_main.xml文件 android:layout_height="fill_parent" android:background="@drawable/background" android:orientation="vertical" > android:layout_height="40dip" android:background="@drawable/lable" > android:layout_width="150dip" android:layout_height="40dip" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_marginTop="5dp" android:text=" 记 事 本 " android:textColor="#FF6600" android:textSize="24sp" android:textStyle="bold" > android:layout_width="35dip" android:layout_height="38dip" android:layout_alignParentRight="true" android:layout_marginTop="2dip" android:src="@drawable/writeicon" > android:layout_width="fill_parent" android:layout_height="fill_parent" > 5、程序截图 (1)新建文本 图 1 (2)修改文本 图 2 图 3 (3)查看事件 图 4 图 5 (4) 删除事件 图 6 图 7 (5)关于记事本 图 8 经过一周的学习,研究和开发,我终于按时完成了这个项目。通过这个项目的研发,我终于认识到理论跟实际还是有很大的不同的。对安卓的基本知识进行了锻炼,对自己的成果也有了很大的成就感,激发了我对安卓研究的巨大兴趣。 学生对课程设计以下几个方面综合评定: 设计目的及要求: 明确【 】 较明确【 】 不明确【 】 设计涉及基本原理: 完整【 】 较完整【 】 不完整【 】 设计方案: 设计总体思路: 严谨【 】 较严谨【 】 存在纰漏 【 】 方案内容: 条理清晰正确 【 】 条理一般,论述基本正确【 】 条理混论,存在抄袭 【 】 还存在其他问题: 指导教师签字(盖章):
三、结论
四、指导教师评语及成绩通过此次设计过程我会到了许多知识,这也是在大学里第一次比较完整的完成一个小项目,虽然过程中遇到了许多困难,在同学和老师的帮助下一一克服了。通过不断的发现问题,总结问题和解决问题的过程,使我在此次课程设计中不断的提高,并且得到了宝贵的经验。 日期: 年 月 日
