安卓應用程序開發
課程設計報告
(2019—2020學年 第一學期)
基於Android的記事本系統
系 別 信息與控制工程
專 業 計算機科學與技術
班 級 1702
姓 名 曲路平
指導教師 郭 丹
目錄
1.設計目的
2.設計內容
3.可行性分析
4.系統設計與實現
4.1系統需求分析
4.2用例分析
4.3邏輯模型
4.4系統整體設計
4.5系統數據庫設計
4.6系統測試
4.7系統實現
5.總結
1.設計目的
隨着IT技術的成熟和智能手機的不斷普及,移動應用的需求與日俱增,移動應用開發成為當下最熱門的技術之一。而通過調查顯示,大部分消費者都會使用手機記事本功能。隨着手機記事本功能的不斷加強與完善,手機記事本對於人們的意義,已不僅僅像一般記事簿一樣簡單記錄,而是向着更個性化人性化的方向發展。記事本在生活和工作也日益凸顯出它的重要性,它能更好的幫助人們更好的管理自己的工作和生活,極大的方便了人們的生活。因其開源,我們可以在之上開發安卓記事本軟件,同時這也符合廣大的市場需求。
2.設計內容
本設計的基本內容是在Android平台下,設計與實現記事本軟件。具體實現的功能是:
(1) 設計實現添加“文字”,等功能模塊。
(2) 進入后,有“保存”“退出”選擇。
(3) 主頁面顯示記事列表,點擊可查看及時內容,並有“刪除”,“返回”等選擇。
3.可行性分析
(1) 技術可行性——這個項目僅需要一台裝有Eclipse及配置好Android開發環境的計算機即可,但是對計算機本身有要求.
(2) 經濟可行性——由於本軟件開發只有單個人,一台電腦就行,基本不需要太大的成本,在經濟上完全可行。
(3) 操作可行性——界面設計時充分考慮用戶的習慣以及手機方面的局限性,程序必須要很簡單;本程序沒有太大的難度,所以項目完全有可操作性。
4.系統設計與實現
4.1系統需求分析
該記事本軟件是一種主要用來記錄筆記的基於安卓平台的軟件,可以運行在安卓平台模擬器或運行在安卓平台的手持設備上。
(1).用戶觸發事件
記事本與外部環境的交互。在這個系統中,通過對系統的分析,可以識別出參與者:用戶。對於用戶而言,記事本上按鈕是用戶向系統輸入的操作請求的輸入設備,設備顯示器是用於向用戶輸出信息的輸出設備。
(2).系統的功能性需求
設計實現“添加文本”,“編輯內容/標題”和“刪除記事”等功能。
事件類別的管理(包括增加、刪除、修改);
事件的管理(包括增加、刪除、修改),關鍵信息包括:事件標題、事件內容、信息。
(3).軟件環境需求
軟件平台:Android2.0以上
4.2用例分析
系統用例圖描述的是用戶眼中的系統,即用戶希望系統有哪些功能。一個用例代表用戶與系統交互的一種方式。而識別用例最好方法是從參與者的角度分析系統。在Android記事本中,首先的參與者是用戶。如圖,它從用戶角度描述了該系統應該具有何種功能。
4.3邏輯模型
常規的Android手機記事本軟件主要功能模塊包括;記事,查看,編輯修改,刪除記事。如圖:
Android記事本軟件:
這次課題的目的是在Android系統的手機平台之上,研究與開發一個記事本軟件,提供適應手機的記事本功能服務,其中包括以下幾個功能:
(1)可以實現基本的文本功能,如新建文本,刪除修改文本,查看已有文件等。
(2)界面設計力求簡潔,整個軟件要盡量占用較少內存。
(3)可以進行日歷查看。
4.4系統總體設計
進入程序,顯示“精靈記事本”登錄后,點擊上面的新建按鈕開始記錄吧!
(1)界面設計
(2)處理流程設計
業務流程圖:
用戶進入手機記事本后,會看到所有記事列表頁面。列表頁面主菜單中包括添加、刪除菜單項。點擊添加,則進入添加頁面,添加成功后返回列表頁面,如圖:
數據增加流程圖:
添加記事時,數據由用戶輸入,點擊確定按鈕。如圖:
數據修改流程圖:
刪除數據:
(3)系統概述
本記事本軟件主要用於記錄生活點滴的基於Android平台的軟件,可以運行於基於Android平台的手持設備。
(4)系統總體結構
本作品實現的功能模塊主要包括:添加、刪除、修改事件,增加、刪除.
4.5系統數據庫設計
在記事本中軟件中,記事作為主要操作對象。
4.6系統測試
為了提高本應用程序的質量,使應用程序的使用更加人性化,友好化,一個完整的軟件測試是必不可少的。通過軟件測試我們能夠發現其中的一些錯誤和不合理的地方,這對於系統的完善是極有好處的。
(1)測試方案及測試用例
軟件測試是對軟件質量保證的關鍵步驟,它是在軟件投入運行前,對軟件的需求分析、軟件規格說明和編碼實現的最終審查。通過對軟件的定義有倆種描述,第一軟件測試是為了發現錯誤而必須執行的程序的過程;第二軟件測試是根據軟件設計開發各階段的需求說明和程序的內部構造而精心設計的一些測試用例,並利用這些測試用例運行程序和及時發現錯誤的過程,即執行測試步驟。
按照軟件測試用例的設計方法而論,軟件測試可以分為白盒測試和黑盒測試法。按照軟件測試的策略和過程分類,軟件測試可分為單元測試、集成測試、系統測試、驗證測試和確認測試。
(2)系統測試計划
在系統的開發和設計過程中,對系統做了如下幾個方面的測試:
功能及正確性測試:對后台記錄信息的增刪改查等操作的測試。
及時正確的處理系統各種錯誤的異常。
(3)系統測試及測試結果
添加記錄測試用例:
功能描述:驗證添加記錄信息功能。
用例目的:驗證添加記錄信息功能的實現。
前提條件:已經進入到添加記錄信息的頁面。
序號 |
輸入 |
輸出 |
實際情況 |
測試結果 |
1 |
輸入標題和內容 |
記錄成功在頁面中顯示 |
添加成功 |
正確 |
修改記錄測試用例:
功能描述:驗證修改記錄信息功能。
用例目的:驗證修改記錄信息功能的實現。
前提條件:已經進入到修改記錄信息的頁面。
序號 |
輸入 |
輸出 |
實際情況 |
測試結果 |
1 |
輸入標題和內容 |
記錄成功在頁面中顯示 |
添加成功 |
正確 |
刪除記錄測試用例:
功能描述:驗證刪除記錄信息功能。
用例目的:驗證刪除記錄信息功能的實現。
前提條件:已經進入到刪除記錄信息的頁面。
序號 |
輸入 |
輸出 |
實際情況 |
測試結果 |
1 |
點擊“刪除”按鈕 |
記錄信息在頁面中消失 |
刪除成功 |
正確 |
查看記錄測試用例:
功能描述:驗證查看記錄信息功能。
用例目的:驗證查看記錄信息功能的實現。
前提條件:已經進入到查看記錄信息的頁面。
序號 |
輸入 |
輸出 |
實際情況 |
測試結果 |
1 |
點擊“查看”按鈕 |
記錄信息在頁面中顯示 |
查看成功 |
正確 |
4.7系統實現
關鍵代碼:
(1)package com.example.jlnote2;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class AdapterDate extends BaseAdapter {
private Context context;
private List<Integer> days = new ArrayList<>();
//日歷數據
private List<Boolean> status = new ArrayList<>();
//簽到狀態,實際應用中初始化簽到狀態可通過該字段傳遞
private OnSignedSuccess onSignedSuccess;
//簽到成功的回調方法,相應的可自行添加簽到失敗時的回調方法
public AdapterDate(Context context) {
this.context = context;
int maxDay = DateUtil.getCurrentMonthLastDay();//獲取當月天數
for (int i = 0; i < DateUtil.getFirstDayOfMonth() - 1; i++) {
//DateUtil.getFirstDayOfMonth()獲取當月第一天是星期幾,星期日是第一天,依次類推
days.add(0);
//0代表需要隱藏的item
status.add(false);
//false代表為簽到狀態
}
for (int i = 0; i < maxDay; i++) {
days.add(i+1);
//初始化日歷數據
status.add(false);
//初始化日歷簽到狀態
}
}
@Override
public int getCount() {
return days.size();
}
@Override
public Object getItem(int i) {
return days.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
if(view==null){
view = LayoutInflater.from(context).inflate(R.layout.item_gv,null);
viewHolder = new ViewHolder();
view.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv = view.findViewById(R.id.tvWeek);
viewHolder.rlItem = view.findViewById(R.id.rlItem);
viewHolder.ivStatus = view.findViewById(R.id.ivStatus);
viewHolder.tv.setText(days.get(i)+"");
if(days.get(i)==0){
viewHolder.rlItem.setVisibility(View.GONE);
}
if(status.get(i)){
viewHolder.tv.setTextColor(Color.parseColor("#FD0000"));
viewHolder.ivStatus.setVisibility(View.VISIBLE);
}else{
viewHolder.tv.setTextColor(Color.parseColor("#666666"));
viewHolder.ivStatus.setVisibility(View.GONE);
}
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(status.get(i)){
Toast.makeText(context,"已經被標記!",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"標記成功!",Toast.LENGTH_SHORT).show();
status.set(i,true);
notifyDataSetChanged();
if(onSignedSuccess!=null){
onSignedSuccess.OnSignedSuccess();
}
}
}
});
return view;
}
class ViewHolder{
RelativeLayout rlItem;
TextView tv;
ImageView ivStatus;
}
public void setOnSignedSuccess(OnSignedSuccess onSignedSuccess){
this.onSignedSuccess = onSignedSuccess;
}
}
(2)package com.example.jlnote2;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends AppCompatActivity {
public Button btnlogin;
public EditText etname;
public EditText etpwd;
private CheckBox checkpwd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
btnlogin = (Button) findViewById(R.id.btnLogin);
etname = (EditText) findViewById(R.id.txtUserName);
etpwd = (EditText) findViewById(R.id.txtPassword);
checkpwd = (CheckBox) findViewById(R.id.ckRememberPassword);
//登錄-判斷輸入內容是否為空
btnlogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name = etname.getText().toString().trim();
String pwd = etpwd.getText().toString().trim();
if (TextUtils.isEmpty(pwd) || TextUtils.isEmpty(name)) {
Toast.makeText(LoginActivity.this, "輸入不能為空", Toast.LENGTH_SHORT).show();
return;
} else {
//登錄成功后跳轉到主界面MainActivity
Toast.makeText(LoginActivity.this, "登錄成功", Toast.LENGTH_SHORT).show();
startActivity(new Intent(LoginActivity.this, MainActivity.class));
}
}}
);}
}
(3)package com.example.mynote;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import java.util.ArrayList;
//主界面
public class MainActivity extends AppCompatActivity {
ListView listview;
LayoutInflater inflater;
ArrayList<Notepad> array;
MyDB_operate mdb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview=(ListView) findViewById(R.id.listView1);
inflater=getLayoutInflater();
mdb=new MyDB_operate(this);
array=mdb.getArray();
MyAdapter adapter=new MyAdapter(inflater,array);
listview.setAdapter(adapter);
//listview點擊事件
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent=new Intent(getApplicationContext(),SecondAtivity.class);
intent.putExtra("ids",array.get(position).getId() );
startActivity(intent);
MainActivity.this.finish();
}
});
//listview長按刪除功能
listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
final int position, long id) {
new AlertDialog.Builder(MainActivity.this)
.setMessage("確定刪除該記事?")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mdb.toDelete(array.get(position).getId());
array=mdb.getArray();
MyAdapter adapter=new MyAdapter(inflater,array);
listview.setAdapter(adapter);
}
})
.create().show();
return true;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item1:
//跳轉
Intent intent=new Intent(getApplicationContext(),SecondAtivity.class);
startActivity(intent);
this.finish();
break;
case R.id.item2:
//結束
MainActivity.this.finish();
break;
case R.id.item3:
Intent intent1=new Intent(getApplicationContext(),RiLiActivity.class);
startActivity(intent1);
this.finish();
break;
default:
break;
}
return true;
}
}
(4)package com.example.mynote;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDB extends SQLiteOpenHelper{
//sqllite數據庫
public MyDB(Context context) {
super(context, "mydate", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table mybook(ids integer PRIMARY KEY autoincrement,title text,content text,times text)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
(5)package com.example.mynote;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
public class MyDB_operate {
Context context;
MyDB mydb;
SQLiteDatabase myDatabase;
public MyDB_operate(Context context){
this.context=context;
mydb=new MyDB(context);
}
public ArrayList<Notepad> getArray(){
ArrayList<Notepad> array=new ArrayList<Notepad>();
ArrayList<Notepad> array1=new ArrayList<Notepad>();
myDatabase=mydb.getWritableDatabase();
Cursor cursor=myDatabase.rawQuery("select ids,title,times from mybook" , null);
cursor.moveToFirst();
while(!cursor.isAfterLast()){
int id=cursor.getInt(cursor.getColumnIndex("ids"));
String title=cursor.getString(cursor.getColumnIndex("title"));
String times=cursor.getString(cursor.getColumnIndex("times"));
Notepad note=new Notepad(id, title, times);
array.add(note);
cursor.moveToNext();
}
myDatabase.close();
for (int i = array.size(); i >0; i--) {
array1.add(array.get(i-1));
}
return array1;
}
public Notepad getTiandCon(int id){
myDatabase=mydb.getWritableDatabase();
Cursor cursor=myDatabase.rawQuery("select title,content from mybook where ids='"+id+"'" , null);
cursor.moveToFirst();
String title=cursor.getString(cursor.getColumnIndex("title"));
String content=cursor.getString(cursor.getColumnIndex("content"));
Notepad cun=new Notepad(title,content);
myDatabase.close();
return cun;
}
//修改
public void toUpdate(Notepad note){
myDatabase=mydb.getWritableDatabase();
myDatabase.execSQL("update mybook set title='"+ note.getTitle()+"',times='"+note.getTimes()+"',content='"+note.getContent() +"' where ids='"+ note.getId()+"'");
myDatabase.close();
}
//添加
public void toInsert(Notepad cun){
myDatabase=mydb.getWritableDatabase();
myDatabase.execSQL("insert into mybook(title,content,times)values('"+ cun.getTitle()+"','"+cun.getContent()+"','"+cun.getTimes()+"')");
myDatabase.close();
}
//刪除
public void toDelete(int ids){
myDatabase=mydb.getWritableDatabase();
myDatabase.execSQL("delete from mybook where ids="+ids+"");
myDatabase.close();
}
}
5.總結
通過這個課程設計,我收獲了一點小小的項目經驗。在設計整個軟件時,先明確要實現功能是非常重要的,要做什么?要用什么做?其次就是界面設計,界面是與用戶交互的接口,如何設計好界面?如何設計界面才能讓人看上去更協調?如何設計才能夠更友好地操作?這些都是我們要考慮的,等到這些都准備好后,才是開始寫代碼,這樣才不會慌亂,才能寫出條理清楚的代碼。
本記事本雖然是一個初級的入門小程序,但是涉及到的東西也很多,比如定位,這些平時在課本中都沒有接觸,就需要我們自己去查找資料,這讓我們體會到自學能力的重要性。未來,我們相信我們在擁有一些基本的素質之后,一定能夠在代碼的路上越走越遠。