安卓APP源码和设计报告——基于Android的垃圾分类系统
《移動(dòng)應(yīng)用開發(fā)》大作業(yè)報(bào)告
題 目?? ?基于Android的垃圾分類系統(tǒng)
系 部?? ?
班 級(jí)?? ?
學(xué) 生 姓 名?? ?
學(xué) 號(hào)?? ?
指 導(dǎo) 教 師?? ?
時(shí) 間?? ?
1、項(xiàng)目名稱
垃圾分類系統(tǒng)
2、項(xiàng)目概述
近些年,由于人民生活水平是的提高,生活方式與生活節(jié)奏的加快,使我國(guó)的垃圾生產(chǎn)數(shù)量已遠(yuǎn)超我國(guó)環(huán)境所能承受的能力,這也得到了國(guó)家領(lǐng)導(dǎo)人的注意,所以我國(guó)提出了垃圾分類的舉措。垃圾分類措施陸續(xù)在各地展開,我國(guó)將垃圾分為四類:可回收垃圾、有害垃圾、濕垃圾和干垃圾。
隨著越來(lái)越多的城市實(shí)施垃圾分類的政策,為了提供更加方便快捷的學(xué)習(xí)垃圾分類知識(shí),軟件的方式無(wú)疑是現(xiàn)代社會(huì)最有效可行的方式,所以開發(fā)了基于Android的垃圾分類系統(tǒng)。
本系統(tǒng)主要將垃圾分類與Android平臺(tái)的App相結(jié)合,開發(fā)出一個(gè)對(duì)用戶有所幫助的了解垃圾分類的系統(tǒng),運(yùn)用手機(jī)App 的易于流行的特點(diǎn),來(lái)讓人們了解垃圾分類的知識(shí)。因?yàn)槔鵁o(wú)處不在并且每個(gè)人每天都在產(chǎn)生垃圾,所以該App能夠滿足日常生活中絕大部分用戶的需求。
本系統(tǒng)最終開發(fā)了一個(gè)功能基本完善的垃圾分類系統(tǒng),集用戶的登錄和注冊(cè)管理、垃圾分類答題管理、搜索垃圾信息管理、垃圾分類百科學(xué)習(xí)管理為一體的垃圾分類系統(tǒng)。
該系統(tǒng)主要實(shí)現(xiàn)的功能模塊包括:
用戶中心模塊:實(shí)現(xiàn)用戶登錄和注冊(cè)的功能。
答題模塊:用戶通過(guò)答題的形式來(lái)辨別和加深對(duì)垃圾類別的認(rèn)識(shí)。
查詢垃圾信息模塊:通過(guò)文字搜索的方式查詢對(duì)應(yīng)類別垃圾的信息。
垃圾百科模塊:通過(guò)頁(yè)面學(xué)習(xí)四類垃圾的分類情況。
設(shè)置模塊:顯示登錄用戶名,用戶協(xié)議和強(qiáng)制下線等功能。
3、目的與要求
通過(guò)一個(gè)綜合的實(shí)例,進(jìn)一步掌握移動(dòng)應(yīng)用程序開發(fā)的基本原理和方法,提高基于Android Studio對(duì)圖形用戶界面的設(shè)計(jì)和開發(fā)能力,以及對(duì)控件事件處理、數(shù)據(jù)存儲(chǔ)以及網(wǎng)絡(luò)訪問(wèn)的能力。具體包括如下幾個(gè)方面:
1)熟練掌握Android開發(fā)工具Android Studio的使用。
2)熟練掌握Android線性布局的使用方法,并熟練使用Activity、Fragment、ListView、TextView、Button、EditText、ImageView等視圖組件構(gòu)建具有良好用戶體驗(yàn)的App界面。
3)熟練掌握對(duì)控件常用事件進(jìn)行處理的方法。
4)掌握數(shù)據(jù)存儲(chǔ)或網(wǎng)絡(luò)訪問(wèn)的基本方法。
4、系統(tǒng)實(shí)現(xiàn)環(huán)境
集成開發(fā)環(huán)境:Android Studio 3.0及以上
JDK :1.8及以上
Android版本:9.0及以上
Android API:28及以上
5、系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
1)用戶的賬號(hào)和密碼保持在安卓本地?cái)?shù)據(jù)庫(kù):使用 Android自帶的關(guān)系型數(shù)據(jù)庫(kù)SQLite。創(chuàng)建MydatabaseHelper繼承SQLiteOpenHelper。
static String name="user.db";
static int dbVersion=1;
public MydatabaseHelper(Context context){
super(context, name,null, dbVersion);
}
public void onCreate(SQLiteDatabase db) {
String sql="create table user(id integer primary key autoincrement,username varchar(20),password varchar(20))";
db.execSQL(sql);
}
2)登錄功能:在LoginActivity通過(guò).getText().toString()得到用戶輸入信息,在UserService里通過(guò)幫助類dbHelper獲得數(shù)據(jù)庫(kù)對(duì)象,通過(guò)UserService 類里面String sql="select * from user where username=? and password=?"根據(jù)用戶信息查詢數(shù)據(jù)庫(kù)信息,若用戶輸入信息匹配數(shù)據(jù)庫(kù)信息則登錄成功,反之則登錄失敗。
login = findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String account = et_account.getText().toString(); //得到用戶輸入信息
String password = et_password.getText().toString();
System.out.println(account);
System.out.println(password);
Log.i("TAG",account+"_"+password);
UserService uService=new UserService(LoginActivity.this);
boolean flag=uService.login(account, password);
if (flag) {
editor= pref.edit();
if(rememberPass.isChecked()){
editor.putBoolean("remember_password", true);
editor.putString("account",account);
editor.putString("password",password);
}else{
editor.clear();
}
editor.apply();
Log.i("TAG","登錄成功");
Toast.makeText(LoginActivity.this, "登陸成功", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("str",account);
startActivity(intent);
finish();
}
else {
Log.i("TAG","登錄失敗");
Toast.makeText(LoginActivity.this, "密碼或者用戶名輸入錯(cuò)誤!", Toast.LENGTH_SHORT).show();
}
}
});
3)注冊(cè)功能:通過(guò)UserService 類里面String sql="insert into user(username,password) values(?,?)"實(shí)現(xiàn)判斷注冊(cè)是否成功。
register.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String name=username.getText().toString().trim();
String pass=password.getText().toString().trim();
Log.i("TAG",name+"_"+pass);
UserService uService=new UserService(RegisterActivity.this);
User user=new User();
user.setUsername(name);
user.setPassword(pass);
uService.register(user);
Toast.makeText(RegisterActivity.this, "注冊(cè)成功", Toast.LENGTH_LONG).show();
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
});
UserService類:
public boolean login(String username,String password){
SQLiteDatabase sdb=dbHelper.getReadableDatabase();
String sql="select * from user where username=? and password=?";
Cursor cursor=sdb.rawQuery(sql, new String[]{username,password});
if(cursor.moveToFirst()==true){
cursor.close();
return true;
}
return false;
}
public boolean register(User user){
SQLiteDatabase sdb=dbHelper.getReadableDatabase();
String sql="insert into user(username,password) values(?,?)";
Object obj[]={user.getUsername(),user.getPassword()};
sdb.execSQL(sql, obj);
return true;
}
4)搜索功能:使用OkHttp和Gson進(jìn)行簡(jiǎn)單網(wǎng)絡(luò)請(qǐng)求與解析。在HttpUtil類里面創(chuàng)建sendOkHttpRequest()網(wǎng)絡(luò)請(qǐng)求方法,在進(jìn)行OKHttp封裝:在SearchActivity里通過(guò)String garbageUrl寫搜索接口地址,調(diào)用HttpUtil類中的sendOkHttpRequest()方法進(jìn)行搜索功能,在使用GSON將網(wǎng)絡(luò)返回的json字符串轉(zhuǎn)為對(duì)象。
HttpUtil類 :
public class HttpUtil {
public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url(address).build();
client.newCall(request).enqueue(callback);
}
}
SearchActivity :OKHttp封裝
public void requestGarbage(final String garbageID){
String garbageUrl=
"https://api.tianapi.com/lajifenlei/index?key=882f80503756018b20d77c21d92057bc&word="+garbageID;
HttpUtil.sendOkHttpRequest(garbageUrl, new Callback() {
public void onResponse(Call call, Response response) throws IOException {
final String responseText = response.body().string();
final GarbageSearch garbageSearch= Utility.handleGarbageSearchResponse(responseText);
Log.d(getClass().getSimpleName(), "========="+garbageSearch.msg);
runOnUiThread(new Runnable() {
public void run() {
Log.d(getClass().getSimpleName(), "========="+garbageSearch.msg);
if(garbageSearch!=null&&"success".equals(garbageSearch.msg) ) {
SharedPreferences.Editor editor=
PreferenceManager.getDefaultSharedPreferences(SearchActivity.this).edit();
editor.putString("garbageSearch",responseText);
editor.apply();
showGarbageInfo(garbageSearch);
}else {
Toast.makeText(SearchActivity.this,"獲取垃圾信息失敗",Toast.LENGTH_SHORT).show();
}
}
});
}
Utility :Gson解析json數(shù)據(jù)
public class Utility {
public static GarbageSearch handleGarbageSearchResponse(String response){
try{
return new Gson().fromJson(response, GarbageSearch.class);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}
5)百科學(xué)習(xí)功能:通過(guò)TabLayout與ViewPager的聯(lián)合使用實(shí)現(xiàn)頂部導(dǎo)航和頁(yè)面對(duì)應(yīng)一起切換。這樣通過(guò)FragmentPagerAdapter適配器把百科的四個(gè)垃圾Fragment與ViewPager連在一起。
public class PagerAdapter extends FragmentPagerAdapter {//定義適配器
List<Fragment> fragments;
public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments=fragments;
}
public int getCount() {
return fragments.size();//有幾個(gè)頁(yè)面
}
public Fragment getItem(int position) {
return fragments.get(position);//顯示第幾個(gè)頁(yè)面
}
6)答題功能:使用bean類序列化存儲(chǔ)題目實(shí)現(xiàn)答題功能。
private TextView btn_sub1;
private List<RefuseBean> mList;
private TextView select1;
private ImageView back;
private RadioGroup select1_1; // 題目
private int num = 0; // 分?jǐn)?shù)
private boolean isXaun = false;
select1 = findViewById(R.id.tv_timu);
select1_1 = findViewById(R.id.select1_1);
mList = new ArrayList<>();
// A 可回收物 B 干垃圾 C 有害垃圾 D 濕垃圾
RefuseBean refuseBean1 = new RefuseBean();
refuseBean1.setName("剩菜屬于什么垃圾?");
refuseBean1.setType("D 濕垃圾");
mList.add(refuseBean1);
num = (int) Math.floor(Math.random() * 10 + 1);
select1.setText(mList.get(num - 1).getName());
btn_sub1 = findViewById(R.id.btn_sub1);
select1_1.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup group, int checkedId) { //單選框 RadioGroup
isXaun = true; }
});
public void onClick(View v) {
TextView answer = (TextView) findViewById(R.id.answer);
if (!isXaun) {
Toast.makeText(ExamActivity.this, "請(qǐng)選擇答案", Toast.LENGTH_SHORT).show();
return;
}
String select11 = select1.getText().toString();
if (select11.equals(mList.get(num - 1).getName())) {
for (int i = 0; i < select1_1.getChildCount(); i++) {
RadioButton select1_1_1 = (RadioButton) select1_1.getChildAt(i);
String select1_1_11 = select1_1_1.getText().toString();
if (select1_1_1.isChecked()) {
if (select1_1_11.equals(mList.get(num - 1).getType())) {
switch (i) {
case 0:
answer.setText("您當(dāng)前答案是 A ,答對(duì)了,真棒!");
break;
case 1:
answer.setText("您當(dāng)前答案是 B ,答對(duì)了,真棒!");
break;
case 2:
answer.setText("您當(dāng)前答案是 C ,答對(duì)了,真棒!");
break;
case 3:
answer.setText("您當(dāng)前答案是 D ,答對(duì)了,真棒!");
break;
}
} else {
answer.setText("答錯(cuò)了,正確答案是 " + mList.get(num - 1).getType());
}
break;
}
}
}
7)強(qiáng)制下線功能:在應(yīng)用重新開始時(shí)注冊(cè)廣播接收器。因?yàn)閯?chuàng)建了BaseActivity類作為所有活動(dòng)的父類,所以只需要在BaseActivity中動(dòng)態(tài)注冊(cè)一個(gè)廣播接收器。在BaseActivity類的onResume()中new ForceOfflineReceiver()實(shí)現(xiàn)在應(yīng)用重新開始時(shí)注冊(cè)廣播接收器,在SettingsActivity里面的onClick()里添加sendBroadcast(intent)實(shí)現(xiàn)創(chuàng)建點(diǎn)擊提示強(qiáng)制下線。
主要代碼:
class ForceOfflineReceiver extends BroadcastReceiver{ // 創(chuàng)建一個(gè)廣播接收器
public void onReceive(final Context context, Intent intent) { // 寫一個(gè)強(qiáng)制下線的警告框
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("警告");
builder.setMessage("你正在強(qiáng)制下線");
builder.setCancelable(false);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCollector.finishAll();// 銷毀所有活動(dòng)
Intent intent = new Intent(context, LoginActivity.class); // 重新啟動(dòng)LoginActivity
context.startActivity(intent);
}
});
builder.show();
}
}
6、系統(tǒng)運(yùn)行結(jié)果
1)登錄注冊(cè)頁(yè)面:
?
?
圖1 登錄 圖2 注冊(cè)
2)首頁(yè):答題頁(yè)面和搜索頁(yè)面
?
圖3 首頁(yè) 圖2 答題頁(yè)面
?
圖4 搜索頁(yè)面
?
3)百科頁(yè)面:
?
圖5 百科頁(yè)面
?
?
?
?
?
?
4)設(shè)置頁(yè)面:
?
圖6 設(shè)置頁(yè)面 圖7 用戶協(xié)議
?
圖8 當(dāng)前版本 圖9 強(qiáng)制下線
?
7、實(shí)驗(yàn)總結(jié)
通過(guò)本學(xué)期Android studio的學(xué)習(xí),知道了Android是一個(gè)平臺(tái),它包括:基礎(chǔ)系統(tǒng)、開發(fā)工具和完整的文檔;,它采用Linux為其支撐操作系統(tǒng),以Java作為其開發(fā)環(huán)境,實(shí)現(xiàn)了完整的電話、視頻、網(wǎng)絡(luò)、界面設(shè)計(jì)等基礎(chǔ)功能。了解了一個(gè)界面就是一個(gè)Activity,View是組件,Intent:是Android應(yīng)用程序界面之間及功能部件之間實(shí)現(xiàn)信息交互的橋梁,Service運(yùn)行于后臺(tái)的程序,Android應(yīng)用程序的配置文件AndroidManifest.xml。
通過(guò)一個(gè)垃圾分類的實(shí)例,進(jìn)一步掌握移動(dòng)應(yīng)用程序開發(fā)的基本原理和方法,提高基于Android Studio對(duì)圖形用戶界面的設(shè)計(jì)和開發(fā)能力,以及對(duì)控件事件處理、數(shù)據(jù)存儲(chǔ)以及網(wǎng)絡(luò)訪問(wèn)的能力。但是在完成垃圾分類APP的設(shè)計(jì)過(guò)程中也出現(xiàn)了很多錯(cuò)誤。
比如配置錯(cuò)誤:使用OkHttp進(jìn)行網(wǎng)絡(luò)請(qǐng)求和使用Gson進(jìn)行數(shù)據(jù)解析時(shí)報(bào)錯(cuò),解決方法是在build.gradle中增加compile 'com.squareup.okhttp3:okhttp:3.2.0'和compile 'com.google.code.gson:gson:2.7'。在xml文件中寫頁(yè)面時(shí)也有很多錯(cuò)誤,比如圖片鋪不滿ImageView,加上屬性android:scaleType="fitXY"得到解決;頁(yè)面各個(gè)控件排布混亂,通過(guò)RelativeLayout和LinearLayout布局,orientation和layout_weight等屬性寫出基本滿意頁(yè)面布局。Java類中把ViewPager和Fragment結(jié)合起來(lái)時(shí),剛開始適配器是PagerAdapter,后來(lái)?yè)Q用FragmentPagerAdapter,當(dāng)你實(shí)現(xiàn)一個(gè)FragmentPagerAdapter,你必須至少覆蓋getCount()和getItem()方法。使用網(wǎng)絡(luò)請(qǐng)求時(shí)報(bào)權(quán)限錯(cuò)誤,在AndroidManifest.xml里面加入允許網(wǎng)絡(luò)android.permission.INTERNET得到解決。
本系統(tǒng)也還有很多有待改進(jìn)的地方,比如頁(yè)面UI不夠美觀,頁(yè)面功能不夠完善等。
?
總結(jié)
以上是生活随笔為你收集整理的安卓APP源码和设计报告——基于Android的垃圾分类系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于ArcGIS的入门建议
- 下一篇: Android 对apk进行签名