基于ssm实现的个人身体健康记录系统APP
1.项目简介
一个具备集 运动记录及查看,饮食热量营养查询,健康记录(心率监测,血压输入记录等),数据图表展示,个人信息维护 一体的简易Android客户端
心率识别参考:https://github.com/ZhaoYukai/HeartRate
其原理是通过摄像头闪光灯发出来的光,通过闪光灯识别手指的血管,读取摄像头红色素平均值/明暗变化,绘制心率曲线,检测曲线上下脉冲,计算心率值.
若要自己搭建一个服务器环境,请将本项目对应服务端部署好,并修改本项目RequestUtil.java中的BASE_URL为对应服务器地址
1.1课程设计题目要求:
-
基于安卓的健康减肥软件的设计与开发
-
现代手机成为人们不可或缺的一部分,而在手机中,安卓手机已经成为年轻人群的主流手机,而年轻人也对减肥瘦身如火如荼,健康减肥也是愈演愈烈。
-
采用安卓平台的健康减肥软件就体现出了很大的优势。采用安卓移动平台,让人们随时随地进行减肥,灵活准确的记录减肥成果,让人们的减肥更加透明化。
-
健康减肥软件主要以运动量的测定和评估为主,加以平衡膳食的健康生活方式为辅助,健康指数查询,给出了健康人的心率、血压、血糖等的标准指数,让大家作为健康的参考;
-
减肥日记,用来记录每天的走路数,让人们清晰的知道自己消耗的卡路里;
-
饮食搭配用来合理的搭配食物,给出饮食建议,知道自己将要增加多少卡路里,以免过多的摄入;
-
健康膳食,提供了大量早中晚的食物以及这些食物的热量,摄入多少出现的问题等信息;
-
运动循迹是利用 GPS 定位来标注你的位置和所走路线的,计算消耗的卡路里,这样让使用者更能了解自己运动的状态和位置。
## 简化后要求:
- 灵活准确的 记录减肥成果
-
健康减肥软件主要以
运动量的测定和评估
为主
- - 减肥日记 ,用来记录每天的 走路数 ,消耗的 卡路里 -
- 给出了健康 人的心率、血压、血糖 等的标准指数
- 运动循迹 是利用GPS定位来标注你的位置和所走路线的,计算消耗的卡路里
- 加以平衡膳食的健康生活方式为辅助, 健康指数查询
- 饮食搭配 用来合理的搭配食物,给出饮食建议,知道自己将要增加多少卡路里,以免过多的摄入
- 提供了大量早中晚的食物以及这些食物的热量,摄入多少出现的问题等信息
1.2开发工具
Android 端
MVP:Model View Presentation, DataBinding技术
名称 | 介绍 | 网址 |
---|---|---|
Android Studio 3.0 Beta7 | 安卓开发工具 | AndroidStudio |
网易mumu | 安卓模拟器 | 网易mumu |
nox夜神 | 安卓模拟器 | 夜神安卓模拟器 |
Web 端
SSM框架:Spring+SpringMVC+Mybatis+mysql
名称 | 介绍 | 网址 |
---|---|---|
IDEA | java开发IDE | IDEA官网 |
spring&springMVC | 网页开发框架 | spring |
maven | java依赖管理 | IDEA自带 |
tomcat 9.0 | java web 容器 | tomcat |
postman | http测试工具,Chrome App,看下方截图 | 在chrome里面下载 |
其他工具
名称 | 介绍 | 网址 |
---|---|---|
leangoo | 看板,敏捷开发,拆分任务,每日移动已完成任务 | Leangoo |
Gradle Dependence
名称 | 链接 | 备注 |
---|---|---|
底部tab | LuseenBottomNavigation | |
安卓Util库 | blankj:AndroidUtilCode | 参见 AndroidUtilCode_CN.md |
jackson | ||
圆形ImageView | CircleImageView | |
平滑加载图片的类库 | Glide | |
高德地图定位&地图api | amap高德地图api | |
Android 自定义图表库 | MPAndroidChart |
Code: ``` gradle compile 'com.github.armcha:LuseenBottomNavigation:1.8.2' compile 'com.blankj:utilcode:1.9.0' compile 'com.fasterxml.jackson.core:jackson-databind:2.9.1' compile 'de.hdodenhof:circleimageview:2.1.0' compile 'com.github.bumptech.glide:glide:4.1.1' annotationProcessor 'com.github.bumptech.glide:compiler:4.1.1'
compile 'com.amap.api:location:3.6.1' //定位
compile 'com.amap.api:3dmap:5.4.0' //导航,已包含3d地图
compile 'com.amap.api:search:5.3.1' //搜索
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
```
1.3.Ref:项目用到的技术/参考文档
DataBinding 技术
- DataBinding快速入门
- DataBinding-是时候放弃butterknife了
- Android MVVM框架 - Data Binding Library介绍
- DataBinding 中 BindingConversion 的使用
- Android dataBinding与ListView及事件详解
- databinding中的ImageView与Glide结合使用
Fragment介绍
BottomNavBar
SwipeRefreshLayout
资源
地图定位
异常处理参考文档
- ADB Install Fails With INSTALL_FAILED_TEST_ONLY - Stack overFlow
- AndroidStudio完美解决"Activity使用Handler时出现警告信息"的问题 - CSDN
- 【已解决】Android Studio中的gradle无法引用HttpClient库
- 我的Android进阶之旅------>解决:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
- jackson下划线和驼峰命名法自动忽略
- Android------startActivityForResult的详细用法
- Android:attempt to re-open an already-closed object
- Android实现圆形Imageview,带白色边框
- stackOverFlow - Warning:Android custom view should extend AppCompatTextView
- Android报错:No package identifier when getting value for resource number 0x00000003
- 笔记12--GridView--且解决与ScrollView共用的冲突问题
- ImageView 简单加载网络图片实例代码
- Android 背景渐变色(shape,gradient)
- Android 开发学习之路 - Android6.0运行时权限
- Jackson 将 json 字符串转换成泛型List
- Android 分享 - 调用系统自带分享功能
- android 调用系统图库查看指定路径的图片
2.系统设计
2.1项目配置
```xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 调用硬件相机权限 -->
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.flash" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<!-- 地图定位额外权限 -->
<!-- 允许程序读写手机状态和身份 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 允许程序访问CellID或WiFi热点来获取粗略的位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 用于申请调用A-GPS模块 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!-- 用于申请获取蓝牙信息进行室内定位 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="a570f782b63ac95a20a423186e245658" />
<activity
android:name=".LauncherActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LoginActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".RegisterActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".UpdateUserInfoActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".ChangePasswordActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".FoodListActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".FoodActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".HeartRateActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".BloodGlucoseActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".BloodPressureActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".WeightRecoardActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name=".RunActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
<service android:name="com.amap.api.location.APSService" />
<activity
android:name=".ShowRunRecordActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait" />
</application>
```
2.2布局实现
```xml
<data>
<variable
name="runRecord"
type="cn.yanweijia.slimming.entity.RunRecord" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/margin"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="@dimen/food_image_size"
android:layout_height="@dimen/food_image_size"
android:layout_marginEnd="5dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/sport" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_toEndOf="@id/image"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_weight="1"
android:text="@{runRecord.distance + `m`}"
android:textSize="15sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_weight="1"
android:text="@{runRecord.calorie + `Kcal`}"
android:textSize="15sp" />
<!--<TextView-->
<!--android:layout_width="0dp"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_marginTop="15dp"-->
<!--android:layout_weight="1"-->
<!--android:text="@{runRecord.speed + `km/h`}"-->
<!--android:textSize="12sp" />-->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_weight="1"
android:text="@{runRecord.pace + `min/km`}"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:textSize="15sp"
app:time="@{runRecord.starttime}" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:textSize="15sp"
app:time="@{runRecord.endtime}" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
```
2.3后端工具类
连接蓝牙打印机并进行打印
```java /* * Created by weijia on 2016/11/9. * function 连接蓝牙打印机并进行打印 /
public class BlueToothPrinter { private static BluetoothAdapter bluetoothAdapter; private static BluetoothDevice btDevice_result = null; //选中的蓝牙设备 private static Boolean isSelected = false; //蓝牙设备是否选过 private static IMyBinder binder;//IMyBinder接口,所有可供调用的连接和发送数据的方法都封装在这个接口内 private static boolean isConnect;//用来标识连接状态的一个boolean值 private static ServiceConnection conn; //运行时需要绑定Service
/**
* 打印到蓝牙打印机
*
* @param context 上下文
* @param text 欲打印内容
* @return
*/
public static boolean print(Context context, String text) {
//打开蓝牙开关,,蓝牙打开失败,则返回失败并退出
if (!BlueToothPrinter.turnOnBlueTooth(context))
return false;
//在弹出对话框Alert.Dialog中显示已配对设备信息(ListView) ,并供用户选择一蓝牙打印机设备
chooseADeviceAndPrint(context, text);
return true;
}
/**
* 打印到蓝牙打印机,这个是调试的时候针对已知蓝牙设备地址
*
* @param context 上下文
* @param blueToothAddress 蓝牙设备地址
* @param text 欲打印文本
* @return
*/
public static boolean print(Context context, String blueToothAddress, String text) {
//打开蓝牙开关,,蓝牙打开失败,则返回失败并退出
if (!BlueToothPrinter.turnOnBlueTooth(context))
return false;
//连接蓝牙,并进行打印
if (!printToDevice(context, blueToothAddress, text))
return false;
return true;
}
/**
* 将文本信息打印到蓝牙Device中
*
* @param context 上下文
* @param blueToothAddress 蓝牙设备地址
* @param text 与打印内容
* @return
*/
private static boolean printToDevice(final Context context, final String blueToothAddress, final String text) {
//bindService的参数conn
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定成功
binder = (IMyBinder) service;
//这个接口的实现在连接过程结束后执行(执行于UI线程),onsucess里执行连接成功的代码,onfailed反之;
binder.connectBtPort(blueToothAddress, new UiExecute() {
@Override
public void onsucess() {
//连接成功后在UI线程中的执行
isConnect = true;
Toast.makeText(context, "连接成功", Toast.LENGTH_LONG).show();
//此处也可以开启读取打印机的数据
//参数同样是一个实现的UiExecute接口对象
//如果读的过程重出现异常,可以判断连接也发生异常,已经断开
//这个读取的方法中,会一直在一条子线程中执行读取打印机发生的数据,
//直到连接断开或异常才结束,并执行onfailed
binder.acceptdatafromprinter(new UiExecute() {
@Override
public void onsucess() {
}
@Override
public void onfailed() {
isConnect = false;
Toast.makeText(context, "连接已断开", Toast.LENGTH_LONG).show();
}
});
//连接打印机打印
byte[] data0 = DataForSendToPrinterTSC.cls();
byte[] data1 = DataForSendToPrinterTSC.text(10, 10, "0", 0, 2, 2, text + "\n\n\n\n");
byte[] data2 = DataForSendToPrinterTSC.feed(4);
byte[] data = byteMerger(byteMerger(data0, data1), data2);
if (isConnect) {
binder.write(data, new UiExecute() {
@Override
public void onsucess() {
Toast.makeText(context, "发送成功", Toast.LENGTH_LONG)
.show();
}
@Override
public void onfailed() {
Toast.makeText(context, "发送失败", Toast.LENGTH_LONG)
.show();
}
});
}
//断开打印机的链接
if (isConnect) {//如果是连接状态才执行断开操作
binder.disconnectCurrentPort(new UiExecute() {
@Override
public void onsucess() {
Toast.makeText(context, "断开连接成功", Toast.LENGTH_LONG).show();
}
@Override
public void onfailed() {
Toast.makeText(context, "断开连接失败", Toast.LENGTH_LONG).show();
}
});
}
context.unbindService(conn);
}
@Override
public void onfailed() {
//连接失败后在UI线程中的执行
isConnect = false;
Toast.makeText(context, "连接失败", Toast.LENGTH_LONG).show();
}
});
}
};
//绑定service,获取ImyBinder对象
Intent intent = new Intent(context, XprinterService.class);
context.bindService(intent, conn, context.BIND_AUTO_CREATE);
//下面这个要在Activity结束的时候运行::::已经在断开打印机的代码中执行.
//context.unbindService(conn);
return true;
}
/**
* 在弹出对话框Alert.Dialog中显示已配对设备信息(ListView) ,并供用户选择一蓝牙打印机设备
*
* @param context Activity的Context
* @return 选中的Device
*/
private static void chooseADeviceAndPrint(final Context context, final String text) {
LinearLayout linearLayoutDialog = new LinearLayout(context);
linearLayoutDialog.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
ListView listView = new ListView(context);
listView.setFadingEdgeLength(0);
List<Map<String, String>> deviceList = new ArrayList<Map<String, String>>(); //建立一个数组存储listview上显示的设备信息
final Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
//获取所有已配对设备列表
for (BluetoothDevice bt : pairedDevices) {
Map<String, String> deviceMap = new HashMap<String, String>();
deviceMap.put("name", bt.getName());
deviceMap.put("macAddress", bt.getAddress());
deviceList.add(deviceMap);
}
Toast.makeText(context.getApplicationContext(), "显示已配对设备", Toast.LENGTH_SHORT).show();
SimpleAdapter adapter = new SimpleAdapter(context, deviceList, android.R.layout.simple_list_item_2, new String[]{"name", "macAddress"}, new int[]{android.R.id.text2, android.R.id.text1});
listView.setAdapter(adapter);
linearLayoutDialog.addView(listView); //在布局中加入ListView
//对话框
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.chooseADevice)
.setView(linearLayoutDialog)
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
})
.setCancelable(false).create();
dialog.setCanceledOnTouchOutside(false); //除了dialog以外的地方不能被点击
dialog.show();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Iterator<BluetoothDevice> iterator = pairedDevices.iterator();
BluetoothDevice btDevice = null;
for (int i = 0; i <= position && iterator.hasNext(); i++) {
btDevice = iterator.next();
}
btDevice_result = btDevice;
isSelected = true;
//连接蓝牙,并进行打印
printToDevice(context, btDevice_result.getAddress(), text);
}
});
}
/**
* 打开蓝牙开关
*
* @param context Activity的Context
* @return 是否打开成功
*/
private static boolean turnOnBlueTooth(Context context) {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//判断蓝牙开关状态并打开蓝牙开关
if (!bluetoothAdapter.isEnabled()) {
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(turnOn);
Toast.makeText(context.getApplicationContext(), "蓝牙成功打开", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context.getApplicationContext(), "蓝牙已是打开状态", Toast.LENGTH_LONG).show();
}
//再次获取打开状态,打开失败则返回
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!bluetoothAdapter.isEnabled())
return false;
else
return true;
}
/**
* byte数组拼接
*/
private static byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
byte[] byte_3 = new byte[byte_1.length + byte_2.length];
System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
return byte_3;
}
}
```
图像处理类
```java public abstract class YUV420SPUtils { // public static int decodeYUV420SPtoY(byte[] yuv420sp, int width, int height) { // // if (yuv420sp == null) return 0; // // int yuv_y = 0; // for (int j = 0, yp = 0; j < height; j++) { // for (int i = 0; i < width; i++, yp++) { // int y = (0xff & ((int) yuv420sp[yp])) - 16; // if (y < 0) y = 0; // yuv_y += y; // } // }return yuv_y; // }
/**
* 内部调用的处理图片的方法
*/
private static int decodeYUV420SPtoRedSum(byte[] yuv420sp, int width, int height) {
if (yuv420sp == null) {
return 0;
}
final int frameSize = width * height;
int sum = 0;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width;
int u = 0;
int v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0) {
y = 0;
}
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0) {
r = 0;
} else if (r > 262143) {
r = 262143;
}
if (g < 0) {
g = 0;
} else if (g > 262143) {
g = 262143;
}
if (b < 0) {
b = 0;
} else if (b > 262143) {
b = 262143;
}
int pixel = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
int red = (pixel >> 16) & 0xff;
sum += red;
}
}
return sum;
}
/**
* 对外开放的图像处理方法
*/
public static int decodeYUV420SPtoRedAvg(byte[] yuv420sp, int width, int height) {
if (yuv420sp == null) {
return 0;
}
final int frameSize = width * height;
int sum = decodeYUV420SPtoRedSum(yuv420sp, width, height);
return (sum / frameSize);
}
}
```
2.4业务代码
```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_food); objectMapper = new ObjectMapper(); myHandler = new FoodActivityHandler(); DBManager.initSQLiteDB(this); list = new ArrayList<>();
Intent intent = getIntent();
foodId = intent.getIntExtra("foodid", 1);
initDatas();
binding.print.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
BlueToothPrinter.print(FoodActivity.this, "DC:0D:30:00:7E:8C", objectMapper.writeValueAsString(food));
BlueToothPrinter.print(FoodActivity.this, objectMapper.writeValueAsString(food));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
});
}
/**
* initial food information
*/
private void initDatas() {
binding.setTitle("标题");
binding.setFoodCategory("食物分类");
binding.setFood(new Food());
new Thread(new Runnable() {
@Override
public void run() {
String jsonResult = RequestUtils.getFoodInfoById(foodId);
Message msg = new Message();
Bundle bundle = new Bundle();
try {
JSONObject jsonObject = new JSONObject(jsonResult);
if (jsonObject.getBoolean("success")) {
msg.what = GET_INFO_SUCCESS;
bundle.putString("message", jsonObject.getString("message"));
food = objectMapper.readValue(jsonObject.getString("food"), Food.class);
binding.setFood(food);
FoodCategory foodCategory = DBManager.getFoodCategory(food.getCategory());
binding.setFoodCategory(foodCategory == null ? "unknow" : foodCategory.getName());
binding.setTitle(food.getName().substring(0, (food.getName().indexOf(',') > 0 ? food.getName().indexOf(',') : food.getName().length())));
} else {
msg.what = GET_INFO_FAIL;
bundle.putString("message", jsonObject.getString("message"));
}
} catch (Exception e) {
msg.what = GET_INFO_FAIL;
Log.e(TAG, "run: ", e);
}
msg.setData(bundle);
myHandler.sendMessage(msg);
}
}).start();
}
private void getFoodMeasurement() {
new Thread(new Runnable() {
@Override
public void run() {
String jsonResult = RequestUtils.getFoodMeasurements(foodId);
try {
JSONObject json = new JSONObject(jsonResult);
if (json.getBoolean("success")) {
JSONArray jsonArray = json.getJSONArray("foodMeasurement");
for (int i = 0; i < jsonArray.length(); i++) {
FoodMeasurement foodMeasurement = objectMapper.readValue(jsonArray.getString(i), FoodMeasurement.class);
list.add(foodMeasurement);
}
}
} catch (Exception e) {
Log.e(TAG, "run: ", e);
}
ListAdapter<FoodMeasurement> adapter = new ListAdapter<>(FoodActivity.this, list, R.layout.food_measurement_item, BR.foodMeasurement);
binding.setAdapter(adapter);
}
}).start();
}
class FoodActivityHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case GET_INFO_SUCCESS:
getFoodMeasurement();
break;
case GET_INFO_FAIL:
Toast.makeText(FoodActivity.this, R.string.load_food_fail, Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(FoodActivity.this, R.string.unknow_exception, Toast.LENGTH_SHORT).show();
Log.d(TAG, "handleMessage: Unknow exception");
}
}
}
```
2.5postman接口测试
3.项目展示
参考文献
- 高并发环境下智慧健康平台的设计与优化(河北大学·周政男)
- 个人健康管理服务平台的设计和实现(厦门大学·傅俊旭)
- 面向社区的卫生服务管理系统的设计与实现(电子科技大学·陈晓)
- 某运动管理App的设计与实现(厦门大学·俞燕波)
- 基于Android的智能医疗监控终端软件的开发(西安科技大学·王璐)
- 基于SSH的个人健康管理系统的设计与实现(电子科技大学·孙蕾)
- 特定人群的健康数据管理系统的设计与实现(北京邮电大学·徐进)
- 基于J2EE平台MVC模式的个人健康管理系统的设计与实现(南昌大学·单文英)
- 面向社区的卫生服务管理系统的设计与实现(电子科技大学·陈晓)
- 企业员工健康管理信息系统的设计与实现(大连理工大学·许菲)
- 高并发环境下智慧健康平台的设计与优化(河北大学·周政男)
- 基于.NET的健康检查个性化服务系统(大连理工大学·刘华林)
- 基于J2EE的居民健康管理系统的设计与实现(河北大学·李思佳)
- 人体健康评估及信息管理平台的设计与实现(山东大学·朱明贤)
- 健康管理云平台的设计与实现(北京交通大学·罗高博)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:毕设助手 ,原文地址:https://bishedaima.com/yuanma/35601.html