Newbie question time again;
So within FormActivity I post then receive a response from a SQL table on a remote server, the data is put into a local SQLite table row. Then, I have a Fragment with several EditText fields which I try to populate with the local table data. Now, I have a method within the Activity, DrawText(), to do this but when ran I am getting a crash. The logcat message I put in shows that when the DrawText() is called the value it is pulling from the SQLite table is null.
I've moved the method around trying to make sure it accesses the table after it has already been populated from the server response, but cannot get it working. Any help would be greatly appreciated. Code below (now Edited with help)
FormActivity.java
public class FormActivity extends FragmentActivity {
//create variables & Logcat tag
private static final String TAG = FormActivity.class.getSimpleName();
private EditText inputTitle;
private EditText inputName;
private EditText inputSurname;
private SessionManager sm;
private SQLiteHandler db;
private ProgressDialog pDialog;
private String e_check;
private String surname;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_form);
//set inputs for fields
inputTitle = (EditText) findViewById(R.id.titleText);
inputName = (EditText) findViewById(R.id.foreText);
inputSurname = (EditText) findViewById(R.id.surnameText);
//initialise pager for swipe screens
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
// Progress dialog
pDialog = new ProgressDialog(this);
pDialog.setCancelable(false);
//email value passed in
Bundle extras = getIntent().getExtras();
if (extras != null) {
e_check = extras.getString("e_check");
}
// SQLite database handler - delete old and recreate db from remote server data
db = new SQLiteHandler(getApplicationContext());
String email = e_check;
checkUserDetails(email);
//<!-- TODO: load db fields to textfields -->
//<!-- TODO: greeting toast -->
}
/**
* function to verify & retrieve details in mysql db
* */
private void checkUserDetails(final String email) {
// Tag used to cancel the request
String tag_string_req = "req_retrieve";
pDialog.setMessage("Retrieving details ...");
showDialog();
StringRequest strReq = new StringRequest(Request.Method.POST,
AppConfig.URL_RETRIEVE, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Retrieval Response: " + response.toString());
hideDialog();
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
// user exists
// fill in textfields
String uid = jObj.getString("uid");
JSONObject user = jObj.getJSONObject("user");
String name = user.getString("name");
surname = user.getString("surname");
String email = user.getString("email");
String created_at = user
.getString("created_at");
String tel_no = user.getString("tel_no");
String home_add = user.getString("home_add");
String postcode = user.getString("postcode");
String postal = user.getString("postal");
// Inserting row in table
db.addUser(name, surname, email, uid, created_at, tel_no, home_add, postcode, postal);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 300ms
DrawText();
}
}, 300);
/* Displaying the user details on the screen
FirstFragment fragA = (FirstFragment) getSupportFragmentManager().findFragmentByTag("fragA");
fragA.DrawText();*/
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Retrieval Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
hideDialog();
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting parameters to url
Map<String, String> params = new HashMap<String, String>();
params.put("tag", "retrieve");
params.put("email", email);
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
public void DrawText() {
// Fetching user details from sqlite
HashMap<String, String> user = db.getUserDetails();
if (user.size() != 0) {
//String surname = user.get("surname");
Log.e(TAG, "string surname: " + surname);
// Displaying the user details on the screen
inputSurname.setText(surname);
}else{
Log.e(TAG, "something you want to say");
}
}
private void showDialog() {
if (!pDialog.isShowing())
pDialog.show();
}
private void hideDialog() {
if (pDialog.isShowing())
pDialog.dismiss();
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return FirstFragment.newInstance("FirstFragment, Instance 1");
case 1: return SecondFragment.newInstance("SecondFragment, Instance 1");
case 2: return ThirdFragment.newInstance("ThirdFragment, Instance 1");
case 3: return FourthFragment.newInstance("FourthFragment, Instance 1");
//case 4: return FifthFragment.newInstance("ThirdFragment, Instance 3");
default: return FirstFragment.newInstance("FirstFragment, Default");
}
}
#Override
// Number of screens we want to swipe between
public int getCount() {
return 4;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_form, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Logcat (also updated)
05-16 09:31:35.560 21981-21981/com.disclosure_scots.disclosure_scots D/FormActivity﹕ Retrieval Response: {"tag":"retrieve","error":false,"uid":"55558b80341dc0.72266271","user":{"name":"John","surname":"Carter","email":"cart#email.com","created_at":"2015-05-15 08:00:32","tel_no":"1231234123","home_add":"22 Lone Road","postcode":"G44 4TT","postal":"false"}}
05-16 09:31:35.643 21981-21981/com.disclosure_scots.disclosure_scots D/SQLiteHandler﹕ Database tables created
05-16 09:31:35.663 21981-21981/com.disclosure_scots.disclosure_scots D/SQLiteHandler﹕ New user inserted into sqlite: 1
05-16 09:31:35.980 21981-21981/com.disclosure_scots.disclosure_scots D/SQLiteHandler﹕ Fetching user from Sqlite: {tel_no=1231234123, postal=false, email=cart#email.com, surname=Carter, name=John, created_at=2015-05-15 08:00:32, uid=55558b80341dc0.72266271, home_add=22 Lone Road, postcode=G44 4TT}
05-16 09:31:35.980 21981-21981/com.disclosure_scots.disclosure_scots E/FormActivity﹕ string surname: Carter
05-16 09:31:35.980 21981-21981/com.disclosure_scots.disclosure_scots D/AndroidRuntime﹕ Shutting down VM
05-16 09:31:35.981 21981-21981/com.disclosure_scots.disclosure_scots E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.disclosure_scots.disclosure_scots, PID: 21981
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference
at com.disclosure_scots.disclosure_scots.FormActivity.DrawText(FormActivity.java:180)
at com.disclosure_scots.disclosure_scots.FormActivity$1$1.run(FormActivity.java:125)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
The problem is that you are trying to collect data before adding data. As you can see you are calling DrawText(); just after the response received (before adding data to database). So obviously the data'll be null. You should call the DrawText(); after adding the data to the db.
db.addUser(name, surname, email, uid, created_at, tel_no, home_add, postcode, postal);
DrawText();
If the above code doesn't work, try calling DrawText() after a 500ms like this
db.addUser(name, surname, email, uid, created_at, tel_no, home_add, postcode, postal);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 500ms
DrawText();
}
}, 500);
If nothing worked from above. declare String variables such as name,surname etc.. ( which you parsed from the JSON ) outside the methods which will extend the accessibility of the variable from any method and update the DrawText(); like this
private String surname;
.....{
....
surname = jsonObject.getString("surname");
...
}
public void DrawText() {
Log.e(TAG, "string surname: " + surname);
// Displaying the user details on the screen
inputSurname.setText(surname);
}
public void DrawText() {
// Fetching user details from sqlite
HashMap<String, String> user = db.getUserDetails();
if (user.size() != 0) {
String surname = user.get("surname");
Log.e(TAG, "string surname: " + surname);
// Displaying the user details on the screen
inputSurname.setText(surname);
}else{
Log.e(TAG, "something you want to say");}
}
Related
I'm having an issue with RecyclerView not refreshing after I do a manual sync of a web service.
The manual sync is triggered by either swiping-down on the list or by tapping on an ActionBar item.
The manual sync uses a Volley Request to retrieve data in a JSON format, the data is parsed and saved to an SQLite database table. The sync datetime is also saved to an SQLite database table and later displayed in the Fragment's ActionBar Subtitle. The Volley Request is kicked of via a WorkManager OneTimeWorkRequest.
The problem being the RecyclerView list is not refreshed. However if I then trigger another manual sync, the sync datatime in the ActionBar Subtitle and RecyclerView contents are updated but with data from the previous manual sync. This becomes clear if I navigate away from the app to the device's Home screen and then navigate back to my app, which now shows the refreshed data from the most recent manual sync.
I have looked at numerous posts around this issue (see below) and whilst I think I have improved my code none of the recommended solutions have resolved the issue.
Recyclerview not call onCreateViewHolder
RecyclerView not calling onCreateViewHolder or onBindView
Recyclerview not call onCreateViewHolder
RecyclerView is not refreshing
get JSON data from web and display using RecyclerView
Recycler View appear blank and doesn't show SQLite data
RecyclerView onClick not working properly?
Why doesn't RecyclerView have onItemClickListener()?
ListView not updating after web service Sync
Other resources looked at:
https://www.mytrendin.com/display-data-recyclerview-using-sqlitecursor-in-android/
https://medium.com/#studymongolian/updating-data-in-an-android-recyclerview-842e56adbfd8
https://www.youtube.com/watch?v=ObU-wCqoo2I
https://www.youtube.com/watch?v=_0C18cbv6UE
So after a number of months trying to fix this issue I am now turning to the StackOverflow community for help.
Fragment
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_warning_list, container, false);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.warning_swipe_refresh_layout);
/* Set the Refresh Listener for the Swipe gesture */
mSwipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
SyncWarningsScheduler.oneTime();
updateUI();
}
}
);
mWarningRecyclerView = (RecyclerView) view.findViewById(R.id.warning_recycler_view);
/* Set the Toolbar to replace the default ActionBar, which has been hidden */
if (mActivity != null) {
Toolbar toolbar = (Toolbar) mActivity.findViewById(R.id.toolbar_abstract_single_fragment);
mActivity.setSupportActionBar(toolbar);
/* Set the toolbar title */
ActionBar actionbar = mActivity.getSupportActionBar();
if (actionbar != null) {
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setTitle(getString(R.string.warning_list_fragment_toolbar_title));
}
}
updateUI();
return view;
}
#Override
public void onResume() {
super.onResume();
updateUI();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_warning_list, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.sync:
mSwipeRefreshLayout.setRefreshing(true);
SyncWarningsScheduler.oneTime();
updateUI();
return true;
case R.id.information:
/* Handle the Information Menu Item */
FragmentManager fm = getFragmentManager();
if (fm != null) {
WarningListFragmentTFBInformationDialogFragment dialog = new WarningListFragmentTFBInformationDialogFragment();
dialog.show(fm, TFB_INFO_DIALOG_TAG);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void updateUI() {
WarningList warningList = WarningList.get(mActivity);
List<Warning> warnings = warningList.getWarnings();
if (mWarningAdaptor == null) {
mWarningAdaptor = new WarningAdaptor(warnings);
mWarningRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
mWarningRecyclerView.setAdapter(mWarningAdaptor);
} else {
mWarningAdaptor.setWarnings(warnings);
mWarningAdaptor.notifyDataSetChanged();
}
/* Update the ToolBar sub title to show the latest sync datetime */
updateToolBarSubTitle();
/* If visible, turn off the Swipe Refresh Progress Circle */
if (mSwipeRefreshLayout != null && mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false);
}
}
private void updateToolBarSubTitle() {
SyncInformationList syncInformationList = SyncInformationList.get(mContext);
Date syncDate = syncInformationList.getSyncDatetime(ORMSync.getWarningSyncTypeKey());
ActionBar actionBar = mActivity.getSupportActionBar();
if (actionBar != null) {
actionBar.setSubtitle(DatabaseUtilities.formatDateSpecial(syncDate, true));
}
}
private class WarningHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private Warning mWarning;
private TextView mIssueForTextView;
private TextView mDeclarationTextView;
private View mStatusWarningViewLeft;
private View mStatusWarningViewRight;
public WarningHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.list_item_warning, parent, false));
/* Handlers a user press on a Warning */
itemView.setOnClickListener(this);
mIssueForTextView = (TextView) itemView.findViewById(R.id.issueFor_textView);
mDeclarationTextView = (TextView) itemView.findViewById(R.id.declaration_textView);
mStatusWarningViewLeft = (View) itemView.findViewById(R.id.status_warning_left);
mStatusWarningViewRight = (View) itemView.findViewById(R.id.status_warning_right);
}
public void bind(Warning warning) {
mWarning = warning;
String issueForDate;
issueForDate = DatabaseUtilities.formatDateSpecial(mWarning.getIssuedFor(), "d MMM yyyy");
mIssueForTextView.setText(issueForDate);
mDeclarationTextView.setText(mWarning.getTfbDeclaration());
/* Set Declaration text colour */
if (mWarning.isTfbStatus()) {
/* If the day is a TFB set text color to Red */
mIssueForTextView.setTextColor(getResources().getColor(R.color.red));
mDeclarationTextView.setTextColor(getResources().getColor(R.color.red));
}
/* Set left and right status warning colour based on TFB status */
mStatusWarningViewLeft.setBackgroundResource(mWarning.setStatusWarningColor());
mStatusWarningViewRight.setBackgroundResource(mWarning.setStatusWarningColor());
}
#Override
public void onClick(View v) {
/* Process onClick */
Intent intent = WarningPagerActivity.newIntent(mActivity, mWarning.getUID());
startActivity(intent);
}
}
private class WarningAdaptor extends RecyclerView.Adapter<WarningHolder> {
private List<Warning> mWarnings;
public WarningAdaptor(List<Warning> warnings) {
mWarnings = warnings;
}
#NonNull
#Override
public WarningHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(mActivity);
return new WarningHolder(layoutInflater, parent);
}
#Override
public void onBindViewHolder(#NonNull WarningHolder holder, int position) {
/* Bind data */
Warning warning = mWarnings.get(position);
holder.bind(warning);
}
#Override
public int getItemCount() {
return mWarnings.size();
}
public void setWarnings(List<Warning> warnings) {
mWarnings.clear();
mWarnings = warnings;
}
public List<Warning> getWarnings() {
return mWarnings;
}
}
}
WorkManager oneTimeWorkRequest Scheduler
public class SyncWarningsScheduler {
private static final String TAG = "SyncWarningsScheduler";
private static final String ONE_TIME_WORK_REQUEST = "OneTime";
private static final String ONE_TIME_WORK_REQUEST_TAG = TAG + ONE_TIME_WORK_REQUEST;
private static final String ONE_TIME_WORK_REQUEST_TAG_UNIQUE = ONE_TIME_WORK_REQUEST_TAG + "Unique";
/* Getters and Setters */
public static String getOneTimeWorkRequestTagUnique() {
return ONE_TIME_WORK_REQUEST_TAG_UNIQUE;
}
public static void oneTime() {
WorkManager workManager = WorkManager.getInstance();
/* Create a Constraints object that defines when and how the task should run */
Constraints constraints = new Constraints.Builder()
.setRequiresCharging(false)
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
/* Build the Input Data to pass to the Worker */
Data inputData = new Data.Builder()
.putString(SyncWarningsWorker.getWorkRequestTypeKey(), ONE_TIME_WORK_REQUEST)
.build();
/* Build the One Time Work Request */
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(SyncWarningsWorker.class)
.setConstraints(constraints)
/* Sets the input data for the ListenableWorker */
.setInputData(inputData)
.addTag(ONE_TIME_WORK_REQUEST_TAG)
.build();
workManager.enqueueUniqueWork(ONE_TIME_WORK_REQUEST_TAG_UNIQUE, ExistingWorkPolicy.REPLACE, oneTimeWorkRequest);
}
}
WorkManager Worker
public class SyncWarningsWorker extends Worker {
private static final String TAG = "SyncWarningsWorker";
private Context mContext;
private SQLiteDatabase mDatabase;
private WarningList mWarningList;
private static final String WORK_REQUEST_TYPE_KEY = "warningworkrequesttype";
private static final String SYNC_DATE_TIME_KEY = "warningsyncdatetime";
public SyncWarningsWorker(#NonNull Context context, #NonNull WorkerParameters workerParams) {
super(context, workerParams);
/* Set the Context which must be the Application Context */
mContext = context;
mDatabase = IncidentsDatabaseHelper.get(context).getWritableDatabase();
/* Get a refer to the WarningList Singleton */
mWarningList = WarningList.get(context);
}
/* Getters and Setters */
public static String getWorkRequestTypeKey() {
return WORK_REQUEST_TYPE_KEY;
}
public static String getSyncDateTimeKey() {
return SYNC_DATE_TIME_KEY;
}
#NonNull
#Override
public Result doWork() {
/* Read passed-in argument(s) */
String workRequestType = getInputData().getString(WORK_REQUEST_TYPE_KEY);
LogUtilities.info(TAG, "doWork() - Processing EMV Warnings Work Request Type: " + workRequestType);
try {
downloadWarnings();
Date now = new Date();
long nowMilliSeconds = now.getTime();
now.setTime(nowMilliSeconds);
/* Update the WarningSyncType in SyncInformationList with the Warnings Sync Datetime */
SyncInformationList syncInformationList = SyncInformationList.get(mContext);
syncInformationList.updateSyncDatetime(ORMSync.getWarningSyncTypeKey(), now);
Data syncDateTime = new Data.Builder()
.putLong(SYNC_DATE_TIME_KEY, nowMilliSeconds)
.build();
return Result.success(syncDateTime);
} catch (Exception e){
LogUtilities.error(TAG, "doWork() - Can't download EMV Warnings data.\n\n" + e.toString());
return Result.failure();
}
}
private void downloadWarnings() {
VolleyRequestQueue volleyRequestQueue;
StringRequest request = new StringRequest(Request.Method.GET, JSONWarningsSchema.getTfbFdrJsonEndPoint(), onPostsLoaded, onPostsError);
volleyRequestQueue = VolleyRequestQueue.get(mContext);
volleyRequestQueue.addToVolleyRequestQueue(request);
}
private final Response.Listener<String> onPostsLoaded = new Response.Listener<String>() {
ContentValues contentvalues;
String noData = "NO DATA";
#Override
public void onResponse(String response) {
/* Delete all the Warning records from the SQLite table */
mWarningList.deleteAllWarnings();
try {
JSONObject jsonBody = new JSONObject(response);
/* Within jsonBody is one nested JSON Array */
JSONArray jsonArrayResults = jsonBody.getJSONArray(JSONWarningsSchema.getJsonRootArrayName());
for (int i = 0; i < jsonArrayResults.length(); i++) {
/*
* Within jsonArrayResults are 10 sometimes 9 JSON Objects, the first 5 Objects are for TFB declarations and
* the last 5 (4) Objects are for FDR declarations.
*/
JSONObject warningMetadata = jsonArrayResults.getJSONObject(i);
if (i < 5) {
/*
* The first 5 Objects are for Today and the next 4 days worth of TFB declarations. The TFB declaration in these Objects are
* used to INSERT new records into the warnings table using the issueFor date as the Alternate Primary Key.
* The FDR declarations for each day are defaulted to "NO DATA" to cater for the sometimes missing FDR data on the 5th day, this is
* to avoid null pointer errors when displaying the data in fragment_warning.
*/
Warning warning = new Warning();
String issueForDate = warningMetadata.getString(JSONWarningsSchema.Keys.getIssueFor());
warning.setIssuedFor(JSONUtilities.stringToDate(issueForDate, JSONWarningsSchema.getJsonIssueForDateFormat()));
String status = warningMetadata.getString(JSONWarningsSchema.Keys.getStatus());
warning.setTfbStatus(JSONUtilities.stringToBoolean(status));
warning.setTfbDeclaration(warningMetadata.getString(JSONWarningsSchema.Keys.getDeclaration()));
/*
* Within the warningMetadata JSONObject is a JSONArray called declareList. Need to get the Array and
* iterate through the Array to extract the TFB warning for each District for this day.
* We know the exact number of JSONObjects in the declareList Array (ie an Object for each District).
*/
JSONArray jsonArrayTFBDeclareList = warningMetadata.getJSONArray(JSONWarningsSchema.getJsonDeclareListArrayName());
/* Iterate through the TFB declareList Array */
for (int j = 0; j < jsonArrayTFBDeclareList.length(); j++) {
/* Get the JSON Object within the jsonArrayDeclareList Array */
JSONObject declareListMetadata = jsonArrayTFBDeclareList.getJSONObject(j);
/* Get the name and status pairs from the declareListMetadata Object */
String name = declareListMetadata.getString(JSONWarningsSchema.Keys.getDeclareListName());
String declareListStatus = declareListMetadata.getString(JSONWarningsSchema.Keys.getDeclareListStatus());
switch (name) {
case "Mallee":
warning.setTfbMallee(declareListStatus);
warning.setFdrMallee(noData);
break;
case "Wimmera":
warning.setTfbWimmera(declareListStatus);
warning.setFdrWimmera(noData);
break;
case "South West":
warning.setTfbSouthWest(declareListStatus);
warning.setFdrSouthWest(noData);
break;
case "Northern Country":
warning.setTfbNorthernCountry(declareListStatus);
warning.setFdrNorthernCountry(noData);
break;
case "North Central":
warning.setTfbNorthCentral(declareListStatus);
warning.setFdrNorthCentral(noData);
break;
case "Central":
warning.setTfbCentral(declareListStatus);
warning.setFdrCentral(noData);
break;
case "North East":
warning.setTfbNorthEast(declareListStatus);
warning.setFdrNorthEast(noData);
break;
case "West and South Gippsland":
warning.setTfbWestAndSouthGippsland(declareListStatus);
warning.setFdrWestAndSouthGippsland(noData);
break;
case "East Gippsland":
warning.setTfbEastGippsland(declareListStatus);
warning.setFdrEastGippsland(noData);
break;
default:
break;
}
}
contentvalues = ContentValueUtilities.getWarningListContentValues(warning, true);
mDatabase.beginTransaction();
try {
mDatabase.insert(ORMWarnings.getTableName(), null, contentvalues);
mDatabase.setTransactionSuccessful();
} catch (SQLiteException e) {
LogUtilities.error(TAG, "onPostsLoaded > onResponse - ERROR Inserting record into the '" + ORMWarnings.getTableName() + "' Table.\n\n" + e.toString());
} finally {
mDatabase.endTransaction();
}
} else {
/*
* The last 5 or sometimes 4 Objects are for Today and the next 4 days worth of FDR declarations. The FDR declarations
* in these Objects are used to UPDATE FDR attributes in the warnings table using the issueFor date to find the existing warnings
* record.
*/
String issueForFDR = warningMetadata.getString(JSONWarningsSchema.Keys.getIssueFor());
/* Ensure the retrieved issueFor date string is converted consistently */
Date issueForFDRDate = JSONUtilities.stringToDate(issueForFDR, JSONWarningsSchema.getJsonIssueForDateFormat());
/* Find the record in the warnings table by using the issueForFDRDate date. */
Warning warningExists = mWarningList.getWarning(issueForFDRDate);
/* Make sure a warning record has been returned */
if (warningExists != null) {
String issueAtDate = warningMetadata.getString(JSONWarningsSchema.Keys.getIssueAt());
warningExists.setFdrIssuedAt(JSONUtilities.stringToDate(issueAtDate, JSONWarningsSchema.getJsonIssueAtDateFormat()));
/*
* Within the warningMetadata JSONObject is a JSONArray called declareList. Need to get the Array and
* iterate through the Array to extract the FDR warning for each District for this day.
* We know the exact number of JSONObjects in the declareList Array (ie an Object for each District).
*/
JSONArray jsonArrayFDRDeclareList = warningMetadata.getJSONArray(JSONWarningsSchema.getJsonDeclareListArrayName());
/* Iterate through the FDR declareList Array */
for (int z = 0; z < jsonArrayFDRDeclareList.length(); z++) {
/* Get the JSON Object within the jsonArrayFDRDeclareList Array */
JSONObject declareListMetadataFDR = jsonArrayFDRDeclareList.getJSONObject(z);
/* Get the name and status pairs from the declareListMetadataFDR Object */
String nameFDR = declareListMetadataFDR.getString(JSONWarningsSchema.Keys.getDeclareListName());
String declareListStatusFDR = declareListMetadataFDR.getString(JSONWarningsSchema.Keys.getDeclareListStatus());
switch (nameFDR) {
case "Mallee":
warningExists.setFdrMallee(declareListStatusFDR);
break;
case "Wimmera":
warningExists.setFdrWimmera(declareListStatusFDR);
break;
case "South West":
warningExists.setFdrSouthWest(declareListStatusFDR);
break;
case "Northern Country":
warningExists.setFdrNorthernCountry(declareListStatusFDR);
break;
case "North Central":
warningExists.setFdrNorthCentral(declareListStatusFDR);
break;
case "Central":
warningExists.setFdrCentral(declareListStatusFDR);
break;
case "North East":
warningExists.setFdrNorthEast(declareListStatusFDR);
break;
case "West and South Gippsland":
warningExists.setFdrWestAndSouthGippsland(declareListStatusFDR);
break;
case "East Gippsland":
warningExists.setFdrEastGippsland(declareListStatusFDR);
break;
default:
break;
}
}
contentvalues = ContentValueUtilities.getWarningListContentValues(warningExists, false);
mDatabase.beginTransaction();
try {
mDatabase.update(ORMWarnings.getTableName(), contentvalues, ORMWarnings.getUUIDColumn() + " = ?", new String[] {warningExists.getUID().toString()});
mDatabase.setTransactionSuccessful();
} catch (SQLiteException e) {
LogUtilities.error(TAG, "onPostsLoaded > onResponse - ERROR Updating record in the '" + ORMWarnings.getTableName() + "' Table.\n\n" + e.toString());
} finally {
mDatabase.endTransaction();
}
} else {
/* Something went wrong can't find warning record using the issueForFDRDate date */
LogUtilities.wtf(TAG, "onPostsLoaded > onResponse - " + issueForFDRDate.toString() + " warning record not found.\n\n");
}
}
}
} catch (JSONException e) {
LogUtilities.error(TAG, "onPostsLoaded > onResponse - Failed to Parse JSON body.\n\n" + e.toString());
}
}
};
private final Response.ErrorListener onPostsError = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
LogUtilities.error(TAG, "onPostsError > onErrorResponse - Failed to download JSON body.\n\n" + error.toString());
}
};
}
Use this in your Adapter
public void setWarnings(List<Warning> warnings) {
mWarnings.clear();
mWarnings = warnings;
notifyDataSetChanged();
}
I think you to updateUI(); method call after successfully api call because when api call it's working in background.
or
you can set
sleep(5000)
updateUI();
I'm new to Android and Java and I'm busy editing an existing app. I am trying to hide a button if no text is getting pulled in from a webservice. I have made it work with another button when the text is being populated
if (textEvent.length() > 1) {
buttonEventSetup.setVisibility(View.INVISIBLE);
}
but when I used:
if (textEvent.length() < 1) {
buttonAccessControl.setVisibility(View.INVISIBLE);
}
nothing seems to happen.
I don't know if the code snippet is in the wrong place or something else is overwriting the code. Here is my activity code:
package com.example.dsouchon.myapplication;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonEventSetup = (Button)findViewById(R.id.buttonEventSetup);
if(Local.isSet(getApplicationContext(), "LoggedIn"))
{
String loggedInUser = Local.Get(getApplicationContext(), "LoggedIn");
if(loggedInUser.length()>0)
{
buttonEventSetup.setVisibility(View.VISIBLE);
}
else
{
buttonEventSetup.setVisibility(View.GONE);
}
}
else
{
buttonEventSetup.setVisibility(View.GONE);
}
if(Local.isSet(getApplicationContext(), "EventName"))
{
String event = Local.Get(getApplicationContext(), "EventName");
TextView textEvent = (TextView) findViewById(R.id.textEventName);
textEvent.setText( event);
Button buttonAccessControl = (Button)findViewById(R.id.buttonAccessControl);
buttonAccessControl.setEnabled(true);
//HIDES SET EVENT BUTTON WHEN EVENT IS SET
if (textEvent.length() > 1) {
buttonEventSetup.setVisibility(View.INVISIBLE);
}
if (textEvent.length() < 1) {
buttonAccessControl.setVisibility(View.INVISIBLE);
}
}
else
{
Button buttonAccessControl = (Button)findViewById(R.id.buttonAccessControl);
buttonAccessControl.setEnabled(false);
}
if(Local.isSet(getApplicationContext(), "EventImage"))
{
TextView textEvent = (TextView) findViewById(R.id.textEventName);
String result = Local.Get(getApplicationContext(), "EventImage");
ImageView imageViewEventImage = (ImageView)findViewById(R.id.imageViewEventImage);
byte[] decodedString = Base64.decode(result, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
imageViewEventImage.setImageBitmap(decodedByte);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main2, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void setupEvent(View view) {
Intent intent = new Intent(MainActivity.this, SetupEvent.class );
finish();
startActivity(intent);
}
public void accessControl(View view) {
Button buttonEventSetup = (Button)findViewById(R.id.buttonEventSetup);
buttonEventSetup.setVisibility(View.GONE);
Intent intent = new Intent(MainActivity.this, MainActivity21.class );
finish();
startActivity(intent);
}
public void Logoff(View view) {
Local.Set(getApplicationContext(), "LoggedIn", "");
}
public void Login(View view) {
final AlertDialog ad=new AlertDialog.Builder(this).create();
MySOAPCallActivity cs = new MySOAPCallActivity();
try {
EditText userName = (EditText) findViewById(R.id.editUserName);
EditText password = (EditText) findViewById(R.id.editPassword);
String user = userName.getText().toString();
String pwd = password.getText().toString();
LoginParams params = new LoginParams(cs, user, pwd);
Local.Set(getApplicationContext(), "UserName", user);
Local.Set(getApplicationContext(), "Password", pwd);
new CallSoapLogin().execute(params);
// new CallSoapGetCurrentEvents().execute(params);
} catch (Exception ex) {
ad.setTitle("Error!");
ad.setMessage(ex.toString());
}
ad.show();
}
public class CallSoapLogin extends AsyncTask<LoginParams, Void, String> {
private Exception exception;
#Override
protected String doInBackground(LoginParams... params) {
return params[0].foo.Login(params[0].username, params[0].password);
}
protected void onPostExecute(String result) {
// TODO: check this.exception
// TODO: do something with the feed
try {
TextView loginResult =(TextView)findViewById(R.id.labelLoginResult);
loginResult.setVisibility(View.VISIBLE);
loginResult.setText(result);
// Button buttonUnsetEvent = (Button)findViewById(R.id.buttonUnsetEvent);
// buttonUnsetEvent.setEnabled(true);
//Spinner spinner2 = (Spinner)findViewById(R.id.spinner2);
//spinner2.setEnabled(true);
boolean LoginSuccessful = false;
if(result.toLowerCase().contains("success"))
{
LoginSuccessful = true;
}
if (LoginSuccessful)
{
String user = Local.Get(getApplicationContext(), "UserName");
Local.Set(getApplicationContext(), "LoggedIn", user);
LinearLayout layoutLoggedIn = (LinearLayout)findViewById(R.id.layoutLoggedIn);
layoutLoggedIn.setVisibility(View.VISIBLE);
Button buttonEventSetup = (Button)findViewById(R.id.buttonEventSetup);
buttonEventSetup.setVisibility(View.VISIBLE);
LinearLayout layoutLogIn = (LinearLayout)findViewById(R.id.layoutLogIn);
layoutLogIn.setVisibility(View.VISIBLE);
}
} catch (Exception ex) {
String e3 = ex.toString();
}
}
}
private static class LoginParams {
MySOAPCallActivity foo;
String username;
String password;
LoginParams(MySOAPCallActivity foo, String username, String password) {
this.foo = foo;
this.username = username;
this.password = password;
}
}
}
You are getting the length of Textview that will not work.Use the text length.This should work
String event = Local.Get(getApplicationContext(), "EventName");
//HIDES SET EVENT BUTTON WHEN EVENT IS SET
if (event.length() > 1) {
buttonEventSetup.setVisibility(View.VISIBLE);
}
if (event.length() < 1) {
buttonAccessControl.setVisibility(View.INVISIBLE);
}
In your code above textEvent is not a string value. It is an Object of type TextView. length() in this case will not return the length of the text contained within that element. You will need to explicitly get the text string before you can get the length of it. This is acquired using the getText() method on the TextView.
Your code should look like the following:
//HIDES SET EVENT BUTTON WHEN EVENT IS SET
if (textEvent.getText().length() >= 1) {
buttonEventSetup.setVisibility(View.VISIBLE);
}
if (textEvent.getText().length() < 1) {
buttonAccessControl.setVisibility(View.INVISIBLE);
}
You also have INVISIBLE on both cases in your posted code example.
Note that your code also does not handle cases where the text length == 1. You could simplify the whole block with the following.
Note: any value != 0 is classed as true
buttonEventSetup.setVisibility(textEvent.getText().length() ? View.VISIBLE : View.INVISIBLE);
I have created an app that is connected to a remote database. The items in the database are displayed through a spinner in my MainActivity class. I want to display the selected item in a separate class(Map.java) and XML page(map.xml), So I used this code in Map.java to try get the selected item and display it:
Spinner mySpinner = (Spinner)findViewById(R.id.spinFood);
String text = mySpinner.getSelectedItem().toString();
EditText e = (EditText) findViewById (R.id.editText1);
e.setText(text);
To display this value I created an EditText in my map.xml file:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="text"
android:text="#string/text"
android:id="#+id/editText1"
android:layout_alignBottom="#+id/textView"
android:layout_toRightOf="#+id/textView"
android:layout_alignRight="#+id/imageView"
android:layout_alignEnd="#+id/imageView" />
The android:input_type="text" is a string value I created:
<string name="text"> %s </string>
But whenever I open the map page my app crashes. Could someone please tell me where I am going wrong?
Here all of my code for MainActivity and Map.java
MainActivity
package com.example.cillin.infoandroidhivespinnermysql;
import java.util.ArrayList;
..
public class MainActivity extends Activity implements OnItemSelectedListener {
private Button btnAddNewCategory;
private TextView txtCategory;
public Spinner spinnerFood;
// array list for spinner adapter
private ArrayList<Category> categoriesList;
ProgressDialog pDialog;
// API urls
// Url to create new category
private String URL_NEW_CATEGORY = "http://192.168.1.4/food_api/new_category.php";
// Url to get all categories
private String URL_CATEGORIES = "http://192.168.1.4/food_api/get_categories.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnAddNewCategory = (Button) findViewById(R.id.btnAddNewCategory);
spinnerFood = (Spinner) findViewById(R.id.spinFood);
txtCategory = (TextView) findViewById(R.id.txtCategory);
categoriesList = new ArrayList<Category>();
// spinner item select listener
spinnerFood.setOnItemSelectedListener(this);
// Add new category click event
btnAddNewCategory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (txtCategory.getText().toString().trim().length() > 0) {
// new category name
String newCategory = txtCategory.getText().toString();
// Call Async task to create new category
new AddNewCategory().execute(newCategory);
} else {
Toast.makeText(getApplicationContext(),
"Please enter category name", Toast.LENGTH_SHORT)
.show();
}
}
});
new GetCategories().execute();
}
/**
* Adding spinner data
* */
private void populateSpinner() {
List<String> lables = new ArrayList<String>();
txtCategory.setText("");
for (int i = 0; i < categoriesList.size(); i++) {
lables.add(categoriesList.get(i).getName());
}
// Creating adapter for spinner
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, lables);
// Drop down layout style - list view with radio button
spinnerAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
spinnerFood.setAdapter(spinnerAdapter);
//spinnerValue = spinnerFood.getSelectedItem().toString();
}
/**
* Async task to get all food categories
* */
private class GetCategories extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Fetching food categories..");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
ServiceHandler jsonParser = new ServiceHandler();
String json = jsonParser.makeServiceCall(URL_CATEGORIES, ServiceHandler.GET);
Log.e("Response: ", "> " + json);
if (json != null) {
try {
JSONObject jsonObj = new JSONObject(json);
if (jsonObj != null) {
JSONArray categories = jsonObj
.getJSONArray("categories");
for (int i = 0; i < categories.length(); i++) {
JSONObject catObj = (JSONObject) categories.get(i);
Category cat = new Category(catObj.getInt("id"),
catObj.getString("name"));
categoriesList.add(cat);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("JSON Data", "Didn't receive any data from server!");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (pDialog.isShowing())
pDialog.dismiss();
populateSpinner();
}
}
/**
* Async task to create a new food category
* */
private class AddNewCategory extends AsyncTask<String, Void, Void> {
boolean isNewCategoryCreated = false;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Creating new category..");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(String... arg) {
String newCategory = arg[0];
// Preparing post params
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("name", newCategory));
ServiceHandler serviceClient = new ServiceHandler();
String json = serviceClient.makeServiceCall(URL_NEW_CATEGORY,
ServiceHandler.POST, params);
Log.d("Create Response: ", "> " + json);
if (json != null) {
try {
JSONObject jsonObj = new JSONObject(json);
boolean error = jsonObj.getBoolean("error");
// checking for error node in json
if (!error) {
// new category created successfully
isNewCategoryCreated = true;
} else {
Log.e("Create Category Error: ", "> " + jsonObj.getString("message"));
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("JSON Data", "Didn't receive any data from server!");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (pDialog.isShowing())
pDialog.dismiss();
if (isNewCategoryCreated) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// fetching all categories
new GetCategories().execute();
}
});
}
}
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(
getApplicationContext(),
parent.getItemAtPosition(position).toString() + " Selected" ,
Toast.LENGTH_LONG).show();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
Map.java
package com.example.cillin.infoandroidhivespinnermysql;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
public class Map extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//This page layout is located in the menu XML file
//SetContentView links a Java file, to its XML file for the layout
setContentView(R.layout.map);
/*TextView.setText(spinnerValue);
TextView spinv = (TextView)findViewById(R.id.textView2);
spinv.setText(getspin());
spinv = getspin();*/
Spinner mySpinner = (Spinner)findViewById(R.id.spinFood);
String text = mySpinner.getSelectedItem().toString();
EditText e = (EditText) findViewById (R.id.editText1);
e.setText(text);
Button mainm = (Button)findViewById(R.id.mainmenu);
mainm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//This button is linked to the map page
Intent i = new Intent(Map.this, MainMenu.class);
//Activating the intent
startActivity(i);
}
});
}
}
Any help would be much appreciated!!
Here are the errors in my logcat when is crashes:
E/DatabaseUtils﹕ Writing exception to parcel
java.lang.SecurityException: Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
at com.android.server.am.ActivityManagerService.handleIncomingUser(ActivityManagerService.java:14643)
at android.app.ActivityManager.handleIncomingUser(ActivityManager.java:2469)
at com.android.providers.settings.SettingsProvider.call(SettingsProvider.java:688)
at android.content.ContentProvider$Transport.call(ContentProvider.java:325)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:275)
at android.os.Binder.execTransact(Binder.java:404)
E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.cillin.infoandroidhivespinnermysql, PID: 14691
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.cillin.infoandroidhivespinnermysql/com.example.cillin.infoandroidhivespinnermysql.Map}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access$900(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.cillin.infoandroidhivespinnermysql.Map.onCreate(Map.java:34)
at android.app.Activity.performCreate(Activity.java:5426)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access$900(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
I'm guessing that you're getting a NullPointerException in your Map.class
Spinner mySpinner = (Spinner)findViewById(R.id.spinFood);
String text = mySpinner.getSelectedItem().toString();
EditText e = (EditText) findViewById (R.id.editText1);
e.setText(text);
You get a reference to Spinner, then you try to get the selected item and then convert that item to a string. As far as I can tell you haven't actually added any items to the spinner. My guess is that you are trying to access an object in the spinner and since it doesn't exist it returns null. Then you try to call a method on the null object and get an NPE.
This is just a guess. A stacktrace is very helpful in trying to diagnose this.
Where I think you're going wrong is that you populate the spinner in MainActivity and then expect to be able to select an item from that spinner from a different activity. This isn't how it works. Map.class won't be able to reference anything in MainActivity.class. You could try passing the object from MainActivity.class to Map.class or use a different method of passing data, but trying to reference data in MainAcitivity.class from Map.class won't work.
Edit:
If you just want to pass a String from MainActivity.class to Map.class you can add the string as an 'extra' to the intent that you use to start Map.class.
In your MainActivity.class code. When the item from the spinner is selected, create an intent and set the string as an extra using the putExtra() method. You will need to supply a key that basically tags the extra so you can identify it in the receiving activity and the string you want to send.
Intent intent = new Intent(this, Map.class);
intent.putExtra("KEY_SPINNER_STRING", variableRepresentingString);
startActivity(intent);
In the Map.class activity, in the onCreate() method you will need to receive the intent, check for the extra, then unpack the extra. Then you will have the String.
onCreate(Bundle savedInstanceState) {
String spinnerString;
if (getIntent() != null && getIntent().getExtras() != null) {
Bundle bundle = getIntent().getExtras();
if (bundle.getString("KEY_SPINNER_STRING") != null) {
spinnerString = bundle.getString("KEY_SPINNER_STRING");
}
}
}
If everything is done correctly the String will be passed from MainActivity.class and received by Map.class
I've got a simple class. It loads data from my localhost and populates in a listview with android:id/list.
I've set a onclick listener to call my delete async task when I click an item.
My profileList.remove(position), works I can't seem to get the notifyDataSetChanged(); method to work and don't know where to place it?
Lastly, Im not sure but I don't think my class is referencing the position of the item I want to delete and matching it with my database? I keep getting "success=0 no profile" found in my LOG.
Any Ideas? I just want my count/listview to be refreshed and my item deleted.
Class:
public class ViewAllLocations extends ListActivity {
String id;
// Progress Dialog
private ProgressDialog pDialog;
// JSON parser class
JSONParser jsonParser = new JSONParser();
ArrayList<HashMap<String, String>> profileList;
SimpleAdapter adapter;
// url to get all products list
private static String url_all_profile = "http://MYIP:8888/android_connect/get_all_location.php";
// url to delete product
private static final String url_delete_profile = "http://MYIP:8888/android_connect/delete_location.php";
// JSON Node names
private static final String TAG_SUCCESS = "success";
private static final String TAG_LOCATION = "Location";
private static final String TAG_ID = "id";
private static final String TAG_LATITUDE = "latitude";
private static final String TAG_LONGITUDE = "longitude";
// products JSONArray
JSONArray userprofile = null;
TextView locationCount;
int count = 0;
Button deleteLocation;
ListView lo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_all_locations);
// Hashmap for ListView
profileList = new ArrayList<HashMap<String, String>>();
deleteLocation = (Button) findViewById(R.id.deleteLocation);
locationCount = (TextView) findViewById(R.id.locationCount);
lo = (ListView) findViewById(android.R.id.list);
//setup adapter first //now no items, after getting items (LoadAllLocations) will update it
adapter = new SimpleAdapter(
ViewAllLocations.this, profileList,
R.layout.locationitem, new String[]{TAG_ID,
TAG_LATITUDE, TAG_LONGITUDE},
new int[]{R.id.id, R.id.latitude, R.id.longitude});
// updating listview
setListAdapter(adapter);
// Loading products in Background Thread
new LoadAllLocation().execute();
deleteLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
// getting product details from intent
Intent i = getIntent();
// getting product id (pid) from intent
id = i.getStringExtra(TAG_ID);
// Get listview
ListView lo = getListView();
lo.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
new DeleteLocation(position).execute();
Map<String, String> item = profileList.get(position);
String selectedItemId = item.get(TAG_ID);
new DeleteLocation(position).execute(selectedItemId);
}
});
}
/**
* **************************************************************
* Background Async Task to Delete Product
*/
class DeleteLocation extends AsyncTask<String, String, Integer> {
int deleteItemPosition;
public DeleteLocation(int position) {
// TODO Auto-generated constructor stub
this.deleteItemPosition = position;
}
/**
* Before starting background thread Show Progress Dialog
*/
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ViewAllLocations.this);
pDialog.setMessage("Deleting Location...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Deleting product
*/
protected Integer doInBackground(String... args) {
String selectedId = args[0];
// Check for success tag
int success = 0; //0=failed 1=success
try {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id", selectedId));
// getting product details by making HTTP request
JSONObject json = jsonParser.makeHttpRequest(
url_delete_profile, "POST", params);
// check your log for json response
Log.d("Delete Product", json.toString());
// json success tag
success = json.getInt(TAG_SUCCESS);
//if (success == 1) {
// product successfully deleted
// notify previous activity by sending code 100
// Intent i = getIntent();
// send result code 100 to notify about product deletion
//setResult(100, i);
//you cant update UI on worker thread, it must be done on UI thread
// Toast.makeText(getApplicationContext(), "Location Deleted",
// Toast.LENGTH_SHORT).show();
//finish();
// }
} catch (JSONException e) {
e.printStackTrace();
}
return success;
}
/**
* After completing background task Dismiss the progress dialog
* *
*/
protected void onPostExecute(Integer result) {
// dismiss the dialog once product deleted
pDialog.dismiss();
if (result == 1) {
//success
//delete from list and update listview
profileList.remove(deleteItemPosition);
adapter.notifyDataSetChanged();
} else {
//failed
}
}
}
/**
* Background Async Task to Load all product by making HTTP Request
*/
class LoadAllLocation extends AsyncTask<String, String, Integer> {
int success;
/**
* Before starting background thread Show Progress Dialog
*/
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ViewAllLocations.this);
pDialog.setMessage("Loading Locations. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All products from url
*/
protected Integer doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jsonParser.makeHttpRequest(url_all_profile, "GET", params);
// Check your log cat for JSON reponse
Log.d("All Profiles: ", json.toString());
try {
// Checking for SUCCESS TAG
success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// products found
// Getting Array of Products
userprofile = json.getJSONArray(TAG_LOCATION);
// looping through All Products
for (int i = 0; i < userprofile.length(); i++) {
JSONObject c = userprofile.getJSONObject(i);
// Storing each json item in variable
String id = c.getString(TAG_ID);
String latitude = c.getString(TAG_LATITUDE);
String longitude = c.getString(TAG_LONGITUDE);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_ID, id);
map.put(TAG_LATITUDE, latitude);
map.put(TAG_LONGITUDE, longitude);
// adding HashList to ArrayList
profileList.add(map);
}
} else {
// no products found
// Launch Add New product Activity
//Intent i = new Intent(getApplicationContext(),
// UserLocation.class);
// Closing all previous activities
// i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// startActivity(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
return success;
}
/**
* After completing background task Dismiss the progress dialog
* *
*/
protected void onPostExecute(Integer result) {
// dismiss the dialog after getting all products
pDialog.dismiss();
locationCount.setText("" + profileList.size());
if (result == 1) {
//success
//update adapter items
adapter.notifyDataSetChanged();
} else {
//failed
//launch activity here
}
}
}
PHP:
<?php
/*
* Following code will delete a profile from table
* A product is identified by profile id (id)
*/
// array for JSON response
$response = array();
// check for required fields
if (isset($_POST['id'])) {
$id = $_POST['id'];
// include db connect class
require_once __DIR__ . '/db_connect.php';
// connecting to db
$db = new DB_CONNECT();
// mysql update row with matched pid
$result = mysql_query("DELETE FROM Location WHERE id = $id");
// check if row deleted or not
if (mysql_affected_rows() > 0) {
// successfully updated
$response["success"] = 1;
$response["message"] = "Profile successfully deleted";
// echoing JSON response
echo json_encode($response);
} else {
// no product found
$response["success"] = 0;
$response["message"] = "No Profile found";
// echo no users JSON
echo json_encode($response);
}
} else {
// required field is missing
$response["success"] = 0;
$response["message"] = "Required field(s) is missing";
// echoing JSON response
echo json_encode($response);
}
?>
The following app upload video to Dropbox when it is start, I added finish() in the end of onCreate to exit the app when its completed the uploading, but I got "Unfortunately, DBRoulette has stopped.".
In the Eclipse LogCat:
Activity com.dropbox.android.sample.DBRoulette has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#42a7ee38 that was originally added here
android.view.WindowLeaked: Activity com.dropbox.android.sample.DBRoulette has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#42a7ee38 that was originally added here
I have Progress viewer which may cause the problem but I don't know how to solve it!
What I want to do is closing the app automatically when the uploading completed.
DBRoulette.java
#SuppressLint("SimpleDateFormat")
public class DBRoulette extends Activity {
private static final String TAG = "DBRoulette";
final static private String APP_KEY = "<My APP_KEY>";
final static private String APP_SECRET = "<My APP_SECRET>";
// You don't need to change these, leave them alone.
final static private String ACCOUNT_PREFS_NAME = "prefs";
final static private String ACCESS_KEY_NAME = "ACCESS_KEY";
final static private String ACCESS_SECRET_NAME = "ACCESS_SECRET";
private static final boolean USE_OAUTH1 = false;
DropboxAPI<AndroidAuthSession> mApi;
private boolean mLoggedIn;
// Android widgets
private Button mSubmit;
private RelativeLayout mDisplay;
private Button mGallery;
private ImageView mImage;
private final String PHOTO_DIR = "/Motion/";
#SuppressWarnings("unused")
final static private int NEW_PICTURE = 50;
private String mCameraFileName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCameraFileName = savedInstanceState.getString("mCameraFileName");
}
// We create a new AuthSession so that we can use the Dropbox API.
AndroidAuthSession session = buildSession();
mApi = new DropboxAPI<AndroidAuthSession>(session);
// Basic Android widgets
setContentView(R.layout.main);
checkAppKeySetup();
mSubmit = (Button) findViewById(R.id.auth_button);
mSubmit.setOnClickListener(new OnClickListener() {
#SuppressWarnings("deprecation")
public void onClick(View v) {
// This logs you out if you're logged in, or vice versa
if (mLoggedIn) {
logOut();
} else {
// Start the remote authentication
if (USE_OAUTH1) {
mApi.getSession().startAuthentication(DBRoulette.this);
} else {
mApi.getSession().startOAuth2Authentication(
DBRoulette.this);
}
}
}
});
mDisplay = (RelativeLayout) findViewById(R.id.logged_in_display);
// This is where a photo is displayed
mImage = (ImageView) findViewById(R.id.image_view);
File outFile = new File("/mnt/sdcard/ipwebcam_videos/video.mov");
mCameraFileName = outFile.toString();
UploadPicture upload = new UploadPicture(DBRoulette.this, mApi, PHOTO_DIR,outFile);
upload.execute();
// Display the proper UI state if logged in or not
setLoggedIn(mApi.getSession().isLinked());
finish();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("mCameraFileName", mCameraFileName);
super.onSaveInstanceState(outState);
}
#Override
protected void onResume() {
super.onResume();
AndroidAuthSession session = mApi.getSession();
if (session.authenticationSuccessful()) {
try {
session.finishAuthentication();
storeAuth(session);
setLoggedIn(true);
} catch (IllegalStateException e) {
showToast("Couldn't authenticate with Dropbox:"
+ e.getLocalizedMessage());
Log.i(TAG, "Error authenticating", e);
}
}
}
private void logOut() {
// Remove credentials from the session
mApi.getSession().unlink();
clearKeys();
// Change UI state to display logged out version
setLoggedIn(false);
}
#SuppressWarnings("deprecation")
public String getRealPathFromURI(Uri contentUri)
{
String[] proj = { MediaStore.Audio.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
private void setLoggedIn(boolean loggedIn) {
mLoggedIn = loggedIn;
if (loggedIn) {
mSubmit.setText("Logout from Dropbox");
mDisplay.setVisibility(View.VISIBLE);
} else {
mSubmit.setText("Login with Dropbox");
mDisplay.setVisibility(View.GONE);
mImage.setImageDrawable(null);
}
}
private void checkAppKeySetup() {
// Check to make sure that we have a valid app key
if (APP_KEY.startsWith("CHANGE") || APP_SECRET.startsWith("CHANGE")) {
showToast("You must apply for an app key and secret from developers.dropbox.com, and add them to the DBRoulette ap before trying it.");
finish();
return;
}
// Check if the app has set up its manifest properly.
Intent testIntent = new Intent(Intent.ACTION_VIEW);
String scheme = "db-" + APP_KEY;
String uri = scheme + "://" + AuthActivity.AUTH_VERSION + "/test";
testIntent.setData(Uri.parse(uri));
PackageManager pm = getPackageManager();
if (0 == pm.queryIntentActivities(testIntent, 0).size()) {
showToast("URL scheme in your app's "
+ "manifest is not set up correctly. You should have a "
+ "com.dropbox.client2.android.AuthActivity with the "
+ "scheme: " + scheme);
finish();
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(this, msg, Toast.LENGTH_LONG);
error.show();
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a
* local store, rather than storing user name & password, and
* re-authenticating each time (which is not to be done, ever).
*/
private void loadAuth(AndroidAuthSession session) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
String key = prefs.getString(ACCESS_KEY_NAME, null);
String secret = prefs.getString(ACCESS_SECRET_NAME, null);
if (key == null || secret == null || key.length() == 0
|| secret.length() == 0)
return;
if (key.equals("oauth2:")) {
// If the key is set to "oauth2:", then we can assume the token is
// for OAuth 2.
session.setOAuth2AccessToken(secret);
} else {
// Still support using old OAuth 1 tokens.
session.setAccessTokenPair(new AccessTokenPair(key, secret));
}
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a
* local store, rather than storing user name & password, and
* re-authenticating each time (which is not to be done, ever).
*/
private void storeAuth(AndroidAuthSession session) {
// Store the OAuth 2 access token, if there is one.
String oauth2AccessToken = session.getOAuth2AccessToken();
if (oauth2AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME,
0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, "oauth2:");
edit.putString(ACCESS_SECRET_NAME, oauth2AccessToken);
edit.commit();
return;
}
// Store the OAuth 1 access token, if there is one. This is only
// necessary if
// you're still using OAuth 1.
AccessTokenPair oauth1AccessToken = session.getAccessTokenPair();
if (oauth1AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME,
0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, oauth1AccessToken.key);
edit.putString(ACCESS_SECRET_NAME, oauth1AccessToken.secret);
edit.commit();
return;
}
}
private void clearKeys() {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.clear();
edit.commit();
}
private AndroidAuthSession buildSession() {
AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeyPair);
loadAuth(session);
return session;
}
}
UploadPicture.java
public class UploadPicture extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private final ProgressDialog mDialog;
private String mErrorMsg;
private File outFiles;
public UploadPicture(Context context, DropboxAPI<?> api, String dropboxPath,
File file) {
// We set the context this way so we don't accidentally leak activities
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
Date dates = new Date();
DateFormat dfs = new SimpleDateFormat("yyyyMMdd-kkmmss");
String newPicFiles = dfs.format(dates) + ".mov";
String outPaths = new File(Environment
.getExternalStorageDirectory(), newPicFiles).getPath();
outFiles = new File(outPaths);
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading " + outFiles.getName());
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton(ProgressDialog.BUTTON_POSITIVE, "Cancel", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// This will cancel the putFile operation
mRequest.abort();
}
});
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// By creating a request, we get a handle to the putFile operation,
// so we can cancel it later if we want to
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + outFiles.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total) {
publishProgress(bytes);
}
});
if (mRequest != null) {
mRequest.upload();
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("Image successfully uploaded");
} else {
showToast(mErrorMsg);
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
}
Your problem is that you are trying to update an Activity's UI after the activity has finished.
First, you kick of an AsyncTask which posts progress updates to the UI thread. Then, before the task completes, you call finish(). Any updates to the Activity's UI after finish() is called are liable to throw exceptions, cause window leak issues, etc.
If you want to have any UI behavior as you perform your AsyncTask, you do not want to finish() the Activity until it the task is completed.
To achieve this, you could include a callback in the onPostExecute which tells the activity it is OK to finish once the AsyncTask completes.
This is how I would do it:
Change the signature of UploadPicture:
final Activity callingActivity;
public UploadPicture(final Activity callingActivity, DropboxAPI api, String dropboxPath, File file) {
Context mContext = callingActivity.getApplicationContext();
this.callingActivity = callingActivity;
Add the finish call to onPostExecute:
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("Image successfully uploaded");
} else {
showToast(mErrorMsg);
}
callingActivity.finish(); //Finish activity only once you are done
}