因此,我创建了一个应用,该应用会根据从您的出发地到目的地的预计时间,在您的出发时间前25分钟设置闹钟。
我能够构建该应用程序,但是每当我按下搜索按钮时,该应用程序就会崩溃。我猜想它与placeautocomplete片段的集成有关,但不确定如何处理。
主要活动
package com.example.mobileassignment2.buildingblocks;
import android.app.AlarmManager;
import android.app.DialogFragment;
import android.app.PendingIntent;
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlaceAutocompleteFragment;
import com.google.android.gms.location.places.ui.PlaceSelectionListener;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity implements TimePickerDialog .OnTimeSetListener{
String DistanceResult;
String DurationResult;
String LeaveByHour;
String LeaveByMin;
String AlarmTimeHour;
String AlarmTimeMin;
int ArriveHour;
int ArriveMin;
int AlarmHour;
int AlarmMin;
Calendar alarmCalendar;
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
TextView textViewArriveByTime = (TextView)findViewById(R.id.textViewArriveByTime);
textViewArriveByTime.setText("Hour: "+ hourOfDay +"\n"+ "Minute: "+minute);
ArriveHour = hourOfDay;
ArriveMin = minute;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activitiy_main);
Button button = (Button) findViewById(R.id.ArriveByBtn);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
DialogFragment timePicker = new TimePickerFragment();
timePicker.show(getFragmentManager(), "time picker");
}
});
Reset();
}
public void Reset(){
DistanceResult = "";
DurationResult = "";
TextView Distance_Output = (TextView) findViewById(R.id.DistanceResult);
TextView Duration_Output = (TextView) findViewById(R.id.DurationResult);
Distance_Output.setText("Distance: " + DistanceResult);
Duration_Output.setText("Duration: " + DurationResult);
LeaveByMin = "";
AlarmTimeMin = "";
TextView LeaveBy_Calculated = (TextView) findViewById(R.id.LeaveBy);
LeaveBy_Calculated.setText("Leave By: " + LeaveByMin);
TextView AlarmTime_Calculated = (TextView) findViewById(R.id.AlarmTime);
AlarmTime_Calculated.setText("Alarm Time: " + AlarmTimeMin);
TextView textViewArriveByTime = (TextView)findViewById(R.id.textViewArriveByTime);
textViewArriveByTime.setText("Hour: "+"\n"+ "Minute: ");
}
private static final String TAG = "MainActivity";
public void SearchDistanceCommand(View view) {
PlaceAutocompleteFragment Start_Location = (PlaceAutocompleteFragment)
getFragmentManager().findFragmentById(R.id.StartLocation);
Start_Location.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(Place place) {
// TODO: Get info about the selected place.
Log.i(TAG, "Place: " + place.getName());
}
@Override
public void onError(Status status) {
// TODO: Handle the error.
Log.i(TAG, "An error occurred: " + status);
}
});
PlaceAutocompleteFragment Goal_Location = (PlaceAutocompleteFragment)
getFragmentManager().findFragmentById(R.id.GoalLocation);
Goal_Location.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(Place place) {
// TODO: Get info about the selected place.
Log.i(TAG, "Place: " + place.getName());
}
@Override
public void onError(Status status) {
// TODO: Handle the error.
Log.i(TAG, "An error occurred: " + status);
}
});
Reset();
if(Start_Location.toString().isEmpty()|| Goal_Location.toString().isEmpty()){
Toast MissingTextErrorHandle = Toast.makeText(getApplicationContext(), "You need to input data into both fields!", Toast.LENGTH_SHORT);
MissingTextErrorHandle.show();
}
else
{
new AsyncTaskParseJson().execute();
}
}
public class AsyncTaskParseJson extends AsyncTask<String, String, String> {
EditText Start_Location = (EditText) findViewById(R.id.StartLocation);
EditText Goal_Location = (EditText) findViewById(R.id.GoalLocation);
//To convert to UTC, how to use time picker
// EditText Arrive_By = (EditText) findViewById(R.id.ArriveBy);
String FormattedStartLocation = Start_Location.getText().toString().replaceAll(" ", "+");
String FormattedGoalLocation = Goal_Location.getText().toString().replaceAll(" ", "+");
String yourServiceUrl = "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=" + FormattedStartLocation + "&destinations=" + FormattedGoalLocation
/* + "&arrival_time=" + Arrive_By*/
+ "&key=___MY___SECRET___KEY___";
@Override
protected void onPreExecute() {
ProgressBar spinner;
spinner = (ProgressBar) findViewById(R.id.progressBar1);
spinner.setVisibility(View.VISIBLE);
}
@Override
protected String doInBackground(String... arg0) {
try {
httpConnect jParser = new httpConnect();
String json = jParser.getJSONFromUrl(yourServiceUrl);
JSONObject object = new JSONObject(json);
//contains ALL routes
JSONArray array = object.getJSONArray("rows");
// Get the first route
JSONObject route = array.getJSONObject(0);
// Take all elements
JSONArray elements = route.getJSONArray("elements");
//Take First Element
JSONObject element = elements.getJSONObject(0);
// Get Duration
JSONObject durationObject = element.getJSONObject("duration");
String duration = durationObject.getString("text");
DurationResult = duration;
// Get Distance
JSONObject distanceObject = element.getJSONObject("distance");
String distance = distanceObject.getString("text");
DistanceResult = distance;
//Get Leave By Time (ATTENTION!!: Need to edit for when duration > 1hr)
String sDMin = DurationResult;
//Nic: Remove Characters, Convert duration str to int, !!Assume duration is <1 Hr
sDMin = sDMin.replaceAll( " mins", "" );
int dMin = Integer.parseInt(sDMin);
int remMin = dMin % 60;
int remHour = dMin / 60;
int leaveHour = ArriveHour - remHour;
if (leaveHour < 0){
leaveHour = 23;
}
int leaveMin = ArriveMin - remMin -5;
if (leaveMin < 0){
leaveHour -= 1;
leaveMin += 60;
if (leaveHour < 0){
leaveHour = 23;
}
}
//Convert int to str for printing
String sLeaveHour = Integer.toString(leaveHour);
String sLeaveMin = Integer.toString(leaveMin);
LeaveByHour = sLeaveHour;
LeaveByMin = sLeaveMin;
//Get Alarm Time (int value), alarmManager later
//String sATMin = DurationResult;
//Nic: Remove Characters, Convert duration str to int, !!Assume duration is <1 Hr
//sATMin = sATMin.replaceAll( " mins", "" );
//int atMin = Integer.parseInt(sATMin);
/*int remAlarmMin = (atMin % 60) - 30;
int remAlarmHour = atMin / 60;
int alarmHour = ArriveHour - remAlarmHour;
int alarmMin = ArriveMin - remAlarmMin;
if (alarmMin < 0){
alarmHour -= 1;
alarmMin += 60;*/
int alarmHour = leaveHour;
if(alarmHour < 0){
alarmHour = 23;
}
int alarmMin = leaveMin - 30;
if (alarmMin < 0){
alarmHour -= 1;
alarmMin += 60;
if(alarmHour < 0){
alarmHour = 23;
}
}
//Set Global Variable to set calendar to set Alarm time
AlarmHour = alarmHour;
AlarmMin = alarmMin;
//Convert int to str for printing
String sAlarmHour = Integer.toString(alarmHour);
String sAlarmMin = Integer.toString(alarmMin);
AlarmTimeHour = sAlarmHour;
AlarmTimeMin = sAlarmMin;
Calendar calendar = Calendar.getInstance();
calendar.set(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH),
AlarmHour,
AlarmMin,
0);
alarmCalendar = calendar;
setAlarm(alarmCalendar.getTimeInMillis());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String strFromDoInBg) {
if(DistanceResult == null || DurationResult == null){
Toast ResultErrorHandle = Toast.makeText(getApplicationContext(), "We could not find any results! Sorry!", Toast.LENGTH_SHORT);
ResultErrorHandle.show();
}
ProgressBar spinner;
spinner = (ProgressBar) findViewById(R.id.progressBar1);
spinner.setVisibility(View.INVISIBLE);
TextView Distance_Output = (TextView) findViewById(R.id.DistanceResult);
Distance_Output.setText("Distance: " + DistanceResult);
TextView Duration_Output = (TextView) findViewById(R.id.DurationResult);
Duration_Output.setText("Duration: " + DurationResult);
TextView LeaveBy_Calculated = (TextView) findViewById(R.id.LeaveBy);
LeaveBy_Calculated.setText("Leave By| Hour: " + LeaveByHour + " Min: " + LeaveByMin);
TextView AlarmTime_Calculated = (TextView) findViewById(R.id.AlarmTime);
AlarmTime_Calculated.setText("Alarm Time| Hour " + AlarmTimeHour + " Min: " + AlarmTimeMin);
}
}
public void CancelAlarmCommand(){
cancelAlarm();
}
public void setAlarm(long timeInMillis) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,intent,0);
AlarmManager.AlarmClockInfo ac= new AlarmManager.AlarmClockInfo(timeInMillis, pendingIntent.getBroadcast(this,0,intent,0));
alarmManager.setAlarmClock(ac,pendingIntent);
Toast.makeText(this, "Alarm set!", Toast.LENGTH_SHORT).show();
}
private void cancelAlarm(){
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,intent,0);
alarmManager.cancel(pendingIntent);
}
}
Gradle应用
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "com.example.mobileassignment2.buildingblocks"
minSdkVersion 21
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:25.3.1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
implementation 'com.google.android.gms:play-services-places:15.0.1'
implementation 'com.google.android.gms:play-services-location:15.0.1'
}
Android清单
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyC0UU_6yNvnroXuHBWPd2_SPfBP9Y29bp4"/>
</application>
logcat
09-05 00:04:22.519 1530-9975 /? I / AudioFlinger:AudioFlinger的线程0xe57037c0 tid = 9975准备运行09-05 00:04:22.546 1530-1603 /? E / AudioFlinger:内存不足,无法容纳AudioTrack大小= 131296 09-05 00:04:22.548 1530-1603 /? E / AudioFlinger:createRecordTrack_l() initCheck失败-12;没有控制块? 09-05 00:04:22.554 2336-9720 / com.google.android.googlequicksearchbox:search E / AudioRecord:AudioFlinger无法创建记录轨道,状态:-12 09-05 00:04:22.575 2336-9720 / com.google.android.googlequicksearchbox:search E / AudioRecord-JNI:创建AudioRecord实例时出错:初始化 检查失败,状态为-12。 09-05 00:04:22.578 2336-9720 / com.google.android.googlequicksearchbox:search E / android.media.AudioRecord:初始化本机时错误代码-20 AudioRecord对象。