《移動應用程式設計基礎》實驗四 Android基本組件互動
實驗名稱:
點選單串列實作
所使用的工具軟體及環境:
JDK1.8,Android Studio
一、實驗目的:
【實驗目的】
本實驗是Android基本組件實驗,主要針對Activity、Service和Receiver實作和使用方法,通過實驗使學生掌握Activity的跳轉、Service的啟動停止以及Receiver的接受等,
【實驗要求】
- 使得學生熟悉Activity、Service和BroadCast基本使用;
- 使得學生掌握短信接收實作和使用;
- 使得學生掌握界面跳轉基本原理和使用方法;
- 使得學生掌握服務和廣播的基本機制,
【實驗原理】
1.Activity跳轉
startActivity——跳轉到目標頁面,引數為Intent;
startActivityForResult ——跳轉到下一個Activity,而當這個Activity被關閉以后,自動跳轉前一個Activity,并呼叫onActivityResult( )方法,引數為Intent和requestcode
2.Intent
Android基本的設計理念是鼓勵減少組件間的耦合,因此Android提供了Intent (意圖) ,Intent提供了一種通用的訊息系統,將要執行的動作的抽象的描述,一般來說是作為引數來使用,由Intent來協助完成Android各個組件之間的通訊 ,
Intent屬性:
- Action ,對執行動作的描述,在Intent類中定義了一些字串常量作為標準動作;
- data ,是對執行動作所要操作的資料的描述,Android中采用URI來表示資料;
例:VIEW_ACTION content://contacts/1表示顯示識別符號為”1″的聯系人的詳細資訊,
- catagory 類別,是被執行動作的附加資訊;
- extra 附加資訊,除了data之外,還可以通過extra附加資訊,extra屬性使用Bundle型別進行資料傳遞;
- component 組件,顯式指定Intent的目標組件的名稱;
- type 資料型別,顯式指定Intent的資料型別;
3.Service組件
Service一般由一個Activity或其他Context物件來啟動,當啟動Service之后,該Service將會在后臺運行,及時啟動這個Service的Activity或其他組件的生命周期已經結束,Service仍然會繼續運行,直到自己的生命周期結束為止,每個Service都應該在ndroidManifest.xml中進行宣告,Service的啟動方式有兩種,對應的生命周期也各不相同,
通過startService方法啟動,當系統呼叫startService方法,如果該Service還未啟動,則依法呼叫其onCreate方法和onStart方法來啟動,當其他Context物件呼叫stopService方法、Service呼叫自身的stopSelf或stopService方法時才會停止Service的執行,
通過bindService方法啟動,當系統呼叫bindService方法時,如果該Service未啟動,則會呼叫onCreate方法完成初始化作業,然后會將該Service和Context物件(如Activity)進行系結,當被系結的Context物件被銷毀時,與之綁在一起的Service也會停止運行,
4.Broadcast Receiver組件
Broadcast Receiver同Service一樣,并不提供與用戶互動的表示層,其實是一種負責接收廣播訊息并對訊息作出反應的組件,在Android的系統中就存在許多這樣的廣播,比如電池電量過低或信號過低時,系統就會發出廣播進行通知,
應用程式如果需要回應某一個廣播訊息,應該注冊對應的BroadcastReceiver物件,該物件繼承自BroadcastReceiver類,該類位于android.content包,這樣一來當系統或另外的應用程式發出特定廣播時,該應用程式就可以接受并做出回應,如啟動Activity等,
接受廣播的時候就需要通過IntentFilter物件來進行過濾,BroadcastReceiver的生命周期比較簡單,其只有一個回呼方法--onReceiver,該方法在應用程式接受到發給自己的廣播的時候呼叫,所以BroadcastReceiver的使用方法也相對簡單,只需要對onReceive方法進行合理重寫,在適當的地方注冊該BroadcastReceiver即可,
注冊BroadcastReceiver物件的方式有以下兩種,
在AndroidMannifest.xml檔案中宣告,注冊資訊包裹在<receiver></receiver>標簽中,并在<intent-filter>標簽內設定過濾規則,
在代碼中創建并設定IntentFilter物件,該IntentFilter物件包含了對廣播的過濾規則,然后在需要的地方呼叫Context.registerReceiver方法和Context.unregisterReceiver方法進行注冊和取消注冊,如果采用這種方式注冊的話,當Context物件被銷毀時,該BroadcastReceiver也就不復存在了,
二、實驗內容:
1.接收短信、開啟和停止服務的界面布局,
2.實作短信接收服務;
3.接收廣播資訊,
具體功能為:
- 實作短信金額通知功能,在訂餐程式,取消自動登錄功能,并在注冊界面增加開啟和停止短信通知服務按鈕,開啟短信按鈕點擊提交后顯示短信服務啟動成功對話框,短信通知服務開啟后,用戶點菜后,將“您點的菜品總價值***元”發到注冊手機上,停止短信按鈕點擊提交后現實短信服務停止對話框;
- 實作用戶點餐廣播功能,用戶點菜后,所點菜品及用戶名以廣播方式通知,廣播接收到后,打開一個新的頁面,以串列的方式追加一條記錄,顯示自己點的菜品和總價,
三、實驗結果測驗
(請先看上一篇移動應用程式設計基礎——點選單串列實作)
移動應用程式設計基礎——點選單串列實作_加載中.......-CSDN博客
在原來實驗基礎上,補充增加Menu.java檔案,增添MyReceiver.java、MyService.java、newlist.java以及注冊界面Register.java檔案;布局檔案中增加listview_two.xml和simpleadapter_list_item_two.xml以及注冊界面布局register.xml檔案,

