鬧鐘提醒備忘錄移動開發技術實驗報告 目錄 第一部分:APP 簡介 ................................................................................ 2
(1)
需求分析 .................................................................................. 2
(2)
系統目標 .................................................................................. 2
(3)
開發及運行環境 ...................................................................... 2
第二部分:開發技術 ................................................................................ 3
(1)SharedPrefenrences 技術 ........................................................... 3
(2)數據庫 ...................................................................................... 11
(3)CRUD 操作 ............................................................................. 12
(4)時鐘提醒 .................................................................................. 13
第三部分:功能介紹 .............................................................................. 15
(1)登錄模塊 .................................................................................. 15
(2)注冊模塊 .................................................................................. 16
(3)主界面模塊 .............................................................................. 16
(4)新建備忘錄模塊 ...................................................................... 17
(5)刪除備忘錄模塊 ...................................................................... 18
第四部分:遇到的問題和解決辦法 ...................................................... 20
(1)無法刷新 UI ............................................................................ 20
(1)無法使用某些 API .................................................................. 20
第五部分:總結 ...................................................................................... 21
第一部分:APP 簡介 (1 1 )
需求分析
隨著時代的發展,我們每天需要處理的事務也呈現了爆炸式的增長。記住親朋好友的生日并及時送上生日的祝福;記住上司布置的任務;記住幾天后的出行車票時間等,這些紛繁的信息記憶是不是正在讓您深陷其中?目前,手機上已經有了備忘錄功能和鬧鐘功能,但二者之間并沒有實現消息的互通(蘋果手機用戶可以設置事件的鬧鐘提醒,但是安卓用戶卻還沒有使用這樣的功能)。用戶在備忘錄中記錄下需要設置時間提醒事件后,還需要再打開鬧鐘app,并設置鬧鐘提醒,這在無形中增加了用戶的負擔,并且產生了糟糕的用戶體驗。
現在,這些都不再是問題,在本次的課程設計中,使用我的軟件,用戶可以十分方便的新建備忘錄,根據標題查找備忘錄事件,刪除已過期的備忘錄并可以隨意修改備忘錄內容。除此之外,用戶還可以為每條事件添加重要程度,并在主界面按重要程度展示所有的已建備忘錄列表本軟件致力于幫助用戶時刻記錄下生活中的重要信息并在設置的時間給用戶發送提醒,讓您不缺席生活中的重要時刻。
(2 2 )
系統目標
1,友好的操作界面和良好的人機互動。
2,軟件的登錄界面保證了信息的保密性。
3,隨時對重要信息的記錄并設置到時間提醒。
4,備忘錄內容的修改,刪除和查詢。
5,也可將其用作記錄本使用,代替原有的單一備忘錄 app。
6,系統可靠運行,安全有效。
(3 3 )
開發及運行環境
(1)
開發工具:Android Studio (2)
系統環境:Windows 10 家庭中文版 (3)
開發語言:Java,xml
第二部分:開發技術 (1 1 )
SharedPrefenrences s 技術
在用戶第一次進入軟件時,可以注冊個人賬號,包括賬號和密碼;密碼須二次輸入同樣的字符,否則無法注冊成功;賬號和密碼使用 SharedPrefenrence 技術保存。保存用戶的賬號密碼,屬于用戶的偏好參數,若使用數據庫來存儲這些數據,未免有些大材小用,此時 SharedPreferences 技術就派上用場。SharedPreferences 使用鍵-值的形式來存儲數據。在我們的實例中,賬號為鍵,密碼為值,具有唯一匹配性,我們只需要調用 SharedPreferences 的getXxx(name), 就可以根據鍵獲得對應的值。使用起來很方便!
登錄界面源碼:
package com.example.uilayouttest.Activity;
import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.support.v7.app.ActionBar; 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.EditText; import android.widget.TextView; import android.widget.Toast;
import com.example.uilayouttest.Adapter.MD5Utils; import com.example.uilayouttest.R;
public class LoginActivity extends AppCompatActivity {
private TextView tv_main_title;//標題
private TextView tv_back,tv_register,tv_find_psw;//返回鍵,顯示的注冊,找回密碼
private Button btn_login;//登錄按鈕
private String userName,psw,spPsw;//獲取的用戶名,密碼,加密密碼
private EditText et_user_name,et_psw;//編輯框
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//設置此界面為豎屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
init();
ActionBar actionbar=getSupportActionBar();
if(actionbar!=null)
actionbar.hide();
}
//獲取界面控件
private void init() {
//從 main_title_bar 中獲取的 id
tv_main_title=findViewById(R.id.tv_main_title);
tv_main_title.setText("登錄");
tv_back=findViewById(R.id.tv_back);
//從 activity_login.xml 中獲取的
tv_register=findViewById(R.id.tv_register);
tv_find_psw=findViewById(R.id.tv_find_psw);
btn_login=findViewById(R.id.btn_login);
et_user_name=findViewById(R.id.et_user_name);
et_psw=findViewById(R.id.et_psw);
//返回鍵的點擊事件
tv_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//登錄界面銷毀
LoginActivity.this.finish();
}
});
//立即注冊控件的點擊事件
tv_register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//為了跳轉到注冊界面,并實現注冊功能
Intent intent=new Intent(LoginActivity.this,RegisterActivity.class);
startActivityForResult(intent, 1);
}
});
//找回密碼控件的點擊事件
tv_find_psw.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳轉到找回密碼界面(此頁面暫未創建)
}
});
//登錄按鈕的點擊事件
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//開始登錄,獲取用戶名和密碼 getText().toString().trim();
userName=et_user_name.getText().toString().trim();
psw=et_psw.getText().toString().trim();
//對當前用戶輸入的密碼進行 MD5 加密再進行比對判斷, MD5Utils.md5( ); psw 進行加密判斷是否一致
String md5Psw= MD5Utils.md5(psw);
// md5Psw ; spPsw 為 根據從 SharedPreferences 中用戶名讀取密碼
// 定義方法 readPsw 為了讀取用戶名,得到密碼
spPsw=readPsw(userName);
// TextUtils.isEmpty
if(TextUtils.isEmpty(userName)){
Toast.makeText(LoginActivity.this, "請輸入用戶名", Toast.LENGTH_SHORT).show();
return;
}else if(TextUtils.isEmpty(psw)){
Toast.makeText(LoginActivity.this, "請輸入密碼", Toast.LENGTH_SHORT).show();
return;
// md5Psw.equals(); 判斷,輸入的密碼加密后,是否與保存在 SharedPreferences 中一致
}else if(md5Psw.equals(spPsw)){
//一致登錄成功
Toast.makeText(LoginActivity.this, "登錄成功", Toast.LENGTH_SHORT).show();
//保存登錄狀態,在界面保存登錄的用戶名 定義個方法 saveLoginStatus boolean 狀態 , userName 用戶名;
saveLoginStatus(true, userName);
//登錄成功后關閉此頁面進入主頁
Intent data=new Intent();
//datad.putExtra( ); name , value ;
data.putExtra("isLogin",true);
//RESULT_OK 為 Activity 系統常量,狀態碼為-1
// 表示此頁面下的內容操作成功將 data 返回到上一頁面,如果是用 back 返回過去的則不存在用 setResult 傳遞 data 值
setResult(RESULT_OK,data);
//銷毀登錄界面
LoginActivity.this.finish();
//跳轉到主界面,登錄成功的狀態傳遞到 MainActivity 中
startActivity(new Intent(LoginActivity.this, MainActivity.class));
return;
}else if((spPsw!=null&&!TextUtils.isEmpty(spPsw)&&!md5Psw.equals(spPsw))){
Toast.makeText(LoginActivity.this, "輸入的用戶名和密碼不一致", Toast.LENGTH_SHORT).show();
return;
}else{
Toast.makeText(LoginActivity.this, "此用戶名不存在", Toast.LENGTH_SHORT).show();
}
}
});
}
/**
*從 SharedPreferences 中根據用戶名讀取密碼
*/
private String readPsw(String userName){
//getSharedPreferences("loginInfo",MODE_PRIVATE);
//"loginInfo",mode_private; MODE_PRIVATE 表示可以繼續寫入
SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
//sp.getString() userName, "";
return sp.getString(userName , "");
}
/**
*保存登錄狀態和登錄用戶名到 SharedPreferences 中
*/
private void saveLoginStatus(boolean status,String userName){
//saveLoginStatus(true, userName);
//loginInfo 表示文件名
SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
//獲取編輯器
SharedPreferences.Editor editor=sp.edit();
//存入 boolean 類型的登錄狀態
editor.putBoolean("isLogin", status);
//存入登錄狀態時的用戶名
editor.putString("loginUserName", userName);
//提交修改
editor.commit();
}
/**
* 注冊成功的數據返回至此
* @param requestCode 請求碼
* @param resultCode 結果碼
* @param data 數據
*/
@Override
//顯示數據, onActivityResult
//startActivityForResult(intent, 1); 從注冊界面中獲取數據
//int requestCode , int resultCode , Intent data
// LoginActivity -> startActivityForResult -> onActivityResult();
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//super.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
if(data!=null){
//是獲取注冊界面回傳過來的用戶名
// getExtra().getString("***");
String userName=data.getStringExtra("userName");
if(!TextUtils.isEmpty(userName)){
//設置用戶名到 et_user_name 控件
et_user_name.setText(userName);
//et_user_name 控件的 setSelection()方法來設置光標位置
et_user_name.setSelection(userName.length());
}
}
} }
注冊界面源碼如下:
package com.example.uilayouttest.Activity;
import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.graphics.Color; import android.support.v7.app.ActionBar; 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.EditText; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast;
import com.example.uilayouttest.Adapter.MD5Utils; import com.example.uilayouttest.R;
public class RegisterActivity extends AppCompatActivity {
private TextView tv_main_title;//標題
private TextView tv_back;//返回按鈕
private Button btn_register;//注冊按鈕
//用戶名,密碼,再次輸入的密碼的控件
private EditText et_user_name,et_psw,et_psw_again;
//用戶名,密碼,再次輸入的密碼的控件的獲取值
private String userName,psw,pswAgain;
//標題布局
private RelativeLayout rl_title_bar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//設置頁面布局 ,注冊界面
setContentView(R.layout.activity_register);
//設置此界面為豎屏 //
ActionBar actionbar = getSupportActionBar(); //
if (actionbar != null) //
actionbar.hide();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
init();
}
private void init() {
//從 main_title_bar.xml 頁面布局中獲取對應的 UI 控件
tv_main_title=findViewById(R.id.tv_main_title);
// tv_main_title.setText("注冊");
tv_back=findViewById(R.id.tv_back);
//布局根元素
rl_title_bar=findViewById(R.id.title_bar); //
rl_title_bar.setBackgroundColor(Color.TRANSPARENT);
//從 activity_register.xml 頁面中獲取對應的 UI 控件
btn_register=findViewById(R.id.btn_register);
et_user_name=findViewById(R.id.et_user_name);
et_psw=findViewById(R.id.et_psw);
et_psw_again=findViewById(R.id.et_psw_again);
Button btnback=findViewById(R.id.btn_backtologin);
btnback.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
startActivity(new Intent(RegisterActivity.this,LoginActivity.class));
}
}); //
tv_back.setOnClickListener(new View.OnClickListener() { //
@Override //
public void onClick(View v) { //
//返回鍵 //
RegisterActivity.this.finish(); //
} //
});
//注冊按鈕
btn_register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//獲取輸入在相應控件中的字符串
getEditString();
//判斷輸入框內容
if(TextUtils.isEmpty(userName)){
Toast.makeText(RegisterActivity.this, "請輸入用戶名", Toast.LENGTH_SHORT).show();
return;
}else if(TextUtils.isEmpty(psw)){
Toast.makeText(RegisterActivity.this, "請輸入密碼", Toast.LENGTH_SHORT).show();
return;
}else if(TextUtils.isEmpty(pswAgain)){
Toast.makeText(RegisterActivity.this, "請再次輸入密碼", Toast.LENGTH_SHORT).show();
return;
}else if(!psw.equals(pswAgain)){
Toast.makeText(RegisterActivity.this, "輸入兩次的密碼不一樣", Toast.LENGTH_SHORT).show();
return;
/**
*從 SharedPreferences 中讀取輸入的用戶名,判斷SharedPreferences 中是否有此用戶名
*/
}else if(isExistUserName(userName)){
Toast.makeText(RegisterActivity.this, "此賬戶名已經存在", Toast.LENGTH_SHORT).show();
return;
}else{
Toast.makeText(RegisterActivity.this, "注冊成功", Toast.LENGTH_SHORT).show();
//把賬號、密碼和賬號標識保存到 sp 里面
/**
* 保存賬號和密碼到 SharedPreferences 中
*/
saveRegisterInfo(userName, psw);
//注冊成功后把賬號傳遞到 LoginActivity.java 中
// 返回值到 loginActivity 顯示
Intent data = new Intent();
data.putExtra("userName", userName);
setResult(RESULT_OK, data);
//RESULT_OK 為 Activity 系統常量,狀態碼為-1,
// 表示此頁面下的內容操作成功將 data 返回到上一頁面,如果是用 back 返回過去的則不存在用 setResult 傳遞 data 值
RegisterActivity.this.finish();
}
}
});
}
/**
* 獲取控件中的字符串
*/
private void getEditString(){
userName=et_user_name.getText().toString().trim();
psw=et_psw.getText().toString().trim();
pswAgain=et_psw_again.getText().toString().trim();
}
/**
* 從 SharedPreferences 中讀取輸入的用戶名,判斷 SharedPreferences 中是否有此用戶名
*/
private boolean isExistUserName(String userName){
boolean has_userName=false;
//mode_private SharedPreferences sp = getSharedPreferences( );
// "loginInfo", MODE_PRIVATE
SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
//獲取密碼
String spPsw=sp.getString(userName, "");//傳入用戶名獲取密碼
//如果密碼不為空則確實保存過這個用戶名
if(!TextUtils.isEmpty(spPsw)) {
has_userName=true;
}
return has_userName;
}
/**
* 保存賬號和密碼到 SharedPreferences 中 SharedPreferences
*/
private void saveRegisterInfo(String userName,String psw){
String md5Psw = MD5Utils.md5(psw);//把密碼用 MD5 加密
//loginInfo 表示文件名, mode_private SharedPreferences sp = getSharedPreferences( );
SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
//獲取編輯器, SharedPreferences.Editor
editor -> sp.edit();
SharedPreferences.Editor editor=sp.edit();
//以用戶名為 key,密碼為 value 保存在 SharedPreferences 中
//key,value,如鍵值對,editor.putString(用戶名,密碼);
editor.putString(userName, md5Psw);
//提交修改 editor.commit();
editor.commit();
} } (2 2 )數據庫
本軟件使用 SQLite 輕量級數據庫,在創建數據庫時,是通過使用SQLiteOpenHelper 類的構造函數實現 代碼如下:
public class DBOpenHelper extends SQLiteOpenHelper {
private static final String TAG = DBOpenHelper.class.getSimpleName();
private static final int VERSION = 1;
private static final String DB_NAME = "memo.db";
public DBOpenHelper() {
super(MemoApplication.getContext(), DB_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
/*第一次初始化 app,創建表結構 */
db.execSQL("CREATE TABLE IF NOT EXISTS " + ColumnContacts.EVENT_TABLE_NAME + "( "
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ ColumnContacts.EVENT_TITLE_COLUMN + " text, "
+ ColumnContacts.EVENT_CONTENT_COLUMN + " text, "
+ ColumnContacts.EVENT_CREATED_TIME_COLUMN + " datetime, "
+ ColumnContacts.EVENT_UPDATED_TIME_COLUMN + " datetime, "
+ ColumnContacts.EVENT_REMIND_TIME_COLUMN + " datetime, "
+ ColumnContacts.EVENT_IS_IMPORTANT_COLUMN + " INTEGER, "
+ ColumnContacts.EVENT_IS_CLOCKED + " INTEGER"
+ ")");
(3 3 )C C RUD 操作
使用 EventDao 類實現添加,查詢,刪除等操作 代碼如下:
1,查詢操作:
public List<Event> findAll() {
//降序排列,按重要性和創建時間 String sql = "SELECT * FROM " + ColumnContacts.EVENT_TABLE_NAME + " ORDER BY " + ColumnContacts.EVENT_IS_IMPORTANT_COLUMN + " DESC, " + ColumnContacts.EVENT_CREATED_TIME_COLUMN + " DESC";
return mTemplate.query(sql, mCallback);
} public List<Event> findAllWithNOClocked() { String sql = "SELECT * FROM " + ColumnContacts.EVENT_TABLE_NAME + " WHERE " + ColumnContacts.EVENT_IS_CLOCKED + " = " + Constants.EventClockFlag.NONE; return mTemplate.query(sql, mCallback); }
2,添加操作:
public int create(Event event) { return (int) mTemplate.create(ColumnContacts.EVENT_TABLE_NAME, generateContentValues(event, false));
}
3,更新操作:
public int update(Event event) {
return mTemplate.update(ColumnContacts.EVENT_TABLE_NAME, generateContentValues(event, true), BaseColumns._ID + "
= ?", Integer.toString(event.getmId())); }
4,刪除操作
public int remove(List<Integer> ids) {
StringBuilder whereConditions = new StringBuilder(BaseColumns._ID + " IN(");
for (Integer id : ids) {
whereConditions.append(id).append(",");
}
whereConditions.deleteCharAt(whereConditions.length() - 1).append(")");
return mTemplate.remove(ColumnContacts.EVENT_TABLE_NAME, whereConditions.toString());
}
(4 4 )時鐘提醒
在退出軟件后,為了讓我們的提醒服務在后臺保活,編寫 ClockService 類在后臺運行。
代碼如下:
public class ClockService extends Service {
private static final String TAG = "ClockService";
public static final String EXTRA_EVENT_ID = "extra.event.id";
public static final String EXTRA_EVENT_REMIND_TIME = "extra.event.remind.time";
public static final String EXTRA_EVENT = "extra.event";
private EventDao mEventDao = EventDao.getInstance();
public ClockService() {
Log.d(TAG, "ClockService: Constructor");
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: onStartCommand");
WakeLockUtil.wakeUpAndUnlock();
postToClockActivity(getApplicationContext(), intent);
return super.onStartCommand(intent, flags, startId);
}
private void postToClockActivity(Context context, Intent intent) {
Intent i = new Intent();
i.setClass(context, ClockActivity.class);
i.putExtra(EXTRA_EVENT_ID, intent.getIntExtra(EXTRA_EVENT_ID, -1));
Event event = mEventDao.findById(intent.getIntExtra(EXTRA_EVENT_ID, -1));
if (event == null) {
return;
}
i.putExtra(EXTRA_EVENT_REMIND_TIME, intent.getStringExtra(EXTRA_EVENT_REMIND_TIME));
i.putExtra(EXTRA_EVENT, event);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i); }
第三部分:功能介紹 (1 1 )登錄模塊
為了保證用戶的信息安全,在登錄界面實現使用賬號,密碼的登錄功能。存儲技術使用了 SharedPreference 鍵值對實現持久性存儲。在登錄界面將輸入的賬號與密碼與已注冊的賬號密碼進行比對。若賬號為空,則提示“請輸入用戶名”;若密碼為空,則提示“請輸入密碼”;若賬號與密碼不匹配,則提示“請輸入密碼”;若賬號密碼完全匹配,則提示“登錄成功”,并跳轉到主界面。
(2 2 )注冊模塊
用戶第一次進入軟件,可在登錄界面選擇“立即注冊”,進入注冊界面,輸入自定義用戶名,密碼并再次輸入密碼,確保輸入無誤,點擊注冊按鈕完成注冊;若二次輸入密碼不一致,則提示“兩次輸入密碼不一致”,并可以再次輸入;注冊成功自動跳轉到登錄界面。
(3 3 )主界面模塊
用戶登錄成功,,進入主界面,可以查看所有已建立的備忘錄,并選擇操作,包括新建備忘錄;瀏覽所有已建立備忘錄;查詢指定備忘錄;修改備忘錄內容;批量刪除備忘錄等。
(4 4 )新建備忘錄模塊
在主界面選擇控件加號,進入新建備忘錄界面。可選擇以下內容輸入:為該備忘錄建立標題,并選擇提醒時間,選擇該備忘錄是否是重要事件,最后在備注中輸入事件的詳細信息,點擊確定,提示備忘錄成功建立,并可在主界面查看。
(5 5 )刪除備忘錄模塊
在主界面點擊垃圾桶按鈕,進入刪除備忘錄功能,選擇零個或多個備忘錄,再次點擊“刪除”,提示刪除成功。
第四部分:遇到的問題和解決辦法 (1 1 )無法刷新 UI
問題:在測試過程中發現,當刪除某備忘錄時,MainActivity 的RecyclerView 不能及時刷新,后面經過仔細排查發現,Android 不允許在子線程中對 UI 進行刷新,對 UI 的刷新只能在主線程中實現。
解決辦法:Android 提供了一套異步消息處理機制,完美的解決了在子線程中進行 UI 操作的問題。首先在主線程中創建一個 Handler 對象,并重寫他的handlerMessage()方法。然后當我們的子線程需要進行 UI 操作時,就創建一個 Message 對象,并通過 Handler 把這條消息發出去,之后這條消息會被添加到 MessageQueue 中等待被處理,而 Looper 一直嘗試在 MessageQueue 中取出消息,最后回到 Handler 的 handlerMessage()中。這樣,就可以安心的進行 UI刷新了。
(1 1 )
無法使用某些 API
問題:某些功能的實現方法可以在網上搜索到,但實際使用時卻無法使用。
解決辦法:問題主要時 Android 的 高版本移除了一些 API,導致使用時報錯,后面通過查詢發現,Android 在移除 API 的同時會發布替換的 API,所以問題也完美解決。
在測試過程中也遇到了各種各樣的報錯,大多經過百度搜索解決方案都可以解決,此處便不再一一贅述!
第五部分:總結 通過本次的課程設計,我獲益頗多,從之前從未接觸過安卓開發到現在可以簡單的開發一個安卓小程序,實現簡單的增、刪、改、查功能。備忘錄是一個相對較簡單的 app,上手難度不高,但我覺得在我的本次實驗中還是有一些可圈可點之處。首先是功能上,備忘錄和鬧鐘的搭配使用,拋開了傳統備忘錄只能單一記錄事件的功能,做到了在記錄事件的同時還可以為事件設置鬧鐘;在設計上,軟件大的登錄注冊模塊使用了持久化技術,具體使用了SharedPreference 鍵值對存儲用戶的賬號和密碼,并創新性的使用鍵來存儲賬號,值存儲密碼,具體做法是使用用戶輸入的賬戶名作為鍵值來取出對應存儲的值,并將取出的值與用戶輸入的密碼比對,如果相同,則判斷登錄成功,跳轉到主界面;否則提醒用戶賬號或密碼出錯。
對軟件的未來展望,在設計時疏忽了將用戶的 id 加入我的備忘錄數據庫存儲,這導致了所有用戶共享自己的備忘錄,即不同用戶登錄不同賬號,看到的依然是相同的備忘錄列表。具體解決方案應是在新建備忘錄時將用戶登錄使用的賬號作為主鍵和備忘錄一并存儲到數據庫。其次在主界面刷新備忘錄列表時進行判斷,將用戶賬號作為判斷條件,只有存儲了該用戶賬號的備忘錄內容才被從數據庫取出;鬧鐘的提示聲音目前還只是 Android Studio 內置的,后面應該可以豐富,比如播放歌曲或自定義聲音。
通過這門課程以及實驗,使我對安卓開發有了初步的理解和認識,在以后的學習過程中,我還會再對安卓開發進行深入的了解,使自己不斷提升。
推薦訪問: 備忘錄 鬧鐘 提醒上一篇:經濟管理中計算機應用-實驗報告十
下一篇:經濟管理中計算機應用-實驗報告八
在偉大祖國73華誕之際,我參加了單位組織的“光影鑄魂”主題黨日活動,集中觀看了抗美援朝題材影片《長津湖》,再一次重溫這段悲壯歷史,再一次深刻感悟偉大抗美援朝精神。1950年10月,新中國剛剛成立一年,
根據省局黨組《關于舉辦習近平談治國理政(第四卷)讀書班的通知》要求,我中心通過專題學習、專題研討以及交流分享等形式,系統的對《習近平談治國理政》(第四卷)進行了深入的學習與交流,下面我就來談一談我個人
《習近平談治國理政》(第四卷)是在百年變局和世紀疫情相互疊加的大背景下,對以習近平同志為核心的黨中央治國理政重大戰略部署、重大理論創造、重大思想引領的系統呈現。它生動記錄了新一代黨中央領導集體統籌兩個
《真抓實干做好新發展階段“三農工作”》是《習近平談治國理政》第四卷中的文章,這是習近平總書記在2020年12月28日中央農村工作會議上的集體學習時的講話。文章指出,我常講,領導干部要胸懷黨和國家工作大
在《習近平談治國理政》第四卷中,習近平總書記強調,江山就是人民,人民就是江山,打江山、守江山,守的是人民的心。從嘉興南湖中駛出的小小紅船,到世界上最大的執政黨,在中國共產黨的字典里,“人民”一詞從來都
黨的十八大以來,習近平總書記以馬克思主義戰略家的博大胸襟和深謀遠慮,在治國理政和推動全球治理中牢固樹立戰略意識,在不同場合多次圍繞戰略策略的重要性,戰略和策略的關系,提高戰略思維、堅定戰略自信、強化戰
《習近平談治國理政》第四卷集中展示了以習近平同志為核心的黨中央在百年變局和世紀疫情相互疊加背景下,如何更好地堅持和發展中國特色社會主義而進行的生動實踐與理論探索;對于新時代堅持和發展什么樣的中國特色社
在黨組織的關懷下,我有幸參加了區委組織部組織的入黨積極分子培訓班。為期一周的學習,學習形式多樣,課程內容豐富,各位專家的講解細致精彩,對于我加深對黨的創新理論的認識、對黨的歷史的深入了解、對中共黨員的
《習近平談治國理政》第四卷《共建網上美好精神家園》一文中指出:網絡玩命是新形勢下社會文明的重要內容,是建設網絡強國的重要領域。截至2021年12月,我國網民規模達10 32億,較2020年12月增長4
剛剛召開的中國共產黨第十九屆中央委員會第七次全體會議上討論并通過了黨的十九屆中央委員會向中國共產黨第二十次全國代表大會的報告、黨的十九屆中央紀律檢查委員會向中國共產黨第二十次全國代表大會的工作報告和《