06-28 17:05:23.694 13262-13262 / io.hypertrack.sendeta.debug E / AndroidRuntime:致命异常:main 进程:io.hypertrack.sendeta.debug,PID:13262 java.lang.RuntimeException:无法启动活动ComponentInfo {io.hypertrack.sendeta.debug / io.hypertrack.sendeta.activities.MainActivity}: android.view.InflateException:二进制XML文件第4行:错误 膨胀类java.lang.reflect.Constructor
io.hypertrack.sendeta.activities.MainActivity.onCreate(MainActivity.java:109)
public class MainActivity extends AppCompatActivity implements LocationListener {
protected static final int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 1;
// Time in milliseconds; only reload weather if last update is longer ago than this value
private static final int NO_UPDATE_REQUIRED_THRESHOLD = 300000;
private static Map<String, Integer> speedUnits = new HashMap<>(3);
private static Map<String, Integer> pressUnits = new HashMap<>(3);
private static boolean mappingsInitialised = false;
Typeface weatherFont;
Weather todayWeather = new Weather();
TextView todayTemperature;
TextView todayDescription;
TextView todayWind;
TextView todayPressure;
TextView todayHumidity;
TextView todaySunrise;
TextView todaySunset;
TextView lastUpdate;
TextView todayIcon;
ViewPager viewPager;
TabLayout tabLayout;
View appView;
LocationManager locationManager;
ProgressDialog progressDialog;
int theme;
boolean destroyed = false;
private List<Weather> longTermWeather = new ArrayList<>();
private List<Weather> longTermTodayWeather = new ArrayList<>();
private List<Weather> longTermTomorrowWeather = new ArrayList<>();
public String recentCity = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
// Initialize the associated SharedPreferences file with default values
PreferenceManager.setDefaultValues(this, R.xml.prefs, false);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
setTheme(theme = getTheme(prefs.getString("theme", "fresh")));
boolean darkTheme = theme == R.style.AppTheme_NoActionBar_Dark ||
theme == R.style.AppTheme_NoActionBar_Classic_Dark;
boolean blackTheme = theme == R.style.AppTheme_NoActionBar_Black ||
theme == R.style.AppTheme_NoActionBar_Classic_Black;
// Initiate activity
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
appView = findViewById(R.id.viewApp);
progressDialog = new ProgressDialog(MainActivity.this);
// Load toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (darkTheme) {
toolbar.setPopupTheme(R.style.AppTheme_PopupOverlay_Dark);
} else if (blackTheme) {
toolbar.setPopupTheme(R.style.AppTheme_PopupOverlay_Black);
}
// Initialize textboxes
todayTemperature = (TextView) findViewById(R.id.todayTemperature);
todayDescription = (TextView) findViewById(R.id.todayDescription);
todayWind = (TextView) findViewById(R.id.todayWind);
todayPressure = (TextView) findViewById(R.id.todayPressure);
todayHumidity = (TextView) findViewById(R.id.todayHumidity);
todaySunrise = (TextView) findViewById(R.id.todaySunrise);
todaySunset = (TextView) findViewById(R.id.todaySunset);
lastUpdate = (TextView) findViewById(R.id.lastUpdate);
todayIcon = (TextView) findViewById(R.id.todayIcon);
weatherFont = Typeface.createFromAsset(this.getAssets(), "fonts/weather.ttf");
todayIcon.setTypeface(weatherFont);
// Initialize viewPager
viewPager = (ViewPager) findViewById(R.id.viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
destroyed = false;
initMappings();
// Preload data from cache
preloadWeather();
updateLastUpdateTime();
// Set autoupdater
AlarmReceiver.setRecurringAlarm(this);
}
public WeatherRecyclerAdapter getAdapter(int id) {
WeatherRecyclerAdapter weatherRecyclerAdapter;
if (id == 0) {
weatherRecyclerAdapter = new WeatherRecyclerAdapter(this, longTermTodayWeather);
} else if (id == 1) {
weatherRecyclerAdapter = new WeatherRecyclerAdapter(this, longTermTomorrowWeather);
} else {
weatherRecyclerAdapter = new WeatherRecyclerAdapter(this, longTermWeather);
}
return weatherRecyclerAdapter;
}
@Override
public void onStart() {
super.onStart();
updateTodayWeatherUI();
updateLongTermWeatherUI();
}
@Override
public void onResume() {
super.onResume();
if (getTheme(PreferenceManager.getDefaultSharedPreferences(this).getString("theme", "fresh")) != theme) {
// Restart activity to apply theme
overridePendingTransition(0, 0);
finish();
overridePendingTransition(0, 0);
startActivity(getIntent());
} else if (shouldUpdate() && isNetworkAvailable()) {
getTodayWeather();
getLongTermWeather();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
destroyed = true;
if (locationManager != null) {
try {
locationManager.removeUpdates(MainActivity.this);
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
private void preloadWeather() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
String lastToday = sp.getString("lastToday", "");
if (!lastToday.isEmpty()) {
new TodayWeatherTask(this, this, progressDialog).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "cachedResponse", lastToday);
}
String lastLongterm = sp.getString("lastLongterm", "");
if (!lastLongterm.isEmpty()) {
new LongTermWeatherTask(this, this, progressDialog).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "cachedResponse", lastLongterm);
}
}
private void getTodayWeather() {
new TodayWeatherTask(this, this, progressDialog).execute();
}
private void getLongTermWeather() {
new LongTermWeatherTask(this, this, progressDialog).execute();
}
private void searchCities() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(this.getString(R.string.search_title));
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setMaxLines(1);
input.setSingleLine(true);
alert.setView(input, 32, 0, 32, 0);
alert.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String result = input.getText().toString();
if (!result.isEmpty()) {
saveLocation(result);
}
}
});
alert.setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Cancelled
}
});
alert.show();
}
private void saveLocation(String result) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
recentCity = preferences.getString("city", Constants.DEFAULT_CITY);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("city", result);
editor.commit();
if (!recentCity.equals(result)) {
// New location, update weather
getTodayWeather();
getLongTermWeather();
}
}
private void aboutDialog() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Forecastie");
final WebView webView = new WebView(this);
String about = "<p>1.6.1</p>" +
"<p>A lightweight, opensource weather app.</p>" +
"<p>Developed by <a href='mailto:t.martykan@gmail.com'>Tomas Martykan</a></p>" +
"<p>Data provided by <a href='https://openweathermap.org/'>OpenWeatherMap</a>, under the <a href='http://creativecommons.org/licenses/by-sa/2.0/'>Creative Commons license</a>" +
"<p>Icons are <a href='https://erikflowers.github.io/weather-icons/'>Weather Icons</a>, by <a href='http://www.twitter.com/artill'>Lukas Bischoff</a> and <a href='http://www.twitter.com/Erik_UX'>Erik Flowers</a>, under the <a href='http://scripts.sil.org/OFL'>SIL OFL 1.1</a> licence.";
TypedArray ta = obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary, R.attr.colorAccent});
String textColor = String.format("#%06X", (0xFFFFFF & ta.getColor(0, Color.BLACK)));
String accentColor = String.format("#%06X", (0xFFFFFF & ta.getColor(1, Color.BLUE)));
ta.recycle();
about = "<style media=\"screen\" type=\"text/css\">" +
"body {\n" +
" color:" + textColor + ";\n" +
"}\n" +
"a:link {color:" + accentColor + "}\n" +
"</style>" +
about;
webView.setBackgroundColor(Color.TRANSPARENT);
webView.loadData(about, "text/html", "UTF-8");
alert.setView(webView, 32, 0, 32, 0);
alert.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
alert.show();
}
private String setWeatherIcon(int actualId, int hourOfDay) {
int id = actualId / 100;
String icon = "";
if (actualId == 800) {
if (hourOfDay >= 7 && hourOfDay < 20) {
icon = this.getString(R.string.weather_sunny);
} else {
icon = this.getString(R.string.weather_clear_night);
}
} else {
switch (id) {
case 2:
icon = this.getString(R.string.weather_thunder);
break;
case 3:
icon = this.getString(R.string.weather_drizzle);
break;
case 7:
icon = this.getString(R.string.weather_foggy);
break;
case 8:
icon = this.getString(R.string.weather_cloudy);
break;
case 6:
icon = this.getString(R.string.weather_snowy);
break;
case 5:
icon = this.getString(R.string.weather_rainy);
break;
}
}
return icon;
}
public static String getRainString(JSONObject rainObj) {
String rain = "0";
if (rainObj != null) {
rain = rainObj.optString("3h", "fail");
if ("fail".equals(rain)) {
rain = rainObj.optString("1h", "0");
}
}
return rain;
}
private ParseResult parseTodayJson(String result) {
try {
JSONObject reader = new JSONObject(result);
final String code = reader.optString("cod");
if ("404".equals(code)) {
return ParseResult.CITY_NOT_FOUND;
}
String city = reader.getString("name");
String country = "";
JSONObject countryObj = reader.optJSONObject("sys");
if (countryObj != null) {
country = countryObj.getString("country");
todayWeather.setSunrise(countryObj.getString("sunrise"));
todayWeather.setSunset(countryObj.getString("sunset"));
}
todayWeather.setCity(city);
todayWeather.setCountry(country);
JSONObject coordinates = reader.getJSONObject("coord");
if (coordinates != null) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.edit().putFloat("latitude", (float) coordinates.getDouble("lon")).putFloat("longitude", (float) coordinates.getDouble("lat")).commit();
}
JSONObject main = reader.getJSONObject("main");
todayWeather.setTemperature(main.getString("temp"));
todayWeather.setDescription(reader.getJSONArray("weather").getJSONObject(0).getString("description"));
JSONObject windObj = reader.getJSONObject("wind");
todayWeather.setWind(windObj.getString("speed"));
if (windObj.has("deg")) {
todayWeather.setWindDirectionDegree(windObj.getDouble("deg"));
} else {
Log.e("parseTodayJson", "No wind direction available");
todayWeather.setWindDirectionDegree(null);
}
todayWeather.setPressure(main.getString("pressure"));
todayWeather.setHumidity(main.getString("humidity"));
JSONObject rainObj = reader.optJSONObject("rain");
String rain;
if (rainObj != null) {
rain = getRainString(rainObj);
} else {
JSONObject snowObj = reader.optJSONObject("snow");
if (snowObj != null) {
rain = getRainString(snowObj);
} else {
rain = "0";
}
}
todayWeather.setRain(rain);
final String idString = reader.getJSONArray("weather").getJSONObject(0).getString("id");
todayWeather.setId(idString);
todayWeather.setIcon(setWeatherIcon(Integer.parseInt(idString), Calendar.getInstance().get(Calendar.HOUR_OF_DAY)));
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit();
editor.putString("lastToday", result);
editor.commit();
} catch (JSONException e) {
Log.e("JSONException Data", result);
e.printStackTrace();
return ParseResult.JSON_EXCEPTION;
}
return ParseResult.OK;
}
private void updateTodayWeatherUI() {
try {
if (todayWeather.getCountry().isEmpty()) {
preloadWeather();
return;
}
} catch (Exception e) {
preloadWeather();
return;
}
String city = todayWeather.getCity();
String country = todayWeather.getCountry();
DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(getApplicationContext());
getSupportActionBar().setTitle(city + (country.isEmpty() ? "" : ", " + country));
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
// Temperature
float temperature = UnitConvertor.convertTemperature(Float.parseFloat(todayWeather.getTemperature()), sp);
if (sp.getBoolean("temperatureInteger", false)) {
temperature = Math.round(temperature);
}
// Rain
double rain = Double.parseDouble(todayWeather.getRain());
String rainString = UnitConvertor.getRainString(rain, sp);
// Wind
double wind;
try {
wind = Double.parseDouble(todayWeather.getWind());
} catch (Exception e) {
e.printStackTrace();
wind = 0;
}
wind = UnitConvertor.convertWind(wind, sp);
// Pressure
double pressure = UnitConvertor.convertPressure((float) Double.parseDouble(todayWeather.getPressure()), sp);
todayTemperature.setText(new DecimalFormat("0.#").format(temperature) + " " + sp.getString("unit", "°C"));
todayDescription.setText(todayWeather.getDescription().substring(0, 1).toUpperCase() +
todayWeather.getDescription().substring(1) + rainString);
if (sp.getString("speedUnit", "m/s").equals("bft")) {
todayWind.setText(getString(R.string.wind) + ": " +
UnitConvertor.getBeaufortName((int) wind) +
(todayWeather.isWindDirectionAvailable() ? " " + getWindDirectionString(sp, this, todayWeather) : ""));
} else {
todayWind.setText(getString(R.string.wind) + ": " + new DecimalFormat("0.0").format(wind) + " " +
localize(sp, "speedUnit", "m/s") +
(todayWeather.isWindDirectionAvailable() ? " " + getWindDirectionString(sp, this, todayWeather) : ""));
}
todayPressure.setText(getString(R.string.pressure) + ": " + new DecimalFormat("0.0").format(pressure) + " " +
localize(sp, "pressureUnit", "hPa"));
todayHumidity.setText(getString(R.string.humidity) + ": " + todayWeather.getHumidity() + " %");
todaySunrise.setText(getString(R.string.sunrise) + ": " + timeFormat.format(todayWeather.getSunrise()));
todaySunset.setText(getString(R.string.sunset) + ": " + timeFormat.format(todayWeather.getSunset()));
todayIcon.setText(todayWeather.getIcon());
}
public ParseResult parseLongTermJson(String result) {
int i;
try {
JSONObject reader = new JSONObject(result);
final String code = reader.optString("cod");
if ("404".equals(code)) {
if (longTermWeather == null) {
longTermWeather = new ArrayList<>();
longTermTodayWeather = new ArrayList<>();
longTermTomorrowWeather = new ArrayList<>();
}
return ParseResult.CITY_NOT_FOUND;
}
longTermWeather = new ArrayList<>();
longTermTodayWeather = new ArrayList<>();
longTermTomorrowWeather = new ArrayList<>();
JSONArray list = reader.getJSONArray("list");
for (i = 0; i < list.length(); i++) {
Weather weather = new Weather();
JSONObject listItem = list.getJSONObject(i);
JSONObject main = listItem.getJSONObject("main");
weather.setDate(listItem.getString("dt"));
weather.setTemperature(main.getString("temp"));
weather.setDescription(listItem.optJSONArray("weather").getJSONObject(0).getString("description"));
JSONObject windObj = listItem.optJSONObject("wind");
if (windObj != null) {
weather.setWind(windObj.getString("speed"));
weather.setWindDirectionDegree(windObj.getDouble("deg"));
}
weather.setPressure(main.getString("pressure"));
weather.setHumidity(main.getString("humidity"));
JSONObject rainObj = listItem.optJSONObject("rain");
String rain = "";
if (rainObj != null) {
rain = getRainString(rainObj);
} else {
JSONObject snowObj = listItem.optJSONObject("snow");
if (snowObj != null) {
rain = getRainString(snowObj);
} else {
rain = "0";
}
}
weather.setRain(rain);
final String idString = listItem.optJSONArray("weather").getJSONObject(0).getString("id");
weather.setId(idString);
final String dateMsString = listItem.getString("dt") + "000";
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(Long.parseLong(dateMsString));
weather.setIcon(setWeatherIcon(Integer.parseInt(idString), cal.get(Calendar.HOUR_OF_DAY)));
Calendar today = Calendar.getInstance();
if (cal.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) {
longTermTodayWeather.add(weather);
} else if (cal.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR) + 1) {
longTermTomorrowWeather.add(weather);
} else {
longTermWeather.add(weather);
}
}
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit();
editor.putString("lastLongterm", result);
editor.commit();
} catch (JSONException e) {
Log.e("JSONException Data", result);
e.printStackTrace();
return ParseResult.JSON_EXCEPTION;
}
return ParseResult.OK;
}
private void updateLongTermWeatherUI() {
if (destroyed) {
return;
}
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
Bundle bundleToday = new Bundle();
bundleToday.putInt("day", 0);
RecyclerViewFragment recyclerViewFragmentToday = new RecyclerViewFragment();
recyclerViewFragmentToday.setArguments(bundleToday);
viewPagerAdapter.addFragment(recyclerViewFragmentToday, getString(R.string.today));
Bundle bundleTomorrow = new Bundle();
bundleTomorrow.putInt("day", 1);
RecyclerViewFragment recyclerViewFragmentTomorrow = new RecyclerViewFragment();
recyclerViewFragmentTomorrow.setArguments(bundleTomorrow);
viewPagerAdapter.addFragment(recyclerViewFragmentTomorrow, getString(R.string.tomorrow));
Bundle bundle = new Bundle();
bundle.putInt("day", 2);
RecyclerViewFragment recyclerViewFragment = new RecyclerViewFragment();
recyclerViewFragment.setArguments(bundle);
viewPagerAdapter.addFragment(recyclerViewFragment, getString(R.string.later));
int currentPage = viewPager.getCurrentItem();
viewPagerAdapter.notifyDataSetChanged();
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
if (currentPage == 0 && longTermTodayWeather.isEmpty()) {
currentPage = 1;
}
viewPager.setCurrentItem(currentPage, false);
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private boolean shouldUpdate() {
long lastUpdate = PreferenceManager.getDefaultSharedPreferences(this).getLong("lastUpdate", -1);
boolean cityChanged = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("cityChanged", false);
// Update if never checked or last update is longer ago than specified threshold
return cityChanged || lastUpdate < 0 || (Calendar.getInstance().getTimeInMillis() - lastUpdate) > NO_UPDATE_REQUIRED_THRESHOLD;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}