主要實驗代碼:(完整所有代碼在資源下載壓縮包中,文章結尾有資源下載鏈接)
//Menu.java
package com.example.login;
import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
//import android.support.v7.app.AppCompatActivity;
public class Menu extends AppCompatActivity {
private ListView listView;
private int [] ivR = {
R.drawable.pic1, R.drawable.pic2,
};
private String[] titles;
private String[] content;
private String[] price;
private String TAG;
private Button less,add;
static public TextView num_sum;
static public String newlist_count1="0";
static public String newlist_count2="0";
private static final int SEND_SMS = 100;
MyReceiver myr = new MyReceiver();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_one);
num_sum=(TextView)findViewById(R.id.textView_sumprice);
//參考string中的檔案
listView = (ListView)findViewById(R.id.listView);
List<HashMap<String,Object>> arrayList = new ArrayList<>();
titles =getResources().getStringArray(R.array.item_title);
content =getResources().getStringArray(R.array.item_content);
price =getResources().getStringArray(R.array.item_price);
//創建自定義Adapter,繼承BaseAdapter
MyBaseAdapter MyBase=new MyBaseAdapter();
listView.setAdapter(MyBase);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
AlertDialog.Builder builder = new AlertDialog.Builder(Menu.this);
builder.setTitle("菜肴詳情");
builder.setCancelable(true); //點擊對話框以外的區域是否讓對話框消失
//設定正面按鈕
builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
//創建AlertDialog物件
AlertDialog dialog = builder.create();
//對話框顯示的監聽事件
if(i==0)
{
View dialogView = View.inflate(Menu.this, R.layout.dialog, null);
dialog.setView(dialogView);
}
else
{
View dialogView = View.inflate(Menu.this, R.layout.dialog2, null);
dialog.setView(dialogView);
}
dialog.show();
}
});
}
private void requestPermission() {
//判斷Android版本是否大于23
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS}, SEND_SMS);
return;
} else {
sendSMSS();
//已有權限
}
} else {
//API 版本在23以下
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case SEND_SMS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
sendSMSS();
} else {
// Permission Denied
Toast.makeText(Menu.this, "CALL_PHONE Denied", Toast.LENGTH_SHORT).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void sendSMSS() {
String dish1="",dish2="";
if(!newlist_count1.equals("0")){
dish1="1.白灼蝦";
}
if(!newlist_count2.equals("0")){
dish2="2.北京烤鴨";
}
String content = "顧客用戶名:"+MainActivity.usenameEdtxt.getText().toString()+'\n'+
"顧客號碼:"+MainActivity.phoneEdtxt.getText().toString()+'\n'+"菜品:" +
dish1+"(數量:"+Menu.newlist_count1+")"+'\n'+" "+dish2+"(數量:"+Menu.newlist_count2+")"+'\n'+
"總計:"+num_sum.getText().toString()+"元";
final String tele=MainActivity.phoneEdtxt.getText().toString();
if(content!=null){
SmsManager manager = SmsManager.getDefault();
ArrayList<String> strings = manager.divideMessage(content);
for (int i = 0; i < strings.size(); i++) {
//作為接收短息者
manager.sendTextMessage("5554", null, content, null, null);
//自己作為發短信的人
//manager.sendTextMessage(tele, null, content, null, null);
}
Toast.makeText(Menu.this, "發送成功", Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.setClass(Menu.this, newlist.class);
startActivity(intent);//跳轉
}
else{
Toast.makeText(this, "手機號或內容不能為空", Toast.LENGTH_SHORT).show();
}
return;
}
public void submit(View view){
String N=MainActivity.usenameEdtxt.getText().toString();
Intent it = new Intent("LIZHAOJING");//自定義廣播
// it.putExtra("Name",Name);//放入自定義資訊
sendBroadcast(it);//發送廣播
IntentFilter filter = new IntentFilter("LIZHAOJING");//接收廣播過濾器
registerReceiver(myr,filter);//注冊廣播
if(MainActivity.service_begin==1){
requestPermission();
}
else{
Intent intent = new Intent();
intent.setClass(Menu.this, newlist.class);
startActivity(intent);//跳轉
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unregisterReceiver(myr);//注銷廣播
super.onDestroy();
}
private class MyBaseAdapter extends BaseAdapter{
@Override
public int getCount() {
return 2;
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
View vi=View.inflate(Menu.this, R.layout.simpleadapter_list_item_one,null);
ImageView imageView=(ImageView) vi.findViewById(R.id.list_item_iv);
TextView titles_=(TextView) vi.findViewById(R.id.list_item_tv1);
TextView content_=(TextView) vi.findViewById(R.id.list_item_tv2);
TextView price_=(TextView) vi.findViewById(R.id.list_item_tv3);
TextView num=(TextView)vi.findViewById(R.id.textView_num);
TextView sum=(TextView)findViewById(R.id.textView_sumprice);
Button less=(Button)vi.findViewById(R.id.button_less);
Button add=(Button)vi.findViewById(R.id.button_add);
imageView.setBackgroundResource(ivR[i]);
titles_.setText(titles[i]);
content_.setText(content[i]);
price_.setText(price[i]);
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int a=Integer.parseInt((String)num.getText());
String a0=Integer.toString(a+1);
num.setText(a0);
if(i==0){
int t=Integer.parseInt((String)sum.getText());
String t0=Integer.toString(t+58);
sum.setText(t0);
newlist_count1=num.getText().toString();
}
else{
int t=Integer.parseInt((String)sum.getText());
String t0=Integer.toString(t+128);
sum.setText(t0);
newlist_count2=num.getText().toString();
}
}
});
less.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int a=Integer.parseInt((String)num.getText());
if(a==0)
{
String a0=Integer.toString(a);
num.setText(a0);
newlist_count1=num.getText().toString();
newlist_count2=num.getText().toString();
}
else {
String a0=Integer.toString(a-1);
num.setText(a0);
if(i==0){
int t=Integer.parseInt((String)sum.getText());
String t0=Integer.toString(t-58);
sum.setText(t0);
newlist_count1=num.getText().toString();
}
else
{
int t=Integer.parseInt((String)sum.getText());
String t0=Integer.toString(t-128);
sum.setText(t0);
newlist_count2=num.getText().toString();
}
}
}
});
return vi;
}
}
}
//MyReceiver.java
package com.example.login;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
String dish1="",dish2="";
if(!Menu.newlist_count1.equals("0")){
dish1="1.白灼蝦";
}
if(!Menu.newlist_count2.equals("0")){
dish2="2.北京烤鴨";
}
Toast.makeText(context,"顧客用戶名:"+MainActivity.usenameEdtxt.getText().toString()+'\n'+
"顧客號碼:"+MainActivity.phoneEdtxt.getText().toString()+'\n'+"菜品:" +
dish1+"(數量:"+Menu.newlist_count1+")"+'\n'+" "+dish2+"(數量:"+Menu.newlist_count2+")"+'\n'+
"總計:"+Menu.num_sum.getText().toString()+"元", Toast.LENGTH_LONG).show();
}}
//MyService.java
package com.example.login;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private static String TAG = "service demo";
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind...!");
return null;
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate...!");
super.onCreate();
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy...!");
super.onDestroy();
}
/* @Override
public void onRebind(Intent intent) {
Log.i(TAG, "onRebind...!");
super.onRebind(intent);
}*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand...!");
return super.onStartCommand(intent, flags, startId);
}
/* @Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind...!");
return true;
}*/
class MyBinder extends Binder{
public void emit(){
}
}
}
//newlist.java
package com.example.login;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class newlist extends AppCompatActivity {
private String [] dishes={
"白灼蝦","北京烤鴨"
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_two);
ListView listView = (ListView) findViewById(R.id.listview_two);
CustomBaseAdapter Myadapter=new CustomBaseAdapter();
listView.setAdapter(Myadapter);
}
private class CustomBaseAdapter extends BaseAdapter{
@Override
public int getCount() {
return 1;
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
View v=View.inflate(newlist.this,R.layout.simpleadapter_list_item_two,null);
TextView name=(TextView) v.findViewById(R.id.list_two_name);
TextView display1=(TextView) v.findViewById(R.id.list_two_one);
TextView display2=(TextView) v.findViewById(R.id.list_two_two);
TextView Sum=(TextView) v.findViewById(R.id.list_two_sum);
final String newlist_name=MainActivity.usenameEdtxt.getText().toString();
final String newlist_sum=Menu.num_sum.getText().toString();
name.setText(newlist_name);
if(!Menu.newlist_count1.equals("0")){
display1.setText("1.白灼蝦"+" (數量:"+Menu.newlist_count1+")");
}
if(!Menu.newlist_count2.equals("0")){
display2.setText("2.北京烤鴨"+" (數量:"+Menu.newlist_count2+")");
}
Sum.setText(newlist_sum);
return v;
}
}
}
實驗結果截圖:

其中畫筆畫掉的為統一用戶名
點擊開始服務,可以接收短信,當用戶提交完所選選單,將以短信的方式和廣播的形式出現,
心得與體會:
實驗較難,撰寫程序時間較長,雖能實作基本功能,但還需要不斷完善;對Activity跳轉、Intent、Service組件以及Broadcast Receiver組件進行不斷學習與運用,基本實作組件的使用,對今后的學習有了較大的幫助,
https://download.csdn.net/download/weixin_48388330/76299992
資源中的圖片以及內容只適用與學習
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/413945.html
標籤:其他
上一篇:冰狐智能輔助與AutoJS的區別
