移动应用开发实验报告
课程名称
移动应用开发
班级 计科 1603
学号
姓名
实验名称
实验环境
实验三 天气预报应用实现
实验时间
第 15 周星期 4 第 78 节
PC/windows/Android Studio 3.0.1
目录
i. 问题描述................................................................................................................................................................... 1
ii. 设计简要描述 ..........................................................................................................................................................1
iii. 程序清单 .................................................................................................................................................................1
AndroidMainfest.xml; ............................................................................................................................................... 1
MainActivity.java ...................................................................................................................................................... 3
PhoneActivity.java.....................................................................................................................................................7
PhoneDetailActivity.java...........................................................................................................................................7
PhoneListActivity.java .............................................................................................................................................. 8
MorePhoneDetailActivity.java................................................................................................................................ 12
SlabActivity.java......................................................................................................................................................14
SlabDetailActivity.java............................................................................................................................................15
SlabListActivity.java............................................................................................................................................... 17
GetPictureHttps.java ................................................................................................................................................22
DatabaseHelper.java ................................................................................................................................................ 23
ReturnData.java....................................................................................................................................................... 24
SettingActivity.java................................................................................................................................................. 27
MapActivity.java..................................................................................................................................................... 29
PollService.java....................................................................................................................................................... 33
Activity_Dia.java.....................................................................................................................................................37
activity_main.xml ....................................................................................................................................................38
activity_phone.xml .................................................................................................................................................. 38
activity_slab.xml ......................................................................................................................................................39
fragment_phone_detail.xml.....................................................................................................................................39
fragment_phone_list.xml .........................................................................................................................................41
fragment_slab_detail.xml ........................................................................................................................................ 45
fragment_slab_list.xml ............................................................................................................................................ 47
activity_phone_detail.xml ....................................................................................................................................... 53
activity_setting.xml................................................................................................................................................. 55
activity_map.xml ..................................................................................................................................................... 56
activity__dia.xml ..................................................................................................................................................... 56
iv. APP 运行展示 ........................................................................................................................................................ 57
v. 调试报告 .................................................................................................................................................................61
实验中遇到的问题及解决方案: .........................................................................................................................61
经验与收获: ......................................................................................................................................................... 61
实验内容
i. 问题描述
实验三 天气预报应用实现
本次实验要求开发一个综合性 APP,实现基本的天气预报、通知和分享功能等。
1.如何实现平板和手机都适应的 APP。
2.如何从网络上获取数据,并解析 JSON 数据。
3.如何使用 SQLite,实现数据的存取。
4.如何设计各个菜单按钮,并实现其功能。
5.如何调用地图实现定位。
6.如何设计后台服务,实现定时通知。
7.如何实现 activity 与 fragment,fragment 与 fragment 之间的通信。
8.如何设计各个 UI 界面,并实现数据显示,加载网络图片。
ii. 设计简要描述
1.通过判别屏幕的长宽来显示来调用相应的 activity 布局,就可以实现手机和平板双适应。同时为了完
成平板下列表与详细界面,使用 fragment 容器就可以完成一个屏幕内显示两个 activity 布局。
2.因为网络服务延时较长,影响用户体验且 Android Studio 已不允许在主线程中访问网络,所以获取网
络数据,必须开辟一个新的线程。由于需求的 JSON 数据量不大,采用最原始的 JSON 数据解析方法,通
过 JSONobject 对象,来解析。
3.对于 SQLite 使用,根据实验前分析要建立一张天气表,来存放天气的状况,建立一张城市表,来存
放当前的城市名。基本逻辑如下:
首先获取城市表中最新的城市名,新建线程并利用这个城市名获取 JSON 数据,解析 JSON 数据并存
入数据库天气表中。UI 显示数据时,直接访问数据库,获取数据并显示。
4.添加菜单时,需要在 activity 中添加,不能在 fragment 中添加。
5.对于地图的定位,可以通过高德地图的 API 来定位,导入 jar 包,建立地图管理类,使用地图容器,
重写各个生命周期。定位成功后,将定位到的城市名存入数据库,否则提示定位失败。
6.在使用后台服务时,首先访问网络,获取新的天气数据存入数据库。再打开数据库,通知用户。最
后通过延时服务来调用这个后台服务,保证销毁这个 APP 后,依然可以实现后台通知。
7.fragment 与 activity 通信,可以通过回调函数实现,fragment 与 fragment 之间的通信可以通过广播通
信实现。
8.在设计 UI 界面时,严格参照实验指导书,访问数据库,获取数据并显示数据,最后建立线程实现加
载网络图片。
iii. 程序清单
主程序清单包括 27 个文件:
AndroidMainfest.xml;
1
MainActivity.java
package com.bignerdranch.android.weathersecond;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private int which;
private static final String TAG = "MainActivity";//记录主类的日志
private DatabaseHelper mDatabaseHelper;//SQLite 实例化对象
private static final String API_KEY = "bfba84c5276dcc1fdeef4f9bdd4f6d1b";//key
private JSONObject jsonObject;
private String CityName = "changsha";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建数据库
mDatabaseHelper = new DatabaseHelper(this,"Weather.db",null,1);
final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
ReturnData cns = new ReturnData(0);
3
if (cns.getCtiyName().equals("")){
//往数据库 city 表中写入初始值 beijing
ContentValues value = new ContentValues();//数据模型
value.put("cityName", CityName);
db.insert("city", null, value);
}
new Thread(new Runnable() {//创建线程,从网上获取 JSON 数据
@Override
public void run() {
try {
//获取当前城市:
ReturnData cn = new ReturnData(0);
if (!cn.getCtiyName().equals("")){
CityName = cn.getCtiyName();
}
Log.i(TAG,CityName);
String url = Uri.parse("https://api.openweathermap.org/data/2.5/forecast?")
.buildUpon()
.appendQueryParameter("q", CityName)
.appendQueryParameter("appid", API_KEY)
.appendQueryParameter("mode", "json")
.build().toString();
String jsonString = getUrlString(url);
Log.i(TAG, "received jsno:" + jsonString);
jsonObject = new JSONObject(jsonString);//获取 json 对象
//解析 JSON 数据及对数据库的操作
db.delete("weather", null, null);
ContentValues values = new ContentValues();//数据模型
//数据定义
String cityName;//城市
Double temp_max;//最高温度
Double temp_min;//最高温度
Double pressure;//气压
Double humidity;//湿度
String weatMain;//天气状况
String weatIcon;//图标
String date;//日期
String oldDate = null;
JSONObject city = jsonObject.getJSONObject("city");
cityName = city.getString("name");//城市
Log.i(TAG, "cityName:" + cityName);
JSONArray list = jsonObject.getJSONArray("list");
for (int i = 0; i < list.length(); i++) {
JSONObject listMain = list.getJSONObject(i);
JSONObject main = listMain.getJSONObject("main");
temp_max = main.getDouble("temp_max");//最高温度
temp_min = main.getDouble("temp_min");//最低温度
4
pressure = main.getDouble("pressure");
humidity = main.getDouble("humidity");//湿度
JSONArray weather = listMain.getJSONArray("weather");
JSONObject weatherMain = weather.getJSONObject(0);
weatMain = weatherMain.getString("main");//天气状况
weatIcon = weatherMain.getString("icon");//图标
JSONObject wind = listMain.getJSONObject("wind");
Double speed = wind.getDouble("speed");//风速
date = listMain.getString("dt_txt").substring(0, 10);//时间
if (!date.equals(oldDate)) {//只保存第一次数据
Log.i(TAG, "date:" + date);
values.put("date", date);
values.put("weather", weatMain);
values.put("picture", weatIcon);
values.put("maxC", temp_max);
values.put("minC", temp_min);
values.put("humidity", humidity);
values.put("pressure", pressure);
values.put("wind", speed);
db.insert("weather", null, values);
oldDate = date;//保存时间
values.clear();
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
//获取屏幕的尺寸,调用布局
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
if (displayMetrics.widthPixels >= displayMetrics.heightPixels) {
SlabActivity slabActivity = new SlabActivity();
getSupportFragmentManager().beginTransaction().replace(R.id.main_layout,
slabActivity).commit();
} else {
PhoneActivity phoneActivity = new PhoneActivity();
getSupportFragmentManager().beginTransaction().replace(R.id.main_layout,phoneActivity).commit();
}
}
/**
* getUrlBytes(String):从指定 URL 获取字节流数组
*/
5
public byte[] getUrlBytes(String urlSpec) throws IOException {
URL url = new URL(urlSpec);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = connection.getInputStream();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
throw new IOException(connection.getResponseMessage()+":with "+urlSpec);
}
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
}
out.close();
return out.toByteArray();
} finally {
connection.disconnect();
}
}
/**
* getUrlString(String):将字节流数据转化为 String
*/
public String getUrlString(String urlSpec) throws IOException {
return new String(getUrlBytes(urlSpec));
}
/**
* 创建菜单
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.fragment_menu,menu);
return true;
}
/**
* 菜单点击事件
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.mapLocation:
// Toast.makeText(this,"成功点击了,Map Location",Toast.LENGTH_SHORT).show();
Intent in = new Intent(MainActivity.this,MapActivity.class);
startActivity(in);
break;
case R.id.setting://启动设置页面
//
Toast.makeText(this,"成功点击了,Setting",Toast.LENGTH_SHORT).show();
6
Intent intent = new Intent(MainActivity.this,SettingActivity.class);
startActivity(intent);
break;
default:
break;
}
return true;
}
}
PhoneActivity.java
package com.bignerdranch.android.weathersecond;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by 31621 on 2018/12/3.
*/
public class PhoneActivity extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle
savedInstanceState) {
return inflater.inflate(R.layout.activity_phone, container, false);
}
}
PhoneDetailActivity.java
package com.bignerdranch.android.weathersecond;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Created by 31621 on 2018/12/3.
*/
public class PhoneDetailActivity extends Fragment {
private TextView mShowDate;
7