Is it possible to write APN programmatically on Android 4.4?
I noticed that the Telephony.Carriers is available for API level 19.
I have a software with APN write feature. Since Android 4.0 you can write APN settings only if you have system permissions. My software was designed to be a system software, so I can write APN and other settings. But, this feature is no longer working in Android 4.4 and I don't know why yet.
After read the Telephony.Carriers class, I could not find a new way to write APN. It's just a class to tell you informations but can't change them.
My code to write APN is:
public class APN {
public static final int AUTH_TYPE_UNKNOW = -1;
public static final int AUTH_TYPE_NONE = 0;
public static final int AUTH_TYPE_PAP = 1;
public static final int AUTH_TYPE_CHAP = 2;
public static final int AUTH_TYPE_PAP_OR_CHAP = 3;
private int id;
private String name;
private String user;
private String password;
private String apn;
private String mcc;
private String mnc;
private String type;
private String server;
private String proxy;
private String port;
private String mmsProxy;
private String mmsPort;
private String mmsc;
private String current;
private int authType;
public APN() {
id = -1;
name = "";
user = "";
password = "";
apn = "";
mcc = "";
mnc = "";
type = "default,supl";
server = "";
proxy = "";
port = "";
mmsProxy = "";
mmsPort = "";
mmsc = "";
current = "";
authType = AUTH_TYPE_NONE;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getApn() {
return apn;
}
public void setApn(String apn) {
this.apn = apn;
}
public String getMcc() {
return mcc;
}
public void setMcc(String mcc) {
this.mcc = mcc;
}
public String getMnc() {
return mnc;
}
public void setMnc(String mnc) {
this.mnc = mnc;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public String getProxy() {
return proxy;
}
public void setProxy(String proxy) {
this.proxy = proxy;
}
public String getMmsProxy() {
return mmsProxy;
}
public void setMmsProxy(String mmsProxy) {
this.mmsProxy = mmsProxy;
}
public String getMmsPort() {
return mmsPort;
}
public void setMmsPort(String mmsPort) {
this.mmsPort = mmsPort;
}
public String getMmsc() {
return mmsc;
}
public void setMmsc(String mmsc) {
this.mmsc = mmsc;
}
public String getCurrent() {
return current;
}
public void setCurrent(String current) {
this.current = current;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public int getAuthType() {
return authType;
}
public void setAuthType(int authType) {
this.authType = authType;
}
}
and:
public class APNUtils {
private static final Uri APN_TABLE_URI = Uri.parse("content://telephony/carriers");
private static final Uri APN_PREFER_URI = Uri.parse("content://telephony/carriers/preferapn");
private static ContentValues prepareValues(APN apn) {
ContentValues values = new ContentValues();
if (!apn.getName().trim().equals(""))
values.put("name", apn.getName());
if (!apn.getApn().trim().equals(""))
values.put("apn", apn.getApn());
if (!apn.getMcc().trim().equals(""))
values.put("mcc", apn.getMcc());
if (!apn.getMnc().trim().equals(""))
values.put("mnc", apn.getMnc());
if (!apn.getMcc().trim().equals("") && !apn.getMnc().trim().equals(""))
values.put("numeric", apn.getMcc() + apn.getMnc());
if (!apn.getUser().trim().equals(""))
values.put("user", apn.getUser());
if (!apn.getPassword().trim().equals(""))
values.put("password", apn.getPassword());
if (!apn.getServer().trim().equals(""))
values.put("server", apn.getServer());
if (!apn.getProxy().trim().equals(""))
values.put("proxy", apn.getProxy());
if (!apn.getPort().trim().equals(""))
values.put("port", apn.getPort());
if (!apn.getMmsProxy().trim().equals(""))
values.put("mmsproxy", apn.getMmsProxy());
if (!apn.getMmsPort().trim().equals(""))
values.put("mmsport", apn.getMmsPort());
if (!apn.getMmsc().trim().equals(""))
values.put("mmsc", apn.getMmsc());
if (!apn.getType().trim().equals(""))
values.put("type", apn.getType());
if (!apn.getCurrent().trim().equals(""))
values.put("current", apn.getCurrent());
values.put("authtype", apn.getAuthType());
return values;
}
public static int createNewApn(Context context, APN apn, boolean setAsDefaultAPN) {
Logs.infoLog("APNutils.createNewApn.");
int apnid = -1;
try {
if (apn != null) {
Logs.infoLog("APNutils.createNewApn. Reading APN list.");
Uri APN_URI = Uri.parse("content://telephony/carriers");
ContentResolver resolver = context.getContentResolver();
Logs.infoLog("APNutils.createNewApn. Creating new registry based on parameters.");
ContentValues values = prepareValues(apn);
Logs.infoLog("APNutils.createNewApn. Inserting new APN.");
Cursor c = null;
Uri newRow = resolver.insert(APN_URI, values);
if(newRow != null) {
Logs.infoLog("APNutils.createNewApn. Getting new ID.");
c = resolver.query(newRow, null, null, null, null);
int tableIndex = c.getColumnIndex("_id");
c.moveToFirst();
apnid = c.getShort(tableIndex);
} else
Logs.warningLog("APNutils.createNewApn. New APN was not found. Inserting failed?");
if(c != null){
c.close();
}
if (apnid > -1 && setAsDefaultAPN) {
Logs.infoLog("APNutils.createNewApn. Setting new APN as default.");
ContentValues v = new ContentValues(1);
v.put("apn_id", apnid);
context.getContentResolver().update(APN_PREFER_URI, v, null, null);
}
} else
Logs.warningLog("APNutils.createNewApn. Invalid apn (null).");
} catch (Exception e) {
Logs.errorLog("createNewApn: error", e);
}
Logs.infoLog("APNutils.createNewApn. Returning ID " + String.valueOf(apnid));
return apnid;
}
public static boolean updateApn(Context context, int id, APN apn) {
Logs.infoLog("APNutils.updateApn.");
if (apn != null) {
try {
Logs.infoLog("APNutils.updateApn. Reading APN list.");
Uri APN_URI = Uri.parse("content://telephony/carriers");
ContentResolver resolver = context.getContentResolver();
Logs.infoLog("APNutils.updateApn. Creating new registry based on parameters.");
ContentValues values = prepareValues(apn);
Logs.infoLog("APNutils.updateApn. Inserting new APN.");
int result = resolver.update(APN_URI, values, "_id = " + String.valueOf(id), null);
if (result != -1) {
Logs.infoLog("APNutils.updateApn. APN updated.");
return true;
} else {
Logs.warningLog("APNutils.updateApn. Invalid ID (" + String.valueOf(id) + ").");
return false;
}
} catch (Exception e) {
Logs.errorLog("APNUtils.updateApn error: ", e);
return false;
}
} else {
Logs.warningLog("APNutils.updateApn. Invalid apn (null).");
return false;
}
}
public static boolean verifyApn(Context context, String apn) {
Logs.infoLog("APNutils.verifyApn.");
return getApn(context, apn) > -1;
}
public static int getApn(Context context, String apn) {
Logs.infoLog("APNutils.getApn.");
int result = -1;
Logs.infoLog("APNutils.getApn. Looking for APN " + apn);
String columns[] = new String[] { "_ID", "NAME" };
String where = "name = ?";
String wargs[] = new String[] { apn };
String sortOrder = null;
Cursor cur = context.getContentResolver().query(APN_TABLE_URI, columns, where, wargs, sortOrder);
if (cur != null) {
int tableIndex = cur.getColumnIndex("_id");
if (cur.moveToFirst()) {
Logs.infoLog("APNutils.getApn. APN found.");
result = cur.getShort(tableIndex);
}
cur.close();
}
if (result == -1)
Logs.warningLog("APNutils.getApn. APN not found.");
return result;
}
public static boolean setPreferredApn(Context context, String apn) {
Logs.infoLog("APNutils.setPreferredApn.");
boolean changed = false;
Logs.infoLog("APNutils.setPreferredApn. Looking for APN " + apn);
String columns[] = new String[] { "_ID", "NAME" };
String where = "name = ?";
String wargs[] = new String[] { apn };
String sortOrder = null;
Cursor cur = context.getContentResolver().query(APN_TABLE_URI, columns, where, wargs, sortOrder);
if (cur != null) {
if (cur.moveToFirst()) {
Logs.infoLog("APNutils.setPreferredApn. APN found. Setting as default.");
ContentValues values = new ContentValues(1);
values.put("apn_id", cur.getLong(0));
if (context.getContentResolver().update(APN_PREFER_URI, values, null, null) == 1) {
Logs.infoLog("APNutils.setPreferredApn. APN marked as default.");
changed = true;
}
}
cur.close();
}
if (!changed)
Logs.warningLog("APNutils.setPreferredApn. APN not found or could not be marked as default.");
return changed;
}
public static APN[] getAllApnList(Context context) {
Logs.infoLog("APNutils.getAllApnList.");
APN[] result = null;
Uri contentUri = Uri.parse("content://telephony/carriers/");
Cursor cursor = null;
try
{
cursor = context.getContentResolver().query(contentUri,
new String[] {"_ID", "name", "apn", "mcc", "mnc", "numeric", "user", "password", "server", "proxy",
"port", "mmsproxy", "mmsport", "mmsc", "type", "current", "authtype "}, null, null, null);
if (cursor != null)
{
result = new APN[cursor.getCount()];
int i = 0;
while (cursor.moveToNext())
{
APN apn = new APN();
apn.setId(cursor.getInt(0));
apn.setName(cursor.getString(1));
apn.setApn(cursor.getString(2));
apn.setMcc(cursor.getString(3));
apn.setMnc(cursor.getString(4));
apn.setUser(cursor.getString(6));
apn.setPassword(cursor.getString(7));
apn.setServer(cursor.getString(8));
apn.setProxy(cursor.getString(9));
apn.setPort(cursor.getString(10));
apn.setMmsProxy(cursor.getString(11));
apn.setMmsPort(cursor.getString(12));
apn.setMmsc(cursor.getString(13));
apn.setType(cursor.getString(14));
apn.setCurrent(cursor.getString(15));
apn.setAuthType(cursor.getInt(16));
result[i] = apn;
i++;
}
}
}
catch (Exception ex)
{
//Handle exceptions here
return null;
}
finally
{
if (cursor != null)
cursor.close();
}
return result;
}
}
Related
I am working on a project where user adds data at runtime.The problem is whenever user inserts the fist element it is adding to the database and displaying in recyclerview.But when user adds more data the recyclerview keeps displaying firstelement over and over again.
If the user adds Apple it is adding to database and recyclerview is displaying Apple.Now if the user adds orange it is adding to database but the recyclerview is displaying Apple two times.
I am using Cursorloader to load data,Contentprovider to add data,and CustomCursoradapter(https://gist.github.com/skyfishjy/443b7448f59be978bc59) to set the data to recyclerview
addDetails() method execute when user adds data
public class AddLog extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
TextView TotalAmount,Date;
EditText name,mobile,city,detailname,detailamount;
RecyclerView adddetailtolist;
DetailsAdapter adapter;
Intent returnback;
double totamount;
long logid;
String Debt = "Debt";
String Paid = "Paid";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_log);
Toolbar toolbar = (Toolbar)findViewById(R.id.addlogtoolbar);
setSupportActionBar(toolbar);
toolbar.setTitle("Add Log");
returnback = new Intent(this,MainActivity.class);
Intent intent = getIntent();
logid = intent.getExtras().getLong("ID");
TotalAmount = (TextView)findViewById(R.id.totalAmount);
Date = (TextView)findViewById(R.id.addlogDate);
name = (EditText)findViewById(R.id.AddName);
mobile = (EditText)findViewById(R.id.AddPhone);
city = (EditText)findViewById(R.id.Addcity);
detailname = (EditText)findViewById(R.id.Detailname);
detailamount = (EditText)findViewById(R.id.Detailamount);
adddetailtolist = (RecyclerView)findViewById(R.id.addloglist);
Date.setText(getDate());
getSupportLoaderManager().initLoader(1,null,this);
adapter = new DetailsAdapter(this,null);
adddetailtolist.setAdapter(adapter);
adddetailtolist.setLayoutManager(new LinearLayoutManager(this));
}
private String getDate()
{
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE,dd-MMM-yyyy");
String date = simpleDateFormat.format(calendar.getTime());
return date;
}
public void addDetails(View view)
{
String Name = detailname.getText().toString();
String Amount = detailamount.getText().toString();
String date = Date.getText().toString();
ContentValues contentValues = new ContentValues();
contentValues.put(DataProvider.Dname,Name);
contentValues.put(DataProvider.DCategory,Debt);
contentValues.put(DataProvider.Damount,Amount);
contentValues.put(DataProvider.Ddate,date);
contentValues.put(DataProvider.Per_In,logid);
Uri uri = getContentResolver().insert(DataProvider.ContentUri_Details,contentValues);
Toast.makeText(AddLog.this, uri.toString()+"Value Inserted", Toast.LENGTH_SHORT).show();
NumberFormat currency = changeamount();
TotalAmount.setText(currency.format(getAmount()));
}
private double getAmount()
{
ContentProviderClient client = getContentResolver().acquireContentProviderClient(DataProvider.ContentUri_Details);
SQLiteDatabase db = ((DataProvider)client.getLocalContentProvider()).sqLiteDatabase;
String query = "SELECT SUM(DAmount) FROM Details WHERE Per_In = "+logid;
Cursor cursor = db.rawQuery(query, null);
cursor.moveToFirst();
double amount = cursor.getDouble(0);
cursor.close();
client.release();
return amount;
}
public NumberFormat changeamount()
{
Locale locale = new Locale("en","IN");
NumberFormat currencyformat = NumberFormat.getCurrencyInstance(locale);
return currencyformat;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuinflate = getMenuInflater();
menuinflate.inflate(R.menu.addlogmenu,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.done:
saveData();
}
return super.onOptionsItemSelected(item);
}
private void saveData()
{
String name1 = name.getText().toString();
String phone = mobile.getText().toString();
String address = city.getText().toString();
if (TextUtils.isEmpty(name1)||TextUtils.isEmpty(phone)||TextUtils.isEmpty(address))
{
if (TextUtils.isEmpty(name1))
{
name.setError("Feild can not be Empty");
}
else if (TextUtils.isEmpty(phone))
{
mobile.setError("Feild can not be Empty");
}
else if (TextUtils.isEmpty(address))
{
city.setError("Feild can not be Empty");
}
}
else
{
ContentValues values = new ContentValues();
values.put(DataProvider.Pname,name1);
values.put(DataProvider.Pphone,phone);
values.put(DataProvider.Paddress,address);
values.put(DataProvider.PCategory,"Debt");
values.put(DataProvider.Pamount,totamount);
String where = DataProvider.PID+"=?";
String[] whereargs = {String.valueOf(logid)};
int a = getContentResolver().update(DataProvider.ContentUri_Person,values,where,whereargs);
Toast.makeText(AddLog.this, String.valueOf(1)+"Value updated", Toast.LENGTH_SHORT).show();
startActivity(returnback);
finish();
}
}
#Override
public Loader<Cursor> onCreateLoader(final int id, Bundle args)
{
String[] Projection = new String[]{DataProvider.DID,DataProvider.Dname,DataProvider.DCategory,DataProvider.Damount,DataProvider.Ddate};
String selection = DataProvider.Per_In+"=?";
String[] selectionargs = new String[]{String.valueOf(logid)};
return new CursorLoader(this,DataProvider.ContentUri_Details,Projection,selection,selectionargs,null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
{
adapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader)
{
adapter.swapCursor(null);
}
}
Content Provider class:
public class DataProvider extends ContentProvider
{
static final String ProviderName = "com.example.mrudu.accounts.provider";
static final String URLPerson = "content://"+ProviderName+"/Person_Detail";
static final String URLDetails = "content://"+ProviderName+"/Details";
static final Uri ContentUri_Person = Uri.parse(URLPerson);
static final Uri ContentUri_Details = Uri.parse(URLDetails);
//Tables
private static String PTableName = "Person_Detail";
private static String DTableName = "Details";
public static long insertId = 0;
//Person_Detail Coloumns
public static String PID = "_id";
public static String Pname = "PName";
public static String Pphone = "PMobile";
public static String Paddress = "PCity";
public static String PCategory = "PCategory";
public static String Pamount = "PAmount";
//Details coloumn
public static String DID = "_id";
public static String Dname = "DName";
public static String Damount = "DAmount";
public static String Ddate = "DDate";
public static String DCategory = "DCategory";
public static String Per_In = "Per_In";
private static final int Person = 1;
private static final int Person_ID = 2;
private static final int Details = 3;
private static final int Details_Id = 4;
static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static
{
uriMatcher.addURI(ProviderName,PTableName,Person);
uriMatcher.addURI(ProviderName,PTableName+"/#",Person_ID);
uriMatcher.addURI(ProviderName,DTableName,Details);
uriMatcher.addURI(ProviderName,DTableName+"/#",Details_Id);
}
public static SQLiteDatabase sqLiteDatabase;
private static String Databasename = "Accounts";
private static int DatabaseVersion = 1;
private class DatabaseHelper extends SQLiteOpenHelper
{
public DatabaseHelper(Context context)
{
super(context, Databasename, null, DatabaseVersion);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase)
{
String Create_Person = " Create Table "+PTableName+"("+PID+" INTEGER PRIMARYKEY ,"+Pname+" TEXT ,"+Pphone+" TEXT ,"+Paddress+" TEXT ,"+PCategory+" TEXT ,"+Pamount+" REAL"+")";
String Create_Details = " Create Table "+DTableName+"("+DID+" INTEGER PRIMARYKEY ,"+Dname+" TEXT ,"+DCategory+" TEXT ,"+Damount+" REAl ,"+Ddate+" TEXT ,"+Per_In+" INTEGER )";
sqLiteDatabase.execSQL(Create_Person);
sqLiteDatabase.execSQL(Create_Details);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1)
{
sqLiteDatabase.execSQL("Drop TABLE if exists"+PTableName);
sqLiteDatabase.execSQL("Drop TABLE if exists"+DTableName);
onCreate(sqLiteDatabase);
}
}
#Override
public boolean onCreate()
{
Context context = getContext();
DatabaseHelper databaseHelper = new DatabaseHelper(context);
sqLiteDatabase = databaseHelper.getWritableDatabase();
return (sqLiteDatabase==null)?false:true;
}
#Override
public Uri insert(Uri uri, ContentValues values)
{
switch (uriMatcher.match(uri))
{
case Person:
long rowId = sqLiteDatabase.insert(PTableName,null,values);
insertId = rowId;
if (rowId>0)
{
Uri _uri = ContentUris.withAppendedId(ContentUri_Person,rowId);
getContext().getContentResolver().notifyChange(_uri,null);
return _uri;
}
break;
case Details:
long rowId1 = sqLiteDatabase.insert(DTableName,null,values);
if (rowId1>0)
{
Uri _uri = ContentUris.withAppendedId(ContentUri_Details,rowId1);
getContext().getContentResolver().notifyChange(_uri,null);
return _uri;
}
break;
}
return null;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)
{
SQLiteQueryBuilder sqLiteQueryBuilder = new SQLiteQueryBuilder();
switch (uriMatcher.match(uri))
{
case Person_ID:
sqLiteQueryBuilder.setTables(PTableName);
sqLiteQueryBuilder.appendWhere(PID+ "="+ uri.getPathSegments().get(1));
break;
case Person:
sqLiteQueryBuilder.setTables(PTableName);
break;
case Details_Id:
sqLiteQueryBuilder.setTables(DTableName);
sqLiteQueryBuilder.appendWhere(Per_In +"="+ uri.getPathSegments().get(1));
break;
case Details:
sqLiteQueryBuilder.setTables(DTableName);
break;
default:
throw new UnsupportedOperationException("Not yet implemented");
}
Cursor cursor = sqLiteQueryBuilder.query(sqLiteDatabase,projection,selection,selectionArgs,null,null,sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(),uri);
return cursor;
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs)
{
int count = 0;
switch (uriMatcher.match(uri))
{
case Person:
count = sqLiteDatabase.update(PTableName,values,selection,selectionArgs);
break;
case Person_ID:
count = sqLiteDatabase.update(PTableName,values,PID+" = "+uri.getPathSegments().get(1)+(!TextUtils.isEmpty(selection)?" AND (" + selection + ')':""),selectionArgs);
break;
case Details:
count = sqLiteDatabase.update(DTableName,values,selection,selectionArgs);
break;
case Details_Id:
count = sqLiteDatabase.update(DTableName,values,Per_In+" = "+uri.getPathSegments().get(1)+(!TextUtils.isEmpty(selection)?" AND (" + selection + ')':""),selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri );
}
getContext().getContentResolver().notifyChange(uri,null);
return count;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// Implement this to handle requests to delete one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Detils class:
public class Details
{
String name,date;
double amount;
public Details(String name, double amount, String date) {
this.name = name;
this.amount = amount;
this.date = date;
}
public Details() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public static Details from(Cursor cursor)
{
cursor.moveToFirst();
do {
Details details = new Details(cursor.getString(1),cursor.getDouble(3),cursor.getString(4));
return details;
}while (cursor.moveToNext());
}
}
Adapter class :
public class DetailsAdapter extends CursorRecyclerViewAdapter<DetailsAdapter.View_Holder>
{
public DetailsAdapter(Context context, Cursor cursor) {
super(context, cursor);
}
public static class View_Holder extends RecyclerView.ViewHolder
{
TextView mName,mAmount,mDate;
public View_Holder(View itemView)
{
super(itemView);
mName = (TextView)itemView.findViewById(R.id.DetailName);
mAmount = (TextView)itemView.findViewById(R.id.DetailAmount);
mDate = (TextView)itemView.findViewById(R.id.DetailDate);
}
}
#Override
public DetailsAdapter.View_Holder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.addloglistlayout,parent,false);
View_Holder viewHolder = new View_Holder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(DetailsAdapter.View_Holder viewHolder, Cursor cursor)
{
Details details = Details.from(cursor);
viewHolder.mName.setText(details.getName());
viewHolder.mAmount.setText(String.valueOf(details.getAmount()));
viewHolder.mDate.setText(details.getDate());
}
}
Cursor Recyclerview Adapter class:
public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private Context mContext;
private Cursor mCursor;
private boolean mDataValid;
private int mRowIdColumn;
private DataSetObserver mDataSetObserver;
public CursorRecyclerViewAdapter(Context context, Cursor cursor) {
mContext = context;
mCursor = cursor;
mDataValid = cursor != null;
mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1;
mDataSetObserver = new NotifyingDataSetObserver();
if (mCursor != null) {
mCursor.registerDataSetObserver(mDataSetObserver);
}
}
public Cursor getCursor() {
return mCursor;
}
#Override
public int getItemCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
}
return 0;
}
#Override
public long getItemId(int position) {
if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
return mCursor.getLong(mRowIdColumn);
}
return 0;
}
#Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(true);
}
public abstract void onBindViewHolder(VH viewHolder, Cursor cursor);
#Override
public void onBindViewHolder(VH viewHolder, int position) {
if (!mDataValid) {
throw new IllegalStateException("this should only be called when the cursor is valid");
}
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
onBindViewHolder(viewHolder, mCursor);
}
/**
* Change the underlying cursor to a new cursor. If there is an existing cursor it will be
* closed.
*/
public void changeCursor(Cursor cursor) {
Cursor old = swapCursor(cursor);
if (old != null) {
old.close();
}
}
/**
* Swap in a new Cursor, returning the old Cursor. Unlike
* {#link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
* closed.
*/
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
final Cursor oldCursor = mCursor;
if (oldCursor != null && mDataSetObserver != null) {
oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
mCursor = newCursor;
if (mCursor != null) {
if (mDataSetObserver != null) {
mCursor.registerDataSetObserver(mDataSetObserver);
}
mRowIdColumn = newCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
notifyDataSetChanged();
} else {
mRowIdColumn = -1;
mDataValid = false;
notifyDataSetChanged();
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
}
return oldCursor;
}
private class NotifyingDataSetObserver extends DataSetObserver {
#Override
public void onChanged() {
super.onChanged();
mDataValid = true;
notifyDataSetChanged();
}
#Override
public void onInvalidated() {
super.onInvalidated();
mDataValid = false;
notifyDataSetChanged();
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
}
}
}
Thank you
Probably from method in Details causing issue due to cursor.moveToFirst(); and do-while loop. change it as:
public static Details from(Cursor cursor)
{
Details details = new Details(cursor.getString(1),
cursor.getDouble(3),
cursor.getString(4));
return details;
}
I have checked your adapter and all, so you are already moving your cursor to particular position from Adapter, so you don't need to set it moveToFist, so just remove the line cursor.moveToFirst() from Details Class and check result.
My application relies on a core module of Android independent classes to carry out business logic. These objects need to be available to all parts of the app and also needs to maintain its state throughout the application.
I have been instantiating these objects in an Application subclass and using them throughout my activities and services. But when Android decides to kill my app to free up memory, those business logic objects are also killed and lose their state.
What is the best strategy for stateful business object models in an Android application?
Perfect solution for this is to use persistence storage. What I follow is bit complex but very useful.
It is divided in three parts :
SQLite Database
API Helper
Singleton Class ( Data Helper )
and following steps :
Retrieve all data from db to single instance classes.
Whenever I need to update it then update in class.
Dump it in database at some particular event. (like button click or back press).
By this way you have all of your data intact and easily available through out the app
Database : Not going to elaborate it. It can be any persistence storage like db or preference.
API Helper : Sample api helper class. It can be any thing depending on your storage.
public class AppsApi {
private static AppsApi appInstance;
private Context mContext;
public static AppsApi getInstance(Context context) {
if (appInstance == null)
appInstance = new AppsApi(context);
return appInstance;
}
public AppsApi(Context context) {
this.mContext = context;
}
public static String PROJECTION[];
static {
String[] arrayOfString = new String[5];
arrayOfString[0] = AppsTable.COLUMN_ID;
arrayOfString[1] = AppsTable.COLUMN_APP_NAME;
arrayOfString[2] = AppsTable.COLUMN_APP_PACKAGE_NAME;
arrayOfString[3] = AppsTable.COLUMN_APP_ACTIVITY_NAME;
arrayOfString[4] = AppsTable.COLUMN_IS_FROM_DASHBOARD;
PROJECTION = arrayOfString;
}
public int insertApp(ContentValues app) {
Uri uri = mContext.getContentResolver().insert(
DashDroidContentProvider.CONTENT_URI_APP, app);
System.out.println("APP Added URI :: " + uri);
return Integer.parseInt(uri.getLastPathSegment());
}
public Cursor getAllApps() {
return mContext.getContentResolver().query(
DashDroidContentProvider.CONTENT_URI_APP, AppsApi.PROJECTION,
null, null, null);
}
public Cursor getAllApp(boolean isFromDashBoard) {
int is = isFromDashBoard ? 1 : 0;
return mContext.getContentResolver().query(
DashDroidContentProvider.CONTENT_URI_APP, AppsApi.PROJECTION,
AppsTable.COLUMN_IS_FROM_DASHBOARD + " LIKE ?",
new String[] { is + "" }, null);
}
public void deleteApp(int id) {
mContext.getContentResolver().delete(
DashDroidContentProvider.CONTENT_URI_APP,
AppsTable.COLUMN_ID + " = ?", new String[] { id + "" });
}
public void deleteApp(String packageName) {
mContext.getContentResolver().delete(
DashDroidContentProvider.CONTENT_URI_APP,
AppsTable.COLUMN_APP_PACKAGE_NAME + " LIKE ?",
new String[] { packageName + "" });
}
public void updateApp(ContentValues app, int id) {
int uri = mContext.getContentResolver().update(
DashDroidContentProvider.CONTENT_URI_APP, app, "_id=?",
new String[] { id + "" });
System.out.println("App Updated URI ::" + uri);
}
public void clear() {
mContext.getContentResolver().delete(
DashDroidContentProvider.CONTENT_URI_APP, null, null);
}
public int count() {
return ((Cursor) mContext.getContentResolver().query(
DashDroidContentProvider.CONTENT_URI_APP,
new String[] { AppsTable.COLUMN_ID }, null, null, null))
.getCount();
}
public Cursor filterApp(String selection, String[] selectionArgs) {
return mContext.getContentResolver().query(
DashDroidContentProvider.CONTENT_URI_APP, AppsApi.PROJECTION,
selection, selectionArgs, null);
}
public int insertBulkApps(ContentValues[] apps) {
int noOfRecordInserted = mContext.getContentResolver().bulkInsert(
DashDroidContentProvider.CONTENT_URI_APP, apps);
System.out.println("Inserted Record Count :: " + noOfRecordInserted);
return noOfRecordInserted;
}
}
Data Helper : It is a single instance class. Provides you with data through out the app. It is huge but simple.
public class AppsHelper {
public static final int TYPE_SAVE = 0;
public static final int TYPE_GET = 1;
public static final int TYPE_UPDATE = 2;
private AppsData[] appsDashBoard;
private AppsData[] appsMoreApps;
private AppsApi appsProvider;
private OnDataBaseUpdateListener mListener;
private static AppsHelper mHelper;
public AppsHelper(Context context) {
appsProvider = AppsApi.getInstance(context);
initData();
if (appsProvider.count() == 0) {
new saveDataTask().execute();
} else {
updateAppsFromDatabase();
}
}
public static AppsHelper getInstance(Context context) {
if (mHelper == null)
mHelper = new AppsHelper(context);
return mHelper;
}
private void initData() {
appsDashBoard = new AppsData[DashDroidConstants.NO_OF_DASH_BOARD_APPS];
appsMoreApps = new AppsData[DashDroidConstants.NO_OF_MORE_APPS];
for (int i = 0; i < appsDashBoard.length; i++) {
appsDashBoard[i] = new AppsData(i, "null", "null", "null");
}
for (int i = appsDashBoard.length; i < (appsMoreApps.length + appsDashBoard.length); i++) {
appsMoreApps[i - appsDashBoard.length] = new AppsData(i, "null",
"null", "null");
}
}
public void updateMoreApp(String appName, String activityName,
String appPackageName, int index) {
appsMoreApps[index].setData(appName, activityName, appPackageName);
new updateDataTask(false, index).execute();
}
public void updateMoreApp(String appName, String activityName,
String appPackageName, int index, OnDataBaseUpdateListener listener) {
appsMoreApps[index].setData(appName, activityName, appPackageName);
this.mListener = listener;
new updateDataTask(false, index).execute();
}
public void updateDashBoardApp(String appName, String activityName,
String appPackageName, int index) {
appsDashBoard[index].setData(appName, activityName, appPackageName);
new updateDataTask(true, index).execute();
}
public void updateDashBoardApp(String appName, String activityName,
String appPackageName, int index, OnDataBaseUpdateListener listener) {
appsDashBoard[index].setData(appName, activityName, appPackageName);
this.mListener = listener;
new updateDataTask(true, index).execute();
}
public void updateAppsFromDatabase() {
new getDataTask().execute();
}
public AppsData[] getDashBoardApps() {
return appsDashBoard;
}
public AppsData[] getMoreApps() {
return appsMoreApps;
}
private void updateAppInDatabase(boolean isDashBoardApp, int index) {
ContentValues cv = new ContentValues();
cv = new ContentValues();
if (isDashBoardApp) {
cv.put(AppsTable.COLUMN_APP_PACKAGE_NAME,
appsDashBoard[index].getPackageName());
cv.put(AppsTable.COLUMN_APP_ACTIVITY_NAME,
appsDashBoard[index].getActivityName());
cv.put(AppsTable.COLUMN_APP_NAME, appsDashBoard[index].getAppName());
} else {
cv.put(AppsTable.COLUMN_APP_PACKAGE_NAME,
appsMoreApps[index].getPackageName());
cv.put(AppsTable.COLUMN_APP_ACTIVITY_NAME,
appsMoreApps[index].getActivityName());
cv.put(AppsTable.COLUMN_APP_NAME, appsMoreApps[index].getAppName());
}
int dbIndex = isDashBoardApp ? index : index + appsDashBoard.length;
appsProvider.updateApp(cv, dbIndex);
}
private int saveDataInDatabase() {
ContentValues[] cv = new ContentValues[appsDashBoard.length
+ appsMoreApps.length];
for (int i = 0; i < appsDashBoard.length; i++) {
cv[i] = new ContentValues();
cv[i].put(AppsTable.COLUMN_ID, appsDashBoard[i].getId());
cv[i].put(AppsTable.COLUMN_APP_PACKAGE_NAME,
appsDashBoard[i].getPackageName());
cv[i].put(AppsTable.COLUMN_APP_ACTIVITY_NAME,
appsDashBoard[i].getActivityName());
cv[i].put(AppsTable.COLUMN_APP_NAME, appsDashBoard[i].getAppName());
cv[i].put(AppsTable.COLUMN_IS_FROM_DASHBOARD, "1");
}
for (int i = appsDashBoard.length; i < (appsMoreApps.length + appsDashBoard.length); i++) {
cv[i] = new ContentValues();
cv[i].put(AppsTable.COLUMN_ID, appsMoreApps[i
- appsDashBoard.length].getId());
cv[i].put(AppsTable.COLUMN_APP_PACKAGE_NAME, appsMoreApps[i
- appsDashBoard.length].getPackageName());
cv[i].put(AppsTable.COLUMN_APP_ACTIVITY_NAME, appsMoreApps[i
- appsDashBoard.length].getActivityName());
cv[i].put(AppsTable.COLUMN_APP_NAME, appsMoreApps[i
- appsDashBoard.length].getAppName());
cv[i].put(AppsTable.COLUMN_IS_FROM_DASHBOARD, "0");
}
return appsProvider.insertBulkApps(cv);
}
private void getDataFromDatabase() {
Cursor appCursor = appsProvider.getAllApps();
appCursor.moveToFirst();
for (int i = 0; i < appsDashBoard.length; i++) {
appsDashBoard[i]
.setData(
appCursor.getString(appCursor
.getColumnIndex(AppsTable.COLUMN_APP_NAME)),
appCursor.getString(appCursor
.getColumnIndex(AppsTable.COLUMN_APP_ACTIVITY_NAME)),
appCursor.getString(appCursor
.getColumnIndex(AppsTable.COLUMN_APP_PACKAGE_NAME)));
appCursor.moveToNext();
}
for (int i = 0; i < appsMoreApps.length; i++) {
appsMoreApps[i]
.setData(
appCursor.getString(appCursor
.getColumnIndex(AppsTable.COLUMN_APP_NAME)),
appCursor.getString(appCursor
.getColumnIndex(AppsTable.COLUMN_APP_ACTIVITY_NAME)),
appCursor.getString(appCursor
.getColumnIndex(AppsTable.COLUMN_APP_PACKAGE_NAME)));
appCursor.moveToNext();
}
}
private class saveDataTask extends AsyncTask<Void, Void, Integer> {
#Override
protected Integer doInBackground(Void... params) {
return saveDataInDatabase();
}
#Override
protected void onPostExecute(Integer result) {
if (mListener != null)
mListener.onDataUpdate(TYPE_SAVE);
super.onPostExecute(result);
}
}
private class getDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
getDataFromDatabase();
return null;
}
#Override
protected void onPostExecute(Void result) {
if (mListener != null)
mListener.onDataUpdate(TYPE_GET);
super.onPostExecute(result);
}
}
private class updateDataTask extends AsyncTask<Void, Void, Void> {
boolean isFromDashBoard;
int index;
public updateDataTask(boolean isFromDashBoard, int index) {
this.isFromDashBoard = isFromDashBoard;
this.index = index;
}
#Override
protected Void doInBackground(Void... params) {
updateAppInDatabase(isFromDashBoard, index);
return null;
}
#Override
protected void onPostExecute(Void result) {
if (mListener != null)
mListener.onDataUpdate(TYPE_UPDATE);
super.onPostExecute(result);
}
}
public static class AppsData {
int id;
String appName;
String activityName;
String packageName;
public AppsData(int id, String appName, String activityName,
String packageName) {
this.id = id;
this.appName = appName;
this.activityName = activityName;
this.packageName = packageName;
}
public void setData(String appName, String activityName,
String packageName) {
this.appName = appName;
this.activityName = activityName;
this.packageName = packageName;
}
public int getId() {
return id;
}
public String getAppName() {
return appName;
}
public String getPackageName() {
return packageName;
}
public String getActivityName() {
return activityName;
}
}
public interface OnDataBaseUpdateListener {
public void onDataUpdate(int updateType);
}
}
It helps you in creating a more structured code and always available data, just need to call AppsHelper.getInstance(context) and boom!!!. :)
if you want to save them when user closes the application , you must save them in shared preferences or database or in a file in phone memory!
and for inside application, you can simply define them in a class that extends from Serializable or Parcelable and pass them between activities/fragments/etc
I need to work with SQLite in Android.
So, do I have to download any SQLite Administration (like MySql) or it is already in device memory?
All you need is already installed. To inspect the database during development you can use the sqlite3 tool. It is installed in the emulator.
You Don't need to download anything.its already there.
You don't have to do anything besides using the built-in tools in the Android SDK. For more information please have a look at the sqlite documentation
Basically you can use Java code to create databases, insert records into them, modify them etc.
If you want a graphical way to work on the databases, simply use Eclipse's DDMS View to navigate into your app's databases folder. From there, download the database on your computer and open it with one of the many sqlite applications available.
------------------------------------------------------------------------
Sqlite
----------------------------------------------------------------------
// instance varieable
Button btn_insert,btn_update,btn_show,btn_delete,btn_search;
EditText edit_no,edit_name,edit_mark;
Cursor c;
Context context=this;
SQLiteDatabase db;
StringBuffer sb;
init
edit_no= (EditText) findViewById(R.id.edit_no);
edit_name= (EditText) findViewById(R.id.edit_name);
edit_mark= (EditText) findViewById(R.id.edit_mark);
btn_insert= (Button) findViewById(R.id.btn_insert);
btn_update= (Button) findViewById(R.id.btn_update);
btn_show= (Button) findViewById(R.id.btn_show);
btn_delete= (Button) findViewById(R.id.btn_delete);
btn_search= (Button) findViewById(R.id.btn_search);
db=openOrCreateDatabase("topstech",context.MODE_PRIVATE,null);
db.execSQL("create table if not exists register(no varchar2(20),name varchar2(20),mark varchar2(20))");
btn_insert.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (edit_no.getText().toString().trim().length() == 0) {
edit_no.setError("Enter Your No");
return;
} else if (edit_name.getText().toString().trim().length() == 0) {
edit_name.setError("Enter Your Name");
return;
} else if (edit_mark.getText().toString().trim().length() == 0) {
edit_mark.setError("Enter Your Mark");
return;
} else {
db.execSQL("insert into register values('" + edit_no.getText().toString() + "','" + edit_name.getText().toString() + "','" + edit_mark.getText().toString() + "')");
Toast.makeText(context, "Record Successfully Inserted...", Toast.LENGTH_SHORT).show();
Clear();
}
}
});
btn_show.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
c=db.rawQuery("select * from register",null);
sb=new StringBuffer();
if(c.moveToFirst())
{
do
{
sb.append(c.getString(c.getColumnIndex("no"))+"\t");
sb.append(c.getString(c.getColumnIndex("name"))+"\t");
sb.append(c.getString(c.getColumnIndex("mark"))+"\n");
}while (c.moveToNext());
Toast.makeText(MainActivity.this, ""+sb, Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(MainActivity.this, "Empty Record...", Toast.LENGTH_SHORT).show();
}
}
});
btn_delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
if (edit_no.getText().toString().trim().length() == 0)
{
edit_no.setError("Enter Your No");
return;
}
else
{
c=db.rawQuery("select * from register where no='"+edit_no.getText().toString()+"'",null);
sb=new StringBuffer();
if(c.moveToFirst())
{
do
{
db.execSQL("delete from register where no='"+edit_no.getText().toString()+"'");
Toast.makeText(MainActivity.this, "1 Record Is Deleted...", Toast.LENGTH_SHORT).show();
Clear();
}while (c.moveToNext());
}
else
{
Toast.makeText(MainActivity.this, "Record Not Found...", Toast.LENGTH_SHORT).show();
Clear();
}
}
}
});
btn_search.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (edit_no.getText().toString().trim().length() == 0)
{
edit_no.setError("Enter Your No");
return;
}
else
{
c=db.rawQuery("select * from register where no='"+edit_no.getText().toString()+"'",null);
sb=new StringBuffer();
if(c.moveToFirst())
{
do
{
edit_name.setText(c.getString(c.getColumnIndex("name")));
edit_mark.setText(c.getString(c.getColumnIndex("mark")));
}while (c.moveToNext());
}
else
{
Toast.makeText(MainActivity.this, "Record Not Found...", Toast.LENGTH_SHORT).show();
Clear();
}
}
}
});
btn_update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
if (edit_no.getText().toString().trim().length() == 0)
{
edit_no.setError("Enter Your No");
return;
}
else
{
c=db.rawQuery("select * from register where no='"+edit_no.getText().toString()+"'",null);
sb=new StringBuffer();
if(c.moveToFirst())
{
do
{
if (edit_name.getText().toString().trim().length() == 0)
{
edit_name.setError("Enter Your Name");
return;
}
else if (edit_mark.getText().toString().trim().length() == 0)
{
edit_mark.setError("Enter Your Mark");
return;
}
else
{
//Syntex:-
// db.execSQL("update tablename set col_name='" +edit_name+"' where no='" + no+ "'");
db.execSQL("update register set name='"+edit_name.getText().toString()+"',mark='"+edit_mark.getText().toString()+"' where no='"+edit_no.getText().toString()+"'");
Toast.makeText(MainActivity.this, "1 Record Is Updated...", Toast.LENGTH_SHORT).show();
Clear();
}
}while (c.moveToNext());
}
else
{
Toast.makeText(MainActivity.this, "Record Not Found...", Toast.LENGTH_SHORT).show();
Clear();
}
}
}
});
}
-----------------------------------------
Upload Image ANd Fetch Device Contact JSON ARRAY
------------------------------------------
Upload Image Using Retrofit
#Multipart
#POST("addDocument")
Call<AddDocumentsResponse> doAddDocuments(#Header("Authorization") String token, #Part List<MultipartBody.Part> files, #PartMap Map<String, RequestBody> map);
private void uploadDocuments() {
if (Utility.checkInternetConnection(InsurenceActivity.this)) {
ArrayList<MultipartBody.Part> multipart = new ArrayList<>();
Map<String, RequestBody> map = new HashMap<>();
map.put("document_type", RequestBody.create(MediaType.parse("text/plain"), "insurance"));
map.put("expiry_date", RequestBody.create(MediaType.parse("text/plain"), str_select_date));
map.put("photo_id_type", RequestBody.create(MediaType.parse("text/plain"), ""));
multipart.add(Utility.prepareFilePart(InsurenceActivity.this, "document_file", picturePath));
messageUtil.showProgressDialog(InsurenceActivity.this);
Call<AddDocumentsResponse> registerResponseCall = ApiClient.getApiInterface().doAddDocuments(fastSave.getString(Constant.ACCESS_TOKEN), multipart, map);
Log.d("request","---- Request -----"+map.toString());
registerResponseCall.enqueue(new Callback<AddDocumentsResponse>() {
#Override
public void onResponse(Call<AddDocumentsResponse> call, Response<AddDocumentsResponse> response) {
if (response.code() == 200) {
if (response.body().getStatus().equalsIgnoreCase("fail"))
{
messageUtil.hideProgressDialog();
messageUtil.showErrorToast(response.body().getMessage());
return;
}
if (response.body().getStatus().equalsIgnoreCase("success"))
{
Log.d("response","---- Respons -----"+new Gson().toJson(response));
messageUtil.hideProgressDialog();
messageUtil.showSuccessToast(response.body().getMessage());
str_select_date = str_select_date;
picturePath = null;
Log.d("TAG", "success:............... " + new Gson().toJson(response));
finish();
}
}
}
#Override
public void onFailure(Call<AddDocumentsResponse> call, Throwable t) {
messageUtil.hideProgressDialog();
messageUtil.showErrorToast("Something went wrong");
}
});
} else {
Toast.makeText(this, R.string.no_internet_connection, Toast.LENGTH_SHORT).show();
}
}
public static MultipartBody.Part prepareFilePart(Context context, String partName, String filePath) {
if(filePath!=null) {
File file = new File(filePath);
Log.d("TAG", "prepareFilePart: " + filePath);
// RequestBody requestBody = RequestBody.create(MediaType.parse(getContentResolver().getType(Uri.fromFile(file))), file);
// Libaray Required
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
// Multipart Camera and Gallery
// RequestBody requestBody = RequestBody.create(MediaType.parse(context.getContentResolver().getType(FileProvider.getUriForFile(context, "com.", file))), file);
return MultipartBody.Part.createFormData(partName, file.getName(), requestBody);
}
else {
return MultipartBody.Part.createFormData(partName,"");
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
Uri resultUri = result.getUri();
ll_profile_file.setVisibility(View.GONE);
img_photo_file.setVisibility(VISIBLE);
img_photo_file.setImageURI(resultUri);
picturePath = resultUri.getPath();
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
}
}
}
Fetch Device Contact Fast
ArrayList<Contact> listContacts;
listContacts = new ContactFetcher(this).fetchAll();
public class ContactPhone {
public String number;
public String type;
public ContactPhone(String number, String type) {
this.number = number;
this.type = type;
}
}
public class ContactFetcher {
private final Context context;
public ContactFetcher(Context c) {
this.context = c;
}
public ArrayList<Contact> fetchAll() {
String[] projectionFields = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
};
ArrayList<Contact> listContacts = new ArrayList<>();
CursorLoader cursorLoader = new CursorLoader(context,
ContactsContract.Contacts.CONTENT_URI,
projectionFields, // the columns to retrieve
null, // the selection criteria (none)
null, // the selection args (none)
null // the sort order (default)
);
Cursor c = cursorLoader.loadInBackground();
final Map<String, Contact> contactsMap = new HashMap<>(c.getCount());
if (c.moveToFirst()) {
int idIndex = c.getColumnIndex(ContactsContract.Contacts._ID);
int nameIndex = c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
do {
String contactId = c.getString(idIndex);
String contactDisplayName = c.getString(nameIndex);
Contact contact = new Contact(contactId, contactDisplayName);
contactsMap.put(contactId, contact);
listContacts.add(contact);
} while (c.moveToNext());
}
c.close();
matchContactNumbers(contactsMap);
matchContactEmails(contactsMap);
return listContacts;
}
public void matchContactNumbers(Map<String, Contact> contactsMap) {
// Get numbers
final String[] numberProjection = new String[]{
Phone.NUMBER,
Phone.TYPE,
Phone.CONTACT_ID,
};
Cursor phone = new CursorLoader(context,
Phone.CONTENT_URI,
numberProjection,
null,
null,
null).loadInBackground();
if (phone.moveToFirst()) {
final int contactNumberColumnIndex = phone.getColumnIndex(Phone.NUMBER);
final int contactTypeColumnIndex = phone.getColumnIndex(Phone.TYPE);
final int contactIdColumnIndex = phone.getColumnIndex(Phone.CONTACT_ID);
while (!phone.isAfterLast()) {
final String number = phone.getString(contactNumberColumnIndex);
final String contactId = phone.getString(contactIdColumnIndex);
Contact contact = contactsMap.get(contactId);
if (contact == null) {
continue;
}
final int type = phone.getInt(contactTypeColumnIndex);
String customLabel = "Custom";
CharSequence phoneType = Phone.getTypeLabel(context.getResources(), type, customLabel);
contact.addNumber(number, phoneType.toString());
phone.moveToNext();
}
}
phone.close();
}
public void matchContactEmails(Map<String, Contact> contactsMap) {
// Get email
final String[] emailProjection = new String[]{
Email.DATA,
Email.TYPE,
Email.CONTACT_ID,
};
Cursor email = new CursorLoader(context,
Email.CONTENT_URI,
emailProjection,
null,
null,
null).loadInBackground();
if (email.moveToFirst()) {
final int contactEmailColumnIndex = email.getColumnIndex(Email.DATA);
final int contactTypeColumnIndex = email.getColumnIndex(Email.TYPE);
final int contactIdColumnsIndex = email.getColumnIndex(Email.CONTACT_ID);
while (!email.isAfterLast()) {
final String address = email.getString(contactEmailColumnIndex);
final String contactId = email.getString(contactIdColumnsIndex);
final int type = email.getInt(contactTypeColumnIndex);
String customLabel = "Custom";
Contact contact = contactsMap.get(contactId);
if (contact == null) {
continue;
}
CharSequence emailType = Email.getTypeLabel(context.getResources(), type, customLabel);
contact.addEmail(address, emailType.toString());
email.moveToNext();
}
}
email.close();
}
public class ContactEmail {
public String address;
public String type;
public ContactEmail(String address, String type) {
this.address = address;
this.type = type;
}
}
public class Contact {
public String id;
public String name;
public ArrayList<ContactEmail> emails;
public ArrayList<ContactPhone> numbers;
public Contact(String id, String name) {
this.id = id;
this.name = name;
this.emails = new ArrayList<ContactEmail>();
this.numbers = new ArrayList<ContactPhone>();
}
#Override
public String toString() {
String result = name;
if (numbers.size() > 0) {
ContactPhone number = numbers.get(0);
result += " (" + number.number + " - " + number.type + ")";
}
if (emails.size() > 0) {
ContactEmail email = emails.get(0);
result += " [" + email.address + " - " + email.type + "]";
}
return result;
}
public void addEmail(String address, String type) {
emails.add(new ContactEmail(address, type));
}
public void addNumber(String number, String type) {
numbers.add(new ContactPhone(number, type));
}
JSON ARRAY
Model model = new Model();
ArrayList<Model> contacts_arraylist=new ArrayList<>();
for (int i = 0; i < 50; i++)
{
model.setName("sanjay"+i);
model.setEmails("sanjay#gmail.com"+i);
model.setNumbers("89689527"+i);
contacts_arraylist.add(model);
}
JSONArray personarray=new JSONArray();
for (int j = 0; j < contacts_arraylist.size(); j++)
{
JSONObject person1 = new JSONObject();
try {
if(contacts_arraylist.get(j).getName()!=null)
{
person1.put("name", contacts_arraylist.get(j).getName());
}
else {
person1.put("name","");
}
if(contacts_arraylist.get(j).getEmails().length()>0)
{
person1.put("email", contacts_arraylist.get(j).getEmails());
}
else {
person1.put("email", "");
}
if(contacts_arraylist.get(j).getNumbers().length()>0)
{
person1.put("mobile_number", contacts_arraylist.get(j).getNumbers());
}
else {
person1.put("mobile_number", "");
}
personarray.put(person1);
} catch (JSONException e)
{
e.printStackTrace();
}
}
txt_array.setText(personarray.toString());
System.out.println("jsonString:---- " + personarray.toString());
}
How can I get all the names of the contacts in my Android and put them into array of strings?
Try this too,
private void getContactList() {
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if ((cur != null ? cur.getCount() : 0) > 0) {
while (cur != null && cur.moveToNext()) {
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
if (cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
String phoneNo = pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.i(TAG, "Name: " + name);
Log.i(TAG, "Phone Number: " + phoneNo);
}
pCur.close();
}
}
}
if(cur!=null){
cur.close();
}
}
If you need more reference means refer this link Read ContactList
Get contacts info , photo contacts , photo uri and convert to Class model
1). Sample for Class model :
public class ContactModel {
public String id;
public String name;
public String mobileNumber;
public Bitmap photo;
public Uri photoURI;
}
2). get Contacts and convert to Model
public List<ContactModel> getContacts(Context ctx) {
List<ContactModel> list = new ArrayList<>();
ContentResolver contentResolver = ctx.getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
if (cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor cursorInfo = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);
InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(ctx.getContentResolver(),
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, new Long(id)));
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, new Long(id));
Uri pURI = Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Bitmap photo = null;
if (inputStream != null) {
photo = BitmapFactory.decodeStream(inputStream);
}
while (cursorInfo.moveToNext()) {
ContactModel info = new ContactModel();
info.id = id;
info.name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
info.mobileNumber = cursorInfo.getString(cursorInfo.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
info.photo = photo;
info.photoURI= pURI;
list.add(info);
}
cursorInfo.close();
}
}
cursor.close();
}
return list;
}
public class MyActivity extends Activity
implements LoaderManager.LoaderCallbacks<Cursor> {
private static final int CONTACTS_LOADER_ID = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(CONTACTS_LOADER_ID,
null,
this);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created.
if (id == CONTACTS_LOADER_ID) {
return contactsLoader();
}
return null;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
//The framework will take care of closing the
// old cursor once we return.
List<String> contacts = contactsFromCursor(cursor);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
}
private Loader<Cursor> contactsLoader() {
Uri contactsUri = ContactsContract.Contacts.CONTENT_URI; // The content URI of the phone contacts
String[] projection = { // The columns to return for each row
ContactsContract.Contacts.DISPLAY_NAME
} ;
String selection = null; //Selection criteria
String[] selectionArgs = {}; //Selection criteria
String sortOrder = null; //The sort order for the returned rows
return new CursorLoader(
getApplicationContext(),
contactsUri,
projection,
selection,
selectionArgs,
sortOrder);
}
private List<String> contactsFromCursor(Cursor cursor) {
List<String> contacts = new ArrayList<String>();
if (cursor.getCount() > 0) {
cursor.moveToFirst();
do {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
contacts.add(name);
} while (cursor.moveToNext());
}
return contacts;
}
}
and do not forget
<uses-permission android:name="android.permission.READ_CONTACTS" />
Get all contacts in less than a second and without any load in your activity.
Follow my steps works like a charm.
ArrayList<Contact> contactList = new ArrayList<>();
private static final String[] PROJECTION = new String[]{
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
private void getContactList() {
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
if (cursor != null) {
HashSet<String> mobileNoSet = new HashSet<String>();
try {
final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String name, number;
while (cursor.moveToNext()) {
name = cursor.getString(nameIndex);
number = cursor.getString(numberIndex);
number = number.replace(" ", "");
if (!mobileNoSet.contains(number)) {
contactList.add(new Contact(name, number));
mobileNoSet.add(number);
Log.d("hvy", "onCreaterrView Phone Number: name = " + name
+ " No = " + number);
}
}
} finally {
cursor.close();
}
}
}
Contacts
public class Contact {
public String name;
public String phoneNumber;
public Contact() {
}
public Contact(String name, String phoneNumber ) {
this.name = name;
this.phoneNumber = phoneNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
Benefits
less than a second
without load
ascending order
without duplicate contacts
Improving on the answer of #Adiii - It Will Cleanup The Phone Number and Remove All Duplicates
Declare a Global Variable
// Hash Maps
Map<String, String> namePhoneMap = new HashMap<String, String>();
Then Use The Function Below
private void getPhoneNumbers() {
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
// Loop Through All The Numbers
while (phones.moveToNext()) {
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// Cleanup the phone number
phoneNumber = phoneNumber.replaceAll("[()\\s-]+", "");
// Enter Into Hash Map
namePhoneMap.put(phoneNumber, name);
}
// Get The Contents of Hash Map in Log
for (Map.Entry<String, String> entry : namePhoneMap.entrySet()) {
String key = entry.getKey();
Log.d(TAG, "Phone :" + key);
String value = entry.getValue();
Log.d(TAG, "Name :" + value);
}
phones.close();
}
Remember in the above example the key is phone number and value is a name so read your contents like 998xxxxx282->Mahatma Gandhi instead of Mahatma Gandhi->998xxxxx282
Cursor contacts = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
String aNameFromContacts[] = new String[contacts.getCount()];
String aNumberFromContacts[] = new String[contacts.getCount()];
int i = 0;
int nameFieldColumnIndex = contacts.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
int numberFieldColumnIndex = contacts.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
while(contacts.moveToNext()) {
String contactName = contacts.getString(nameFieldColumnIndex);
aNameFromContacts[i] = contactName ;
String number = contacts.getString(numberFieldColumnIndex);
aNumberFromContacts[i] = number ;
i++;
}
contacts.close();
The result will be aNameFromContacts array full of contacts. Also ensure that you have added
<uses-permission android:name="android.permission.READ_CONTACTS" />
in main.xml
This is the Method to get contact list Name and Number
private void getAllContacts() {
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Cursor phoneCursor = contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id},
null);
if (phoneCursor != null) {
if (phoneCursor.moveToNext()) {
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
//At here You can add phoneNUmber and Name to you listView ,ModelClass,Recyclerview
phoneCursor.close();
}
}
}
}
}
}
//GET CONTACTLIST WITH ALL FIELD...
public ArrayList < ContactItem > getReadContacts() {
ArrayList < ContactItem > contactList = new ArrayList < > ();
ContentResolver cr = getContentResolver();
Cursor mainCursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (mainCursor != null) {
while (mainCursor.moveToNext()) {
ContactItem contactItem = new ContactItem();
String id = mainCursor.getString(mainCursor.getColumnIndex(ContactsContract.Contacts._ID));
String displayName = mainCursor.getString(mainCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
Uri displayPhotoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
//ADD NAME AND CONTACT PHOTO DATA...
contactItem.setDisplayName(displayName);
contactItem.setPhotoUrl(displayPhotoUri.toString());
if (Integer.parseInt(mainCursor.getString(mainCursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
//ADD PHONE DATA...
ArrayList < PhoneContact > arrayListPhone = new ArrayList < > ();
Cursor phoneCursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] {
id
}, null);
if (phoneCursor != null) {
while (phoneCursor.moveToNext()) {
PhoneContact phoneContact = new PhoneContact();
String phone = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
phoneContact.setPhone(phone);
arrayListPhone.add(phoneContact);
}
}
if (phoneCursor != null) {
phoneCursor.close();
}
contactItem.setArrayListPhone(arrayListPhone);
//ADD E-MAIL DATA...
ArrayList < EmailContact > arrayListEmail = new ArrayList < > ();
Cursor emailCursor = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[] {
id
}, null);
if (emailCursor != null) {
while (emailCursor.moveToNext()) {
EmailContact emailContact = new EmailContact();
String email = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
emailContact.setEmail(email);
arrayListEmail.add(emailContact);
}
}
if (emailCursor != null) {
emailCursor.close();
}
contactItem.setArrayListEmail(arrayListEmail);
//ADD ADDRESS DATA...
ArrayList < PostalAddress > arrayListAddress = new ArrayList < > ();
Cursor addrCursor = getContentResolver().query(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI, null, ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + " = ?", new String[] {
id
}, null);
if (addrCursor != null) {
while (addrCursor.moveToNext()) {
PostalAddress postalAddress = new PostalAddress();
String city = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
String state = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
String country = addrCursor.getString(addrCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
postalAddress.setCity(city);
postalAddress.setState(state);
postalAddress.setCountry(country);
arrayListAddress.add(postalAddress);
}
}
if (addrCursor != null) {
addrCursor.close();
}
contactItem.setArrayListAddress(arrayListAddress);
}
contactList.add(contactItem);
}
}
if (mainCursor != null) {
mainCursor.close();
}
return contactList;
}
//MODEL...
public class ContactItem {
private String displayName;
private String photoUrl;
private ArrayList<PhoneContact> arrayListPhone = new ArrayList<>();
private ArrayList<EmailContact> arrayListEmail = new ArrayList<>();
private ArrayList<PostalAddress> arrayListAddress = new ArrayList<>();
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getPhotoUrl() {
return photoUrl;
}
public void setPhotoUrl(String photoUrl) {
this.photoUrl = photoUrl;
}
public ArrayList<PhoneContact> getArrayListPhone() {
return arrayListPhone;
}
public void setArrayListPhone(ArrayList<PhoneContact> arrayListPhone) {
this.arrayListPhone = arrayListPhone;
}
public ArrayList<EmailContact> getArrayListEmail() {
return arrayListEmail;
}
public void setArrayListEmail(ArrayList<EmailContact> arrayListEmail) {
this.arrayListEmail = arrayListEmail;
}
public ArrayList<PostalAddress> getArrayListAddress() {
return arrayListAddress;
}
public void setArrayListAddress(ArrayList<PostalAddress> arrayListAddress) {
this.arrayListAddress = arrayListAddress;
}
}
public class EmailContact
{
private String email = "";
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public class PhoneContact
{
private String phone="";
public String getPhone()
{
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
public class PostalAddress
{
private String city="";
private String state="";
private String country="";
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
//In Kotlin
private fun showContacts() {
// Check the SDK version and whether the permission is already granted or not.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(
requireContext(),
Manifest.permission.READ_CONTACTS
) != PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(Manifest.permission.READ_CONTACTS),
1001
)
//After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
} else {
// Android version is lesser than 6.0 or the permission is already granted.
getContactList()
}
}
private fun getContactList() {
val cr: ContentResolver = requireActivity().contentResolver
val cur: Cursor? = cr.query(
ContactsContract.Contacts.CONTENT_URI,
null, null, null, null
)
if ((if (cur != null) cur.getCount() else 0) > 0) {
while (cur != null && cur.moveToNext()) {
val id: String = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID)
)
val name: String = cur.getString(
cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME
)
)
if (cur.getInt(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
val pCur: Cursor? = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
arrayOf(id),
null
)
pCur?.let {
while (pCur.moveToNext()) {
val phoneNo: String = pCur.getString(
pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER
)
)
Timber.i("Name: $name")
Timber.i("Phone Number: $phoneNo")
}
pCur.close()
}
}
}
}
if (cur != null) {
cur.close()
}
}
I am using this method, and it is working perfectly.
It gets fav, picture, name, number etc. (All the details of the contact). And also it is not repetitive.
List
private static List<FavContact> contactList = new ArrayList<>();
Method to get contacts
#SuppressLint("Range")
public static void readContacts(Context context) {
if (context == null)
return;
ContentResolver contentResolver = context.getContentResolver();
if (contentResolver == null)
return;
String[] fieldListProjection = {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.PHOTO_URI
,ContactsContract.Contacts.STARRED
};
String sort = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " ASC";
Cursor phones = contentResolver
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI
, fieldListProjection, null, null, sort);
HashSet<String> normalizedNumbersAlreadyFound = new HashSet<>();
if (phones != null && phones.getCount() > 0) {
while (phones.moveToNext()) {
String normalizedNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
if (Integer.parseInt(phones.getString(phones.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
if (normalizedNumbersAlreadyFound.add(normalizedNumber)) {
int id = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
int fav = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.STARRED));
boolean isFav;
isFav= fav == 1;
String uri = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
if(uri!=null){
contactList.add(new FavContact(id,isFav,uri,name,phoneNumber));
}
else{
contactList.add(new FavContact(id,isFav,name,phoneNumber));
}
}
}
}
phones.close();
}
}
Model Class
public class FavContact{
private int id;
private boolean isFavorite;
private String image;
private String name;
private String number;
public FavContact(int id,boolean isFavorite, String image, String name, String number){
this.id=id;
this.isFavorite = isFavorite;
this.image = image;
this.name = name;
this.number = number;
}
public FavContact(int id,boolean isFavorite, String name, String number){
this.id=id;
this.isFavorite = isFavorite;
this.name = name;
this.number = number;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isFavorite() {
return isFavorite;
}
public void setFavorite(boolean favorite) {
isFavorite = favorite;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
Adapter
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.MyViewHolder> implements Filterable {
private final Context context;
private final List<FavContact> contactList;
private final List<FavContact> filterList;
private final OnMyOwnClickListener onMyOwnClickListener;
private final FavContactRepo favContactRepo;
public ContactAdapter(Application application,Context context, List<FavContact> contactList, OnMyOwnClickListener onMyOwnClickListener) {
this.context = context;
this.contactList = contactList;
this.onMyOwnClickListener = onMyOwnClickListener;
filterList = new ArrayList<>(contactList);
favContactRepo = new FavContactRepo(application);
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(context);
#SuppressLint("InflateParams") final View view = inflater.inflate(R.layout.design_fav_contact, null, false);
return new MyViewHolder(view,onMyOwnClickListener);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
final FavContact obj = contactList.get(position);
holder.tv_contact_name.setText(obj.getName());
holder.tv_contact_number.setText(obj.getNumber());
if(obj.getImage()==null){
Picasso.get().load(R.drawable.ic_circle_fav_no_dp).fit().into(holder.img_contact);
}
else{
Bitmap bp;
try {
bp = MediaStore.Images.Media
.getBitmap(context.getContentResolver(),
Uri.parse(obj.getImage()));
Glide.with(context).load(bp).centerInside().into(holder.img_contact);
} catch (IOException e) {
e.printStackTrace();
Picasso.get().load(R.drawable.ic_circle_fav_no_dp).fit().into(holder.img_contact);
}
}
obj.setFavorite(favContactRepo.checkIfFavourite(obj.getId()));
if(obj.isFavorite()){
Picasso.get().load(R.drawable.ic_menu_favorite_true).into(holder.img_fav_true_or_not);
}
else{
Picasso.get().load(R.drawable.ic_menu_favorite_false).into(holder.img_fav_true_or_not);
}
}
#Override
public int getItemCount() {
return contactList.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CircleImageView img_contact;
TextView tv_contact_name,tv_contact_number;
ImageView img_fav_true_or_not;
ImageView img_call;
RecyclerView fav_contact_rv;
OnMyOwnClickListener onMyOwnClickListener;
public MyViewHolder(#NonNull View itemView, OnMyOwnClickListener onMyOwnClickListener) {
super(itemView);
img_contact = itemView.findViewById(R.id.img_contact);
tv_contact_name = itemView.findViewById(R.id.tv_contact_name);
img_fav_true_or_not = itemView.findViewById(R.id.img_fav_true_or_not);
tv_contact_number = itemView.findViewById(R.id.tv_contact_number);
img_call = itemView.findViewById(R.id.img_call);
fav_contact_rv = itemView.findViewById(R.id.fav_contact_rv);
this.onMyOwnClickListener = onMyOwnClickListener;
img_call.setOnClickListener(this);
img_fav_true_or_not.setOnClickListener(this);
img_contact.setOnClickListener(this);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
onMyOwnClickListener.onMyOwnClick(getAbsoluteAdapterPosition(),view);
}
}
public interface OnMyOwnClickListener{
void onMyOwnClick(int position,View view);
}
#Override
public Filter getFilter() {
return filteredList;
}
public Filter filteredList = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<FavContact> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList=filterList;
} else {
String filterText = constraint.toString().toLowerCase().trim();
for (FavContact item : filterList) {
if (item.getName().toLowerCase().contains(filterText)
||item.getNumber().toLowerCase().contains(filterText)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#SuppressLint("NotifyDataSetChanged")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
contactList.clear();
contactList.addAll((ArrayList)results.values);
notifyDataSetChanged();
}
};
I try to retrieve the data each time the Android sends SMS.
Data form:
destination phone number
delivery time
SMS body
Anyone knows how?
Get sms in sent box.
public List<SmsRep> getOutboxSms()
{
if(null == context)
{
return new ArrayList<SmsRep>();
}
Uri uriSms = Uri.parse("content://sms/sent");
Cursor cursor = context.getContentResolver().query(uriSms, null,null,null,null);
List<SmsRep> outboxSms = cursor2SmsArray(cursor);
if(!cursor.isClosed())
{
cursor.close();
}
return outboxSms;
}
And the method to handle data in sent box:
public static List<SmsRep> cursor2SmsArray(Cursor cursor)
{
if(null == cursor || 0 == cursor.getCount())
{
return new ArrayList<SmsRep>();
}
List<SmsRep> messages = new ArrayList<SmsRep>();
try
{
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
{
SmsRep singleSms = new SmsRep();
singleSms.id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
singleSms.address = cursor.getString(cursor.getColumnIndexOrThrow("address"));
singleSms.timestamp = cursor.getLong(cursor.getColumnIndexOrThrow("date")) / 1000; //### the sent time
singleSms.type = cursor.getInt(cursor.getColumnIndexOrThrow("type"));
singleSms.protocol = cursor.getInt(cursor.getColumnIndexOrThrow("protocol"));
/*
String smsSubject = cursor.getString(cursor.getColumnIndex("subject"));
byte[] subjByts = smsSubject.getBytes("UTF8");
singleSms.subject = new String(subjByts, "UTF8");
*/
String smsBody = cursor.getString(cursor.getColumnIndexOrThrow("body")); //### body
byte[] bodyBytes = smsBody.getBytes("UTF8");
singleSms.body = TextUtils.htmlEncode(new String(bodyBytes, "UTF8")); //escape,handle '='
singleSms.deviceId = deviceId;
//singleSms.body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
messages.add(singleSms);
}
}
catch (Exception e)
{
Log.e(TAG, e.getMessage());
}
finally
{
cursor.close();
}
return messages;
}
Definition of SmsRep:
public class SmsRep
{
static String separator ;
public int id;
public String address;
public long timestamp;
public int type;
public int protocol;
public String subject;
public String body;
public String deviceId;
public SmsRep()
{
// do nothing in ctor
}
}
Is this what you want ?:)
There is nothing in the Android SDK for this, sorry.
We can get notified when you receive a SMS, but there is no way to get notified when a SMS is sent.
Uri uriSMS = Uri.parse("content://sms/sent");
Cursor cur = getActivity().getContentResolver().query(uriSMS , null, null, null, null);
Cursor messagesCursor = getActivity().getContentResolver().query(uriSMS , new String[]{"_id", "address", "body", "person", "date",}, null, null, null);
if(messagesCursor.getCount() > 0) {
try {
while (messagesCursor.moveToNext())
{
int x=messagesCursor.getInt(messagesCursor.getColumnIndex("_id"));
String address=messagesCursor.getString(messagesCursor.getColumnIndex("address"));
String body=messagesCursor.getString(messagesCursor.getColumnIndex("body"));
String person=messagesCursor.getString(messagesCursor.getColumnIndex("person"));
String date_=messagesCursor.getString(messagesCursor.getColumnIndex("date"));
}
}
catch(Exception ex)
{
}
}