Can set location, see weather data

This commit is contained in:
2025-01-29 19:55:08 +01:00
parent fcf1624258
commit 1cf19b3934
4 changed files with 70 additions and 37 deletions
@@ -1,6 +1,8 @@
package eur.one00kb.minipogodynka;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
@@ -12,6 +14,8 @@ import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.LinearLayout;
@@ -22,13 +26,17 @@ import java.util.Locale;
import eur.one00kb.minipogodynka.adapters.AddressAdapter;
public class LocationSearchView extends LinearLayout {
// TODO: This doesn't need to have a parent. However, for some reason it screams with a bunch of
// exceptions when you extend AutoCompleteTextView.
public class LocationSearchView extends LinearLayout
implements TextWatcher, AdapterView.OnItemClickListener {
private static final String TAG = "LocationDialogView";
private static final int SUGGESTIONS_DELAY = 300;
private final Geocoder mGeocoder;
private final Handler mGeocodingHandler;
private final AddressAdapter mAddressAdapter;
private AutoCompleteTextView mSearchField;
private boolean mIsGeocodingAvailable;
public LocationSearchView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -37,41 +45,59 @@ public class LocationSearchView extends LinearLayout {
mAddressAdapter = new AddressAdapter(getContext());
mAddressAdapter.setNotifyOnChange(false);
mIsGeocodingAvailable = true;
mGeocoder = new Geocoder(getContext(), Locale.getDefault());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && !Geocoder.isPresent()) {
Log.w(TAG, "Geocoder is not present");
}
// TODO: Add check for "disabled" error if on a custom ROM without any location provider,
// and fallback to some other stuff, like an Internet API or something, or just change
// the layout to be latitude/longitude setting.
try {
mGeocoder.getFromLocationName("A", 1);
Log.i(TAG, "Geocoding is available and functional");
} catch (IOException e) {
mIsGeocodingAvailable = false;
Log.w(TAG, "Geocoding is unavailable or non-functional");
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mSearchField = findViewById(R.id.dl_search);
mSearchField.setAdapter(mAddressAdapter);
AutoCompleteTextView mSearchField = findViewById(R.id.dl_search);
mSearchField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
if (mIsGeocodingAvailable) {
mSearchField.setAdapter(mAddressAdapter);
mSearchField.addTextChangedListener(this);
mSearchField.setOnItemClickListener(this);
} else {
mSearchField.setEnabled(false);
mSearchField.setText(getContext().getString(R.string.dialog_search_error));
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mGeocodingHandler.removeCallbacksAndMessages(null);
mGeocodingHandler.postDelayed(() ->
new GeocodeAsyncTask(mGeocoder, mAddressAdapter)
.execute(s.toString()), SUGGESTIONS_DELAY);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@Override
public void afterTextChanged(Editable s) {
}
}
});
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mGeocodingHandler.removeCallbacksAndMessages(null);
mGeocodingHandler.postDelayed(() ->
new GeocodeAsyncTask(mGeocoder, mAddressAdapter)
.execute(s.toString()), SUGGESTIONS_DELAY);
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
((MainActivity) getContext()).setAddress(mAddressAdapter.getItem(position));
((MainActivity) getContext()).dismissLocationDialog();
AutoCompleteTextView mSearchField = findViewById(R.id.dl_search);
mSearchField.setText("");
}
// TODO: Perhaps get rid of this and use Thread or something.
@@ -3,6 +3,7 @@ package eur.one00kb.minipogodynka;
import android.app.AlertDialog;
import android.app.TabActivity;
import android.content.Intent;
import android.location.Address;
import android.location.Location;
import android.os.Bundle;
import android.view.Menu;
@@ -32,7 +33,7 @@ public class MainActivity extends TabActivity {
private static final String TAG = "MainActivity";
private PreferenceHolder mPreferenceHolder;
private Location mCurrentLocation;
private Address mCurrentAddress;
private Map<Date, WeatherData> mWeatherData;
private LocationSearchView mLocationSearchView;
@@ -53,8 +54,7 @@ public class MainActivity extends TabActivity {
mLocationDialog = new AlertDialog.Builder(this)
.setCancelable(false)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, null)
.setTitle(R.string.alert_location_title)
.setTitle(R.string.dialog_search_title)
.setView(mLocationSearchView).create();
mDetailsDialogBuilder = new AlertDialog.Builder(this)
@@ -98,10 +98,16 @@ public class MainActivity extends TabActivity {
return super.onOptionsItemSelected(item);
}
private void updateInfo() {
setTitle(String.format(Locale.getDefault(), "%.2f°; %.2f°",
mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()));
public void setAddress(Address address) {
mCurrentAddress = address;
setTitle(mCurrentAddress.getAddressLine(0));
}
public void dismissLocationDialog() {
mLocationDialog.dismiss();
}
private void updateInfo() {
Date forApiDate = Utilities.getDateOnly();
ArrayList<WeatherData> forAdapter = new ArrayList<>();
@@ -114,15 +120,15 @@ public class MainActivity extends TabActivity {
}
private void updateApiData() {
if (mCurrentLocation == null) {
if (mCurrentAddress == null) {
return;
}
Utilities.quickToast(this, "Fetching weather data…");
new Thread(() -> {
String apiData = WeatherAPIFetcher.fetch(mCurrentLocation.getLatitude(),
mCurrentLocation.getLongitude(), mPreferenceHolder.getProvider());
String apiData = WeatherAPIFetcher.fetch(mCurrentAddress.getLatitude(),
mCurrentAddress.getLongitude(), mPreferenceHolder.getProvider());
mWeatherData = WeatherAPIParser.parse(apiData, mPreferenceHolder.getProvider());
runOnUiThread(this::updateInfo);
}).start();
+1 -1
View File
@@ -11,7 +11,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="2"
android:hint="@string/alert_location_search"
android:hint="@string/dialog_search_field"
android:dropDownHeight="170dp" />
</eur.one00kb.minipogodynka.LocationSearchView>
+3 -2
View File
@@ -6,8 +6,9 @@
<string name="placeholder">Placeholder</string>
<string name="alert_location_title">Set location</string>
<string name="alert_location_search">Search for location</string>
<string name="dialog_search_title">Set location</string>
<string name="dialog_search_field">Search for location</string>
<string name="dialog_search_error">Geocoder unavailable</string>
<string name="menu_item_update">Update</string>
<string name="menu_item_location">Location</string>