my app i've created using android studio keeps crashing , don't know why. weather app , i'm following google's developing android app course, here's logcat:
07-20 18:19:45.740 16410-16434/com.alexander.sunshine e/activitythread﹕ failed find provider info com.alexander.android.sunshine.app 07-20 18:19:45.748 16410-16434/com.alexander.sunshine e/androidruntime﹕ fatal exception: asynctask #1 process: com.alexander.sunshine, pid: 16410 java.lang.runtimeexception: error occured while executing doinbackground() @ android.os.asynctask$3.done(asynctask.java:304) @ java.util.concurrent.futuretask.finishcompletion(futuretask.java:355) @ java.util.concurrent.futuretask.setexception(futuretask.java:222) @ java.util.concurrent.futuretask.run(futuretask.java:242) @ android.os.asynctask$serialexecutor$1.run(asynctask.java:231) @ java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1112) @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:587) @ java.lang.thread.run(thread.java:818) caused by: java.lang.nullpointerexception: attempt invoke interface method 'boolean android.database.cursor.movetofirst()' on null object reference @ com.alexander.sunshine.app.fetchweathertask.addlocation(fetchweathertask.java:109) @ com.alexander.sunshine.app.fetchweathertask.getweatherdatafromjson(fetchweathertask.java:214) @ com.alexander.sunshine.app.fetchweathertask.doinbackground(fetchweathertask.java:414) @ com.alexander.sunshine.app.fetchweathertask.doinbackground(fetchweathertask.java:34) @ android.os.asynctask$2.call(asynctask.java:292) @ java.util.concurrent.futuretask.run(futuretask.java:237) at android.os.asynctask$serialexecutor$1.run(asynctask.java:231) at java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1112) at java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:587) at java.lang.thread.run(thread.java:818) and here's fetchweathertask.java:
package com.alexander.sunshine.app; import android.content.contenturis; import android.content.contentvalues; import android.content.context; import android.content.sharedpreferences; import android.database.cursor; import android.database.databaseutils; import android.net.uri; import android.os.asynctask; import android.preference.preferencemanager; import android.text.format.time; import android.util.log; import android.widget.arrayadapter; import com.alexander.sunshine.r; import com.alexander.sunshine.app.data.weathercontract; import com.alexander.sunshine.app.data.weathercontract.weatherentry; import org.json.jsonarray; import org.json.jsonexception; import org.json.jsonobject; import java.io.bufferedreader; import java.io.ioexception; import java.io.inputstream; import java.io.inputstreamreader; import java.net.httpurlconnection; import java.net.url; import java.text.simpledateformat; import java.util.date; import java.util.vector; public class fetchweathertask extends asynctask<string, void, string[]> { private final string log_tag = fetchweathertask.class.getsimplename(); private arrayadapter<string> mforecastadapter; private final context mcontext; public fetchweathertask(context context, arrayadapter<string> forecastadapter) { mcontext = context; mforecastadapter = forecastadapter; } private boolean debug = true; /* date/time conversion code going moved outside asynctask later, * convenience we're breaking out own method now. */ private string getreadabledatestring(long time){ // because api returns unix timestamp (measured in seconds), // must converted milliseconds in order converted valid date. date date = new date(time); simpledateformat format = new simpledateformat("e, mmm d"); return format.format(date).tostring(); } /** * prepare weather high/lows presentation. */ private string formathighlows(double high, double low) { // data fetched in celsius default. // if user prefers see in fahrenheit, convert values here. // rather fetching in fahrenheit user can // change option without having re-fetch data once // start storing values in database. sharedpreferences sharedprefs = preferencemanager.getdefaultsharedpreferences(mcontext); string unittype = sharedprefs.getstring( mcontext.getstring(r.string.pref_units_key), mcontext.getstring(r.string.pref_units_metric)); if (unittype.equals(mcontext.getstring(r.string.pref_units_imperial))) { high = (high * 1.8) + 32; low = (low * 1.8) + 32; } else if (!unittype.equals(mcontext.getstring(r.string.pref_units_metric))) { log.d(log_tag, "unit type not found: " + unittype); } // presentation, assume user doesn't care tenths of degree. long roundedhigh = math.round(high); long roundedlow = math.round(low); string highlowstr = roundedhigh + "/" + roundedlow; return highlowstr; } /** * helper method handle insertion of new location in weather database. * * @param locationsetting location string used request updates server. * @param cityname human-readable city name, e.g "mountain view" * @param lat latitude of city * @param lon longitude of city * @return row id of added location. */ long addlocation(string locationsetting, string cityname, double lat, double lon) { long locationid; // first, check if location city name exists in db cursor locationcursor = mcontext.getcontentresolver().query( weathercontract.locationentry.content_uri, new string[]{weathercontract.locationentry._id}, weathercontract.locationentry.column_location_setting + " = ?", new string[]{locationsetting}, null); if (locationcursor.movetofirst()) { int locationidindex = locationcursor.getcolumnindex(weathercontract.locationentry._id); locationid = locationcursor.getlong(locationidindex); } else { // content provider set up, inserting rows of data pretty simple. // first create contentvalues object hold data want insert. contentvalues locationvalues = new contentvalues(); // add data, along corresponding name of data type, // content provider knows kind of value being inserted. locationvalues.put(weathercontract.locationentry.column_city_name, cityname); locationvalues.put(weathercontract.locationentry.column_location_setting, locationsetting); locationvalues.put(weathercontract.locationentry.column_coord_lat, lat); locationvalues.put(weathercontract.locationentry.column_coord_long, lon); // finally, insert location data database. uri inserteduri = mcontext.getcontentresolver().insert( weathercontract.locationentry.content_uri, locationvalues ); // resulting uri contains id row. extract locationid uri. locationid = contenturis.parseid(inserteduri); } locationcursor.close(); // wait, worked? yes! return locationid; } /* students: code allow fetchweathertask continue return strings ux expects can continue test application once begin using database. */ string[] convertcontentvaluestouxformat(vector<contentvalues> cvv) { // return strings keep ui functional string[] resultstrs = new string[cvv.size()]; ( int = 0; < cvv.size(); i++ ) { contentvalues weathervalues = cvv.elementat(i); string highandlow = formathighlows( weathervalues.getasdouble(weatherentry.column_max_temp), weathervalues.getasdouble(weatherentry.column_min_temp)); resultstrs[i] = getreadabledatestring( weathervalues.getaslong(weatherentry.column_date)) + " - " + weathervalues.getasstring(weatherentry.column_short_desc) + " - " + highandlow; } return resultstrs; } /** * take string representing complete forecast in json format , * pull out data need construct strings needed wireframes. * * fortunately parsing easy: constructor takes json string , converts * object hierarchy us. */ private string[] getweatherdatafromjson(string forecastjsonstr, string locationsetting) throws jsonexception { // have string representing complete forecast in json format. // fortunately parsing easy: constructor takes json string , converts // object hierarchy us. // these names of json objects need extracted. // location information final string owm_city = "city"; final string owm_city_name = "name"; final string owm_coord = "coord"; // location coordinate final string owm_latitude = "lat"; final string owm_longitude = "lon"; // weather information. each day's forecast info element of "list" array. final string owm_list = "list"; final string owm_pressure = "pressure"; final string owm_humidity = "humidity"; final string owm_windspeed = "speed"; final string owm_wind_direction = "deg"; // temperatures children of "temp" object. final string owm_temperature = "temp"; final string owm_max = "max"; final string owm_min = "min"; final string owm_weather = "weather"; final string owm_description = "main"; final string owm_weather_id = "id"; try { jsonobject forecastjson = new jsonobject(forecastjsonstr); jsonarray weatherarray = forecastjson.getjsonarray(owm_list); jsonobject cityjson = forecastjson.getjsonobject(owm_city); string cityname = cityjson.getstring(owm_city_name); jsonobject citycoord = cityjson.getjsonobject(owm_coord); double citylatitude = citycoord.getdouble(owm_latitude); double citylongitude = citycoord.getdouble(owm_longitude); long locationid = addlocation(locationsetting, cityname, citylatitude, citylongitude); // insert new weather information database vector<contentvalues> cvvector = new vector<contentvalues>(weatherarray.length()); // owm returns daily forecasts based upon local time of city being // asked for, means need know gmt offset translate data // properly. // since data sent in-order , first day // current day, we're going take advantage of nice // normalized utc date of our weather. time daytime = new time(); daytime.settonow(); // start @ day returned local time. otherwise mess. int julianstartday = time.getjulianday(system.currenttimemillis(), daytime.gmtoff); // work exclusively in utc daytime = new time(); for(int = 0; < weatherarray.length(); i++) { // these values collected. long datetime; double pressure; int humidity; double windspeed; double winddirection; double high; double low; string description; int weatherid; // json object representing day jsonobject dayforecast = weatherarray.getjsonobject(i); // cheating convert utc time, want anyhow datetime = daytime.setjulianday(julianstartday+i); pressure = dayforecast.getdouble(owm_pressure); humidity = dayforecast.getint(owm_humidity); windspeed = dayforecast.getdouble(owm_windspeed); winddirection = dayforecast.getdouble(owm_wind_direction); // description in child array called "weather", 1 element long. // element contains weather code. jsonobject weatherobject = dayforecast.getjsonarray(owm_weather).getjsonobject(0); description = weatherobject.getstring(owm_description); weatherid = weatherobject.getint(owm_weather_id); // temperatures in child object called "temp". try not name variables // "temp" when working temperature. confuses everybody. jsonobject temperatureobject = dayforecast.getjsonobject(owm_temperature); high = temperatureobject.getdouble(owm_max); low = temperatureobject.getdouble(owm_min); contentvalues weathervalues = new contentvalues(); weathervalues.put(weatherentry.column_loc_key, locationid); weathervalues.put(weatherentry.column_date, datetime); weathervalues.put(weatherentry.column_humidity, humidity); weathervalues.put(weatherentry.column_pressure, pressure); weathervalues.put(weatherentry.column_wind_speed, windspeed); weathervalues.put(weatherentry.column_degrees, winddirection); weathervalues.put(weatherentry.column_max_temp, high); weathervalues.put(weatherentry.column_min_temp, low); weathervalues.put(weatherentry.column_short_desc, description); weathervalues.put(weatherentry.column_weather_id, weatherid); cvvector.add(weathervalues); } // add database if ( cvvector.size() > 0 ) { contentvalues[] cvarray = new contentvalues[cvvector.size()]; cvvector.toarray(cvarray); mcontext.getcontentresolver().bulkinsert(weatherentry.content_uri, cvarray); } // sort order: ascending, date. string sortorder = weatherentry.column_date + " asc"; uri weatherforlocationuri = weatherentry.buildweatherlocationwithstartdate( locationsetting, system.currenttimemillis()); // students: uncomment next lines display what stored in bulkinsert cursor cur = mcontext.getcontentresolver().query(weatherforlocationuri, null, null, null, sortorder); cvvector = new vector<contentvalues>(cur.getcount()); if ( cur.movetofirst() ) { { contentvalues cv = new contentvalues(); databaseutils.cursorrowtocontentvalues(cur, cv); cvvector.add(cv); } while (cur.movetonext()); } log.d(log_tag, "fetchweathertask complete. " + cvvector.size() + " inserted"); string[] resultstrs = convertcontentvaluestouxformat(cvvector); return resultstrs; } catch (jsonexception e) { log.e(log_tag, e.getmessage(), e); e.printstacktrace(); } return null; } @override protected string[] doinbackground(string... params) { // if there's no zip code, there's nothing up. verify size of params. if (params.length == 0) { return null; } string locationquery = params[0]; // these 2 need declared outside try/catch // can closed in block. httpurlconnection urlconnection = null; bufferedreader reader = null; // contain raw json response string. string forecastjsonstr = null; string format = "json"; string units = "metric"; int numdays = 14; try { // construct url openweathermap query // possible parameters avaiable @ owm's forecast api page, @ // http://openweathermap.org/api#forecast final string forecast_base_url = "http://api.openweathermap.org/data/2.5/forecast/daily?"; final string query_param = "q"; final string format_param = "mode"; final string units_param = "units"; final string days_param = "cnt"; uri builturi = uri.parse(forecast_base_url).buildupon() .appendqueryparameter(query_param, params[0]) .appendqueryparameter(format_param, format) .appendqueryparameter(units_param, units) .appendqueryparameter(days_param, integer.tostring(numdays)) .build(); url url = new url(builturi.tostring()); // create request openweathermap, , open connection urlconnection = (httpurlconnection) url.openconnection(); urlconnection.setrequestmethod("get"); urlconnection.connect(); // read input stream string inputstream inputstream = urlconnection.getinputstream(); stringbuffer buffer = new stringbuffer(); if (inputstream == null) { // nothing do. return null; } reader = new bufferedreader(new inputstreamreader(inputstream)); string line; while ((line = reader.readline()) != null) { // since it's json, adding newline isn't necessary (it won't affect parsing) // make debugging *lot* easier if print out completed // buffer debugging. buffer.append(line + "\n"); } if (buffer.length() == 0) { // stream empty. no point in parsing. return null; } forecastjsonstr = buffer.tostring(); } catch (ioexception e) { log.e(log_tag, "error ", e); // if code didn't weather data, there's no point in attemping // parse it. return null; } { if (urlconnection != null) { urlconnection.disconnect(); } if (reader != null) { try { reader.close(); } catch (final ioexception e) { log.e(log_tag, "error closing stream", e); } } } try { return getweatherdatafromjson(forecastjsonstr, locationquery); } catch (jsonexception e) { log.e(log_tag, e.getmessage(), e); e.printstacktrace(); } // happen if there error getting or parsing forecast. return null; } @override protected void onpostexecute(string[] result) { if (result != null && mforecastadapter != null) { mforecastadapter.clear(); for(string dayforecaststr : result) { mforecastadapter.add(dayforecaststr); } // new data server. hooray! } } }
as stack trace says, you're trying call movetofirst() on null reference. locationcursor object you're calling method on, must null.
the docs query() can return null, you'll should null check object, , should check invocation of query() try understand why it's returning null.
Comments
Post a Comment