I am working on have been getting contacts from the device's address book. I have an issue with getting the Email. I have tried and it keeps showing either phone number or a number (I am guessing it is a type). Please Help.
Here is my AdressBook.java
package newgbacard.gbacard.com.gbacard.fragments;
import android.content.Intent;
import android.support.v4.app.Fragment;
import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import newgbacard.gbacard.com.gbacard.R;
import newgbacard.gbacard.com.gbacard.activities.ContactDetailActivity;
import newgbacard.gbacard.com.gbacard.activities.SettingsActivity;
import newgbacard.gbacard.com.gbacard.adapters.ContactUserAdapter;
import newgbacard.gbacard.com.gbacard.models.Contact;
import newgbacard.gbacard.com.gbacard.utils.Constants;
public class AddressBookFragment2 extends Fragment {
private ArrayList<Contact> selectUsers;
private ListView listView;
private Cursor phoneCursor;
private Cursor emailCursor;
private MenuItem searchMenuItem;
// Pop up
ContentResolver resolver;
SearchView searchView;
ContactUserAdapter adapter;
String email;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_addressbook, null);
selectUsers = new ArrayList<Contact>();
resolver = getActivity().getContentResolver();
listView = (ListView) view.findViewById(R.id.list);
try {
phoneCursor = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
LoadContact loadContact = new LoadContact();
loadContact.execute();
setHasOptionsMenu(true);
} catch (Exception e){
e.printStackTrace();
}
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_addressbook_fragment, menu);
searchMenuItem = menu.findItem(R.id.action_search);
searchView = (SearchView) searchMenuItem.getActionView();
searchView.setOnQueryTextListener(listener);
searchView.setFocusable(true);
searchView.setIconified(false);
searchView.requestFocusFromTouch();
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent intent = new Intent(getActivity(), SettingsActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
SearchView.OnQueryTextListener listener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
// newText is text entered by user to SearchView
adapter.filter(newText);
return false;
}
};
// Load data on background
class LoadContact extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
// Get Contact list from Phone
if (phoneCursor != null) {
Log.e("count", "" + phoneCursor.getCount());
if (phoneCursor.getCount() == 0) {
Toast.makeText(getActivity(), "No contacts in your contact list.", Toast.LENGTH_LONG).show();
}
while (phoneCursor.moveToNext()) {
Bitmap bitmapThumbnail = null;
String id = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
String displayName = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String email = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
String address = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
String imageThumbnail = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI));
try {
if (imageThumbnail != null) {
bitmapThumbnail = MediaStore.Images.Media.getBitmap(resolver, Uri.parse(imageThumbnail));
} else {
// Log.e("No Image Thumb", "--------------");
}
} catch (IOException e) {
e.printStackTrace();
}
Contact contact = new Contact();
contact.setThumb(bitmapThumbnail);
contact.setFirstName(displayName);
contact.setLastName("");
contact.setPhoneNumber(phoneNumber);
contact.setEmail(email);
contact.setAddress(address);
selectUsers.add(contact);
}
}
//phones.close();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
adapter = new ContactUserAdapter(selectUsers, getActivity());
listView.setAdapter(adapter);
// Select item on listclick
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
try {
Contact contact = selectUsers.get(i);
Intent intent = new Intent(getActivity(), ContactDetailActivity.class);
intent.putExtra(Constants.TAG_CONTACT_DETAIL, contact);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
});
//listView.setFastScrollEnabled(true);
}
}
}
Please I would appreciate if this issue is resolved. Thanks
You're trying the get an email from your phoneCursor field, which you initalize like this:
phoneCursor = getActivity().getContentResolver().query(Phone.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
The table at Phone.CONTENT_URI contains only phone-number related information, it doesn't contain any emails.
If you want more then one type of data, you should query on CommonDataKinds.Data.CONTENT_URI which should return all types of contact information, you can limit it to phones and emails by using the selection:
Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "' OR " + Data.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "'"
docs: https://developer.android.com/reference/android/provider/ContactsContract.Data.html
Related
I am trying to filter my RecyclerView using SearchView by following this guide: https://www.geeksforgeeks.org/searchview-in-android-with-recyclerview/
However, I am getting an IndexOutOfBoundsException when making one Arraylist equal to another, which I believe is happening at this portion of the code here:
public void filterList(ArrayList filteredlist) {
// below line is to add our filtered
// list in our course array list.
book_title = filteredlist;
// below line is to notify our adapter
// as change in recycler view data.
notifyDataSetChanged();
}
Here is the full code for my adapter class:
package com.benjamin.kwok.recipertracker;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {
private Context context;
private Activity activity;
private ArrayList book_id, book_title, book_author, book_pages;
CustomAdapter(Activity activity, Context context, ArrayList book_id, ArrayList book_title, ArrayList book_author,
ArrayList book_pages){
this.activity = activity;
this.context = context;
this.book_id = book_id;
this.book_title = book_title;
this.book_author = book_author;
this.book_pages = book_pages;
}
public void filterList(ArrayList filteredlist) {
// below line is to add our filtered
// list in our course array list.
book_title = filteredlist;
// below line is to notify our adapter
// as change in recycler view data.
notifyDataSetChanged();
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.my_row, parent, false);
return new MyViewHolder(view);
}
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.book_title_txt.setText(String.valueOf(book_title.get(position)));
holder.book_author_txt.setText(String.valueOf(book_author.get(position)));
holder.book_pages_txt.setText(String.valueOf(book_pages.get(position)));
//Recyclerview onClickListener
holder.mainLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, UpdateActivity.class);
intent.putExtra("id", String.valueOf(book_id.get(position)));
intent.putExtra("title", String.valueOf(book_title.get(position)));
intent.putExtra("author", String.valueOf(book_author.get(position)));
intent.putExtra("pages", String.valueOf(book_pages.get(position)));
activity.startActivityForResult(intent, 1);
}
});
}
#Override
public int getItemCount() {
return book_id.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView book_id_txt, book_title_txt, book_author_txt, book_pages_txt;
LinearLayout mainLayout;
MyViewHolder(#NonNull View itemView) {
super(itemView);
book_title_txt = itemView.findViewById(R.id.recipe_title_txt);
book_author_txt = itemView.findViewById(R.id.book_description_txt);
book_pages_txt = itemView.findViewById(R.id.recipe_pages_txt);
mainLayout = itemView.findViewById(R.id.mainLayout);
//Animate Recyclerview
Animation translate_anim = AnimationUtils.loadAnimation(context, R.anim.translate_anim);
mainLayout.setAnimation(translate_anim);
}
}
}
And the full code for my MainActivity:
package com.benjamin.kwok.recipertracker;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.app.Activity;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
FloatingActionButton add_button;
FloatingActionButton camera_button;
ImageView empty_imageview;
ImageView imageView;
TextView no_data;
MyDatabaseHelper myDB;
ArrayList<String> recipe_id, recipe_title, recipe_description, recipe_minutes;
CustomAdapter customAdapter;
final static private int NEW_PICTURE = 1;
private String mCameraFileName;
private static final String TAG = "CapturePicture";
static final int REQUEST_PICTURE_CAPTURE = 1;
private String pictureFilePath;
private String deviceIdentifier;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
// SharedPreferences mSharedPreference= PreferenceManager.getDefaultSharedPreferences(this);
// SharedPreferences.Editor editor = mSharedPreference.edit();
// String text= mSharedPreference.getString(getString(R.string.name), "");
//// name_output.setText(text);
recyclerView = findViewById(R.id.recyclerView);
add_button = findViewById(R.id.add_button);
camera_button = findViewById(R.id.camera_button);
empty_imageview = findViewById(R.id.empty_imageview);
imageView = findViewById(R.id.imageView);
no_data = findViewById(R.id.no_data);
add_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
}
});
camera_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 100);
}
});
myDB = new MyDatabaseHelper(MainActivity.this);
recipe_id = new ArrayList<>();
recipe_title = new ArrayList<>(10);
recipe_description = new ArrayList<>();
recipe_minutes = new ArrayList<>();
storeDataInArrays();
customAdapter = new CustomAdapter(MainActivity.this,this, recipe_id, recipe_title, recipe_description,
recipe_minutes);
recyclerView.setAdapter(customAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
loadData();
}
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100) {
Bundle bundle = data.getExtras();
Bitmap captureImage = (Bitmap) bundle.get("data");
imageView.setImageBitmap(captureImage);
saveToGallery();
}
if(resultCode == RESULT_OK){
Toast.makeText(this, "Image added to Gallery", Toast.LENGTH_LONG);
}
}
private void saveToGallery(){
BitmapDrawable draw = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = draw.getBitmap();
FileOutputStream outStream = null;
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/RecipeImages");
dir.mkdirs();
String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outFile = new File(dir, fileName);
MediaScannerConnection.scanFile(this, new String[] { outFile.getPath() }, new String[] { "image/jpeg" }, null);
try {
outStream = new FileOutputStream(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
try {
outStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
void storeDataInArrays(){
Cursor cursor = myDB.readAllData();
if(cursor.getCount() == 0){
empty_imageview.setVisibility(View.VISIBLE);
no_data.setVisibility(View.VISIBLE);
}else{
while (cursor.moveToNext()){
recipe_id.add(cursor.getString(0));
recipe_title.add(cursor.getString(1));
recipe_description.add(cursor.getString(2));
recipe_minutes.add(cursor.getString(3));
}
empty_imageview.setVisibility(View.GONE);
no_data.setVisibility(View.GONE);
}
}
public void loadData() {
SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
String name = mPreferences.getString("name","");
setTitle(name+"'s" + " Recipe Tracker");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.my_menu, menu);
// return super.onCreateOptionsMenu(menu);
MenuItem searchItem = menu.findItem(R.id.actionSearch);
// getting search view of our item.
SearchView searchView = (SearchView) searchItem.getActionView();
// below line is to call set on query text listener method.
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
// inside on query text change method we are
// calling a method to filter our recycler view.
filter(newText);
return false;
}
});
return true;
}
private void filter(String text) {
// creating a new array list to filter our data.
ArrayList filteredlist = new ArrayList<>();
// running a for loop to compare elements.
for (String item : recipe_title) {
// checking if the entered string matched with any item of our recycler view.
if (item.toLowerCase().contains(text.toLowerCase())) {
// if the item is matched we are
// adding it to our filtered list.
filteredlist.add(item);
}
}
if (filteredlist.isEmpty()) {
// if no item is added in filtered list we are
// displaying a toast message as no data found.
Toast.makeText(this, "No Data Found..", Toast.LENGTH_SHORT).show();
} else {
// at last we are passing that filtered
// list to our adapter class.
customAdapter.filterList(filteredlist);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.delete_all){
confirmDialog();
}
return super.onOptionsItemSelected(item);
}
void confirmDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Delete All?");
builder.setMessage("Are you sure you want to delete all Data?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
MyDatabaseHelper myDB = new MyDatabaseHelper(MainActivity.this);
myDB.deleteAllData();
//Refresh Activity
Intent intent = new Intent(MainActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
builder.create().show();
}
}
As soon as I start typing in a new search query, this error seems to get thrown.
JSON data is showing null after publishing my app on google play, But it shows the data in the emulator while running the non published app sourcecode. The data is coming from the Database online from external server.The json data is visible in the URL, But is shows null in my published app. What could be the reason??.....
PLEASE HELP ME
This is my MainActivity
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.json.JSONArray;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class JUR extends AppCompatActivity implements jurAdapter.JURAdapterListener {
private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView recyclerView2;
private List<JURlist> jurList;
private jurAdapter mAdapter;
private SearchView searchView;
ProgressBar progressBar2;
static {
System.loadLibrary("keys");
}
public native String getJUR();
public native String geturl2();
String getJUR = URLEncoder.encode(getJUR());
String geturl2 = URLEncoder.encode(geturl2());
// url to fetch contacts json
private final String URL = "https://"+geturl2+"/...../"+getJUR;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jur);
progressBar2 = findViewById(R.id.progress2);
progressBar2.setVisibility(View.VISIBLE);
Toolbar toolbar2 = findViewById(R.id.toolbar2);
setSupportActionBar(toolbar2);
// toolbar fancy stuff
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.toolbar_JUR);
recyclerView2 = findViewById(R.id.recycler_view2);
jurList = new ArrayList<>();
mAdapter = new jurAdapter(this, jurList, this);
// white background notification bar
whiteNotificationBar(recyclerView2);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView2.setLayoutManager(mLayoutManager);
recyclerView2.setItemAnimator(new DefaultItemAnimator());
recyclerView2.addItemDecoration(new MyDividerItemDecoration(this, DividerItemDecoration.VERTICAL, 36));
recyclerView2.setAdapter(mAdapter);
fetchJUR();
}
/**
* fetches json by making http calls
*/
private void fetchJUR() {
JsonArrayRequest request = new JsonArrayRequest(URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
if (response == null) {
Toast.makeText(getApplicationContext(), "Couldn't fetch JURISDICTION Pleas try again.", Toast.LENGTH_LONG).show();
return;
}
List<JURlist> items = new Gson().fromJson(response.toString(), new TypeToken<List<JURlist>>() {
}.getType());
// adding contacts to contacts list
jurList.clear();
jurList.addAll(items);
// refreshing recycler view
mAdapter.notifyDataSetChanged();
progressBar2.setVisibility(View.GONE);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// error in getting json
Log.e(TAG, "Error: " + error.getMessage());
Toast.makeText(getApplicationContext(), "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
APP.getInstance().addToRequestQueue(request);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
searchView.setMaxWidth(Integer.MAX_VALUE);
// listening to search query text change
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// filter recycler view when query submitted
mAdapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String query) {
// filter recycler view when text is changed
mAdapter.getFilter().filter(query);
return false;
}
});
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_search) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
// close search view on back button pressed
if (!searchView.isIconified()) {
searchView.setIconified(true);
return;
}
super.onBackPressed();
}
private void whiteNotificationBar(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int flags = view.getSystemUiVisibility();
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
view.setSystemUiVisibility(flags);
getWindow().setStatusBarColor(Color.WHITE);
}
}
#Override
public void onJURSelected(JURlist jur) {
Toast.makeText(getApplicationContext(), "Selected: " + jur.getSTATE() + ", " + jur.getZONE(), Toast.LENGTH_LONG).show();
}
}
This is the Adapter
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class jurAdapter extends RecyclerView.Adapter<jurAdapter.MyViewHolder>
implements Filterable {
private Context context;
private List<JURlist> JuRlist;
private List<JURlist> JURlistFiltered;
private JURAdapterListener listener;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView STATE, ZONE, COM, DIVI, RANAME, RANGE1;
// public ImageView thumbnail;
public MyViewHolder(View view) {
super(view);
STATE = view.findViewById(R.id.STATE);
ZONE = view.findViewById(R.id.ZONE);
COM = view.findViewById(R.id.COM);
DIVI = view.findViewById(R.id.DIVI);
RANAME = view.findViewById(R.id.RANAME);
RANGE1 = view.findViewById(R.id.RANGE1);
// thumbnail = view.findViewById(R.id.thumbnail);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// send selected contact in callback
listener.onJURSelected(JURlistFiltered.get(getAdapterPosition()));
}
});
}
}
public jurAdapter(Context context, List<JURlist> JURLIST, JURAdapterListener listener) {
this.context = context;
this.listener = listener;
this.JuRlist = JURLIST;
this.JURlistFiltered = JURLIST;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent1, int viewType1) {
View itemView = LayoutInflater.from(parent1.getContext())
.inflate(R.layout.jur_item_row, parent1, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
final JURlist jurlist = JURlistFiltered.get(position);
holder.STATE.setText("STATE : "+jurlist.getSTATE()+"\r\n") ;
holder.ZONE.setText("ZONE : "+jurlist.getZONE()+"\r\n");
holder.COM.setText("COMMISSIONERATE NAME : "+jurlist.getCOM()+"\r\n");
holder.DIVI.setText("DIVISION NAME : "+jurlist.getDIVI()+"\r\n");
holder.RANAME.setText("RANGE NAME : "+jurlist.getRANAME()+"\r\n");
holder.RANGE1.setText("RANGE JURISDICTION : \r\n"+jurlist.getRANGE1());
// Glide.with(context)
// .load(contact.getImage())
// .apply(RequestOptions.circleCropTransform())
// .into(holder.thumbnail);
}
#Override
public int getItemCount() {
return JURlistFiltered.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
JURlistFiltered = JuRlist;
} else {
List<JURlist> filteredList = new ArrayList<>();
for (JURlist row : JuRlist) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.getSTATE().toLowerCase().contains(charString.toLowerCase()) || row.getZONE().toLowerCase().contains(charString.toLowerCase()) || row.getCOM().toLowerCase().contains(charString.toLowerCase()) || row.getDIVI().toLowerCase().contains(charString.toLowerCase()) || row.getRANAME().toLowerCase().contains(charString.toLowerCase()) || row.getRANGE1().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(row);
}
}
JURlistFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = JURlistFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
JURlistFiltered = (ArrayList<JURlist>) filterResults.values;
notifyDataSetChanged();
}
};
}
public interface JURAdapterListener {
void onJURSelected(JURlist jur);
}
}```
[1]: https://i.stack.imgur.com/vcWmG.jpg
I am pretty new to this whole android development but I am looking to create a simple android app making use of a sql database, cardViews and a RecycleView.
The app I have so far works but I am trying to add a button to the DetailedActivity which will allow me to remove the entry from the database.
The desired workflow would be:
Get Data
Select a CardView
Click New Button (will be
delete)
Go back to CardView, Remove entry on which the button has
been pressed and populate the CardView.
RecyclerAdapter.java
package com.example.prabhu.databasedemo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
static List<DatabaseModel> dbList;
static Context context;
RecyclerAdapter(Context context, List<DatabaseModel> dbList ){
this.dbList = new ArrayList<DatabaseModel>();
this.context = context;
this.dbList = dbList;
}
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_row, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {
holder.name.setText(dbList.get(position).getName());
holder.email.setText(dbList.get(position).getEmail());
}
#Override
public int getItemCount() {
return dbList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView name,email;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
name = (TextView) itemLayoutView
.findViewById(R.id.rvname);
email = (TextView)itemLayoutView.findViewById(R.id.rvemail);
itemLayoutView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Intent intent = new Intent(context,DetailsActivity.class);
Bundle extras = new Bundle();
extras.putInt("position",getAdapterPosition());
intent.putExtras(extras);
/*
int i=getAdapterPosition();
intent.putExtra("position", getAdapterPosition());*/
context.startActivity(intent);
Toast.makeText(RecyclerAdapter.context, "you have clicked Row " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
}
}
DatabaseHelper.java
package com.example.prabhu.databasedemo;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class DatabaseHelpher extends SQLiteOpenHelper {
private static final String DATABASE_NAME="student";
private static final int DATABASE_VERSION = 1;
private static final String STUDENT_TABLE = "stureg";
private static final String STU_TABLE = "create table "+STUDENT_TABLE +"(name TEXT,email TEXT primary key,roll TEXT,address TEXT,branch TEXT)";
Context context;
public DatabaseHelpher(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(STU_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + STUDENT_TABLE);
// Create tables again
onCreate(db);
}
/* Insert into database*/
public void insertIntoDB(String name,String email,String roll,String address,String branch){
Log.d("insert", "before insert");
// 1. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
// 2. create ContentValues to add key "column"/value
ContentValues values = new ContentValues();
values.put("name", name);
values.put("email", email);
values.put("roll", roll);
values.put("address", address);
values.put("branch", branch);
// 3. insert
db.insert(STUDENT_TABLE, null, values);
// 4. close
db.close();
Toast.makeText(context, "insert value", Toast.LENGTH_SHORT);
Log.i("insert into DB", "After insert");
}
/* Retrive data from database */
public List<DatabaseModel> getDataFromDB(){
List<DatabaseModel> modelList = new ArrayList<DatabaseModel>();
String query = "select * from "+STUDENT_TABLE;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query,null);
if (cursor.moveToFirst()){
do {
DatabaseModel model = new DatabaseModel();
model.setName(cursor.getString(0));
model.setEmail(cursor.getString(1));
model.setRoll(cursor.getString(2));
model.setAddress(cursor.getString(3));
model.setBranch(cursor.getString(4));
modelList.add(model);
}while (cursor.moveToNext());
}
Log.d("student data", modelList.toString());
return modelList;
}
/*delete a row from database*/
public void deleteARow(String email){
SQLiteDatabase db= this.getWritableDatabase();
db.delete(STUDENT_TABLE, "email" + " = ?", new String[] { email });
db.close();
}
}
DatabaseModel.java
package com.example.prabhu.databasedemo;
public class DatabaseModel {
private String name;
private String roll;
private String address;
private String branch;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRoll() {
return roll;
}
public void setRoll(String roll) {
this.roll = roll;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
MainActivity.java
package com.example.prabhu.databasedemo;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
EditText etName,etRoll,etAddress,etBranch,etEmail;
Button btnSubmit,btngetdata;
DatabaseHelpher helpher;
List<DatabaseModel> dbList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
dbList= new ArrayList<DatabaseModel>();
etName = (EditText)findViewById(R.id.etName);
etRoll = (EditText)findViewById(R.id.etRoll);
etAddress =(EditText)findViewById(R.id.etAddress);
etBranch = (EditText)findViewById(R.id.etBranch);
etEmail = (EditText)findViewById(R.id.etEmail);
btnSubmit =(Button)findViewById(R.id.btnSubmit);
btngetdata =(Button)findViewById(R.id.btngetdata);
btngetdata.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, SecondActivity.class));
// startActivity(new Intent(MainActivity.this, DetailsActivity.class));
}
});
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name=etName.getText().toString();
String email=etEmail.getText().toString();
String roll=etRoll.getText().toString();
String address=etAddress.getText().toString();
String branch=etBranch.getText().toString();
if(name.equals("") || email.equals("") || roll.equals("") ||address.equals("")||branch.equals("")){
Toast.makeText(MainActivity.this,"Please fill all the fields",Toast.LENGTH_SHORT).show();
}else {
helpher = new DatabaseHelpher(MainActivity.this);
helpher.insertIntoDB(name, email, roll, address, branch);
}
etName.setText("");
etRoll.setText("");
etAddress.setText("");
etBranch.setText("");
etEmail.setText("");
Toast.makeText(MainActivity.this, "insert value", Toast.LENGTH_SHORT);
}
});
}
}
SecondActivity.java
package com.example.prabhu.databasedemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.List;
public class SecondActivity extends AppCompatActivity {
DatabaseHelpher helpher;
List<DatabaseModel> dbList;
RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
helpher = new DatabaseHelpher(this);
dbList= new ArrayList<DatabaseModel>();
dbList = helpher.getDataFromDB();
mRecyclerView = (RecyclerView)findViewById(R.id.recycleview);
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter (see also next example)
mAdapter = new RecyclerAdapter(this,dbList);
mRecyclerView.setAdapter(mAdapter);
}
#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_second, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
DetailedActivity.java
package com.example.prabhu.databasedemo;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class DetailsActivity extends AppCompatActivity {
DatabaseHelpher helpher;
List<DatabaseModel> dbList;
int position;
TextView tvname,tvemail,tvroll,tvaddress,tvbranch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
// 5. get status value from bundle
position = bundle.getInt("position");
tvname =(TextView)findViewById(R.id.name);
tvemail =(TextView)findViewById(R.id.email);
tvroll =(TextView)findViewById(R.id.roll);
tvaddress =(TextView)findViewById(R.id.address);
tvbranch =(TextView)findViewById(R.id.branch);
helpher = new DatabaseHelpher(this);
dbList= new ArrayList<DatabaseModel>();
dbList = helpher.getDataFromDB();
if(dbList.size()>0){
String name= dbList.get(position).getName();
String email=dbList.get(position).getEmail();
String roll=dbList.get(position).getRoll();
String address=dbList.get(position).getAddress();
String branch=dbList.get(position).getBranch();
tvname.setText(name);
tvemail.setText(email);
tvroll.setText(roll);
tvaddress.setText(address);
tvbranch.setText(branch);
}
Toast.makeText(DetailsActivity.this, dbList.toString(), Toast.LENGTH_SHORT);
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_details, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
I had added a button (findViewByID) in the DetailedAvtivity.java with an OnClickListener. Initially to only show a toast, however, when the button on any detailed view is clicked, nothing happens - no toast.
So really, questions are:
Where do I have to define the button and where do I implement the onClickListener?
How do I make the button delete the entry? For now I am happy to use the email from the email TextView (tvemail) but I will have to go back and refresh the cards as well.
Thanks all in advance
After some time I found the answer. What I was doing was correct but messed the toast command.
Basically what needs to be done is
delButton = (Button) findViewById(R.id.button);
delButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), tvemail.getText() + " deleted", Toast.LENGTH_SHORT).show();
startActivity(new Intent(DetailsActivity.this, MainActivity.class));
helpher.deleteARow((String) tvemail.getText());
}
});
In my note app for Android, if I press long on a note then chose "Delete" to delete the note, the note still exists in the list, then after I close the app then return to it, the note is gone!
Hint: I am uses the onContextItemSelected method to show the "Delete" option.
How I can delete the note from the list and from the database?!
The MainActivity class which contains the onContextItemSelected method:
package com.twitter.i_droidi.mynotes;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends ActionBarActivity implements AdapterView.OnItemClickListener {
ListView lv;
NotesDataSource nDS;
List<NotesModel> notesList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nDS = new NotesDataSource(this);
lv = (ListView) findViewById(R.id.lv);
nDS.open();
notesList = nDS.getAllNotes();
nDS.close();
String[] notes = new String[notesList.size()];
for (int i = 0; i < notesList.size(); i++) {
notes[i] = notesList.get(i).getTitle();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,
android.R.id.text1, notes);
lv.setAdapter(adapter);
registerForContextMenu(lv);
lv.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent nView = new Intent(this, Second2.class);
nView.putExtra("id", notesList.get(position).getId());
nView.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(nView);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_delete, menu);
super.onCreateContextMenu(menu, v, menuInfo);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.delete:
nDS.open();
nDS.deleteNote("id"); // Check...!!!
nDS.close();
Toast nDelete = Toast.makeText(this, R.string.deleted, Toast.LENGTH_LONG);
nDelete.show();
}
return super.onContextItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.mainMenuNewNote:
Intent nNote = new Intent(this, Second.class);
startActivity(nNote);
return true;
case R.id.mainMenuAbout:
AlertDialog.Builder aboutDialog = new AlertDialog.Builder(this);
aboutDialog.setTitle(getString(R.string.about_title));
aboutDialog.setMessage(R.string.about_body);
aboutDialog.setIcon(R.drawable.my_notes);
aboutDialog.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface aboutDialog, int witch) {
// Do Not Do Anything.
}
});
aboutDialog.show();
return true;
case R.id.mainMenuExit:
AlertDialog.Builder exDialog = new AlertDialog.Builder(this);
exDialog.setTitle(R.string.exit_title);
exDialog.setMessage(R.string.exit_body);
exDialog.setIcon(R.drawable.my_notes);
exDialog.setNegativeButton(R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface exDialog, int which) {
finish();
}
});
exDialog.setPositiveButton(R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface exDialog, int which) {
// Do Not Do Anything.
}
});
exDialog.show();
return true;
}
return super.onOptionsItemSelected(item);
}
}
The DB class:
package com.twitter.i_droidi.mynotes;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DB extends SQLiteOpenHelper {
private static final String DB_NAME = "MyNotes";
private static final int DB_VERSION = 1;
public static final String TABLE_NAME = "MyNotes";
public static final String ID = "id";
public static final String TITLE = "title";
public static final String BODY = "body";
private static final String DB_CREATE = "create table " + TABLE_NAME + " (" + ID + " integer primary key autoincrement, " +
TITLE + " text not null, " + BODY + " text not null)";
public DB(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
The NotesDataSource class:
package com.twitter.i_droidi.mynotes;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class NotesDataSource {
DB myDB;
SQLiteDatabase sql;
String[] getAllColumns = new String[]{DB.ID, DB.TITLE, DB.BODY};
public NotesDataSource(Context context) {
myDB = new DB(context);
}
public void open() {
try {
sql = myDB.getWritableDatabase();
} catch (Exception ex) {
Log.d("Error in your database!", ex.getMessage());
}
}
public void close() {
sql.close();
}
public void createNote(String title, String body) {
ContentValues note = new ContentValues();
note.put(myDB.TITLE, title);
note.put(myDB.BODY, body);
sql.insert(myDB.TABLE_NAME, null, note);
}
public NotesModel getNote(int id) {
NotesModel note = new NotesModel();
Cursor cursor = sql.rawQuery("SELECT * FROM " + DB.TABLE_NAME + " WHERE " + DB.ID + " = ?", new String[]{id + ""});
if (cursor.getCount() > 0) {
cursor.moveToFirst();
note.setId(cursor.getInt(0));
note.setTitle(cursor.getString(1));
note.setBody(cursor.getString(2));
cursor.close();
}
return note;
}
public void updateNote(int id, String title, String body) {
ContentValues note = new ContentValues();
note.put(myDB.TITLE, title);
note.put(myDB.BODY, body);
sql.update(myDB.TABLE_NAME, note, myDB.ID + " = " + id, null);
}
public void deleteNote(Object id) {
sql.delete(myDB.TABLE_NAME, myDB.ID + " = " + id, null);
}
public List<NotesModel> getAllNotes() {
List<NotesModel> notesList = new ArrayList<NotesModel>();
StringBuffer selectQuery = new StringBuffer();
selectQuery.append("SELECT * FROM "+ myDB.TABLE_NAME +"");
Cursor cursor = sql.rawQuery(selectQuery.toString(), null);
if(cursor != null && cursor.moveToFirst()) {
do {
NotesModel notes = new NotesModel();
notes.setId(cursor.getInt(0));
notes.setTitle(cursor.getString(1));
notes.setBody(cursor.getString(2));
notesList.add(notes);
} while (cursor.moveToNext());
}
cursor.close();
return notesList;
}
}
After removing item from database
Remove the deleted item from
String[] notes
by using
notes.remove(position);
nd call
adapter.notifyDataSetChanged();
I user LoaderManager and CursorLoader to load the data from my database using a ContentProvider.
Now, the initial load is fine. I have a ListView that display all the rows from the DB(only the names-String adapter).
Now, when I add/delete a row from the database, I want to refresh the ListView so it will display the recent changes.
Currently I just restart the loader with the method "restartLoader" whenever a change is commited but I want to ask if there is another way of doing this without restarting the loader.
Here is my activity class code:
package com.silverfix.phony.activities;
import java.util.ArrayList;
import com.silverfix.phony.R;
import com.silverfix.phony.contentprovider.PhonyContentProvider;
import com.silverfix.phony.database.RingtonesTable;
import android.app.Activity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.Editable;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
public class RingtonesActivity extends Activity implements LoaderCallbacks<Cursor>{
private final int PICK_RINGTONE_CODE = 1;
private final int CURSOR_LOADER_ID = 1;
private final int EDIT_ID = 1;
private final int DELETE_ID = 2;
private String[] ContextCommands;
private ArrayAdapter<String> adapter;
private ArrayList<String> ringtones;
private ListView listview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ringtones);
listview = (ListView) findViewById(R.id.list);
Button add = (Button) findViewById(R.id.add_ringtone);
add.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, PICK_RINGTONE_CODE);
}
});
fillData();
}
#Override
protected void onActivityResult(int arg0, int arg1, Intent arg2) {
super.onActivityResult(arg0, arg1, arg2);
switch (arg0) {
case 1: // PICK_RINGTONE_CODE
if (arg1 == RESULT_OK) {
Uri ringtoneURI = arg2.getData();
String[] projection = { MediaStore.MediaColumns.DISPLAY_NAME };
Cursor cursor = getContentResolver().query(ringtoneURI,
projection, null, null, null);
cursor.moveToFirst();
int column = cursor
.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
String displayName = cursor.getString(column);
addRingtone(ringtoneURI, displayName);
cursor.close();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.ringtones, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void fillData() {
getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);
ringtones = new ArrayList<String>();
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, ringtones);
ContextCommands = getResources().getStringArray(R.array.commands);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
editRingtone();
}
});
registerForContextMenu(listview);
listview.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
if (v.getId()==R.id.list) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
menu.setHeaderTitle(ContextCommands[info.position]);
String[] menuItems = getResources().getStringArray(R.array.commands);
menu.add(Menu.NONE, EDIT_ID, 0, menuItems[0]);
menu.add(Menu.NONE, DELETE_ID, 0, menuItems[1]);
}
}
});
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()) {
case EDIT_ID:
editRingtone();
return true;
case DELETE_ID:
String name = adapter.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);
getContentResolver().delete(PhonyContentProvider.RINGTONES_URI, RingtonesTable.COLUMN_NAME
+ "='" + name + "'", null);
return true;
default:
return super.onContextItemSelected(item);
}
}
private void editRingtone() {
Intent i = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, PICK_RINGTONE_CODE);
}
private void addRingtone(Uri uri, String name) {
String[] projection = { RingtonesTable.COLUMN_NAME };
Cursor cursor = getContentResolver().query(
PhonyContentProvider.RINGTONES_URI, projection,
RingtonesTable.COLUMN_NAME + "='"+name+"'", null, null);
if (cursor.getCount() == 0) {
ContentValues values = new ContentValues();
values.put(RingtonesTable.COLUMN_NAME, name);
values.put(RingtonesTable.COLUMN_URI, uri.toString());
getContentResolver().insert(PhonyContentProvider.RINGTONES_URI,
values);
getLoaderManager().restartLoader(CURSOR_LOADER_ID, null, this);
} else {
Toast.makeText(this, "You already picked that ringtone!",
Toast.LENGTH_LONG).show();
cursor.close();
}
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {RingtonesTable.COLUMN_ID, RingtonesTable.COLUMN_NAME, RingtonesTable.COLUMN_URI};
return new CursorLoader(this, PhonyContentProvider.RINGTONES_URI, projection, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
swapCursor(null);
}
private void swapCursor(Cursor cursor) {
if(cursor != null) {
cursor.moveToFirst();
ringtones.clear();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
int column = cursor.getColumnIndex(RingtonesTable.COLUMN_NAME);
ringtones.add(cursor.getString(column));
}
adapter.notifyDataSetChanged();
cursor.close();
return;
}
ringtones.clear();
adapter.notifyDataSetChanged();
}
}
Since you already have access to the loader, you may not expect that much of a change, but another way of implementing this is by having the cursor setting PhonyContentProvider.RINGTONES_URI as its notification uri and notifying the uri whenever the database data changes.
Relevant methods:
setNotificationUri
notifyChange