《移动应用程序设计基础》实验四 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
资源中的图片以及内容只适用与学习