I have two applications and I want to create a query from App A to get App B's info.
This is a very simple process as shown below, but i wanted to double check with the community and get some constructive criticism. Is there a better way?
Thank you.
This code gets the name of someone in my DB.
private Cursor getData() {
final Uri uri = Uri.parse("content://" + AUTHORITY + "/" + TABLE_PATH);
String[] projection = new String[] { "_id", "foo" };
String selection = null;
String[] selectionArgs = null;
String sortOrder = null;;
ContentResolver resolver = getContentResolver();
return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
}
Well, it should work if the system is aware of a content provider that has the authority you've specified, and that provider recognizes TABLE_PATH, and the provider recognizes "_id" and "foo" as valid column names.
However, you seem to be asking several different questions:
Is this a safe way to query another app's content provider? Oh yes; It is by far the most preferred way to get data from another app.
"This code gets the name of someone in my DB". Actually, that's a slight misstatement. The code runs a query against the content provider that has the authority AUTHORITY, and against an entity in the provider that is named TABLE_PATH. No database is necessary, although content providers often store their data in an SQLite database. All that the CP has to do is establish an authority and respond to incoming content URIs.
Related
I need to get a link from auto-sent-SMS, but this SMS is always from a different number, so it's not like Retriever API.
I wanted to know - is it even possible for Android 8-9 and higher to programmatically read SMS via app?
If you know some examples on how - appreciate if you'll share :)
*most of the topics here are outdated or related to Retriever API so I wanted to know for sure about the latest Android versions.
There are Telephony.Sms.Inbox and Telephony.Sms.Sent content providers to access incoming and outgoing sms data. I used this far far way ago, but now i got my old code, and it still working in api 29. Here is my sample code to get basic data from inbox table, it's full text, but better way is to access content_uri and columns via content provider classes. If you want to get more columns, check docs. Remember, you need to grant READ_SMS permission.
Uri inboxUri = Uri.parse("content://sms/inbox");
String[] projection = new String[] { "_id", "date", "date_sent", "address", "body" };
String sortOrder = "date";
String limit = " DESC";
Cursor cursor = mContext.getApplicationContext().getContentResolver().
query(inboxUri, projection, null, null, sortOrder + limit);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
//read sms data
} while (cursor.moveToNext());
}
cursor.close();
}
I have been retrieving images from MediaStore in the following way...
Uri uriExternal = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {
MediaStore.MediaColumns._ID,
MediaStore.MediaColumns.DATE_ADDED
};
Cursor cursor = getContentResolver()
.query(uriExternal, projection,
MediaStore.MediaColumns.DATA + " IS NOT NULL",
null,
MediaStore.MediaColumns.DATE_ADDED + " DESC");
if(cursor != null) {
while (cursor.moveToNext()) {
String _id = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
paths.add(uriExternal.toString() + "/" + _id);
}
cursor.close();
}
Basically, I'm simply appending the file id to the external content provider uri. This makes a uri that I can use with content providers...
content://media/external/images/media/{id}
It all works perfectly fine, all external images are displayed and loaded flawlessly. However, since I've failed to find proper documentation, I'm a little concerned I'm not doing things the proper way. Especially because of the way I'm constructing the uri...kind of hard-coding it...
The questions are...
Is this the correct way to construct a content uri for an external image?
Is there a more reliable way to achieve this?
Personally, I use ContentUris.withAppendedId(). That way, I don't have to worry about whether I am starting with a Uri that ends in / or not. :-)
In general, MediaStore adheres to the original ContentProvider vision of using the content ID as the last path segment of a Uri pointing to the content. However, that is not a general rule, and it will not work for all providers.
I need to retrieve all data for a single contact which was chosen by a user (Action.Pick). I want to use LOOKUP KEY as suggested by developer.android.com. Can I do it by a simple query without creating Loader etc. as suggested by the documentation ?
I wrote this method for my application:
public static Cursor getContactCursorByLookUpKey(Context context,String lookUpKey)
{
ContentResolver contentResolver = context.getContentResolver();
Uri lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI,lookUpKey);
return contentResolver.query(lookupUri,null,null,null,null);
}
To get the data simply read data from the cursor. For example :
Cursor data = ContactManager.getContactCursorByLookUpKey(ContactDetailsActivity.this,lookUpKey);
String name = data.getString(data.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String photoPath = data.getString(data.getColumnIndex(ContactsContract.Contacts.PHOTO_URI));
You can query the Contacts provider using ContentResolver directly, if you have the READ_CONTACTS permission. You will receive a cursor with multiple rows of raw contact details (phones, emails, etc.). Iterate over the cursor to read them and don't forget to close the cursor.
In my Android app i have an Activity with tabs and each tab changes to a different Fragment, each with several fields the user should fill. The user can then submit all data by clicking a button in the action bar.
Is there an easy way to access and store all data from the different Fragments at action bar button click? Am i missing something here?
If I understood your problem right, I'd see two possible solutions:
1) To copy the data from the fragments to a class extending the Application class, so that class work as a placeholder for global variables. You only would need to capture the input events on the fragments to update the class, or to capture the fragment transition to copy the data from it to the Application
2) You can inflate your fragments' views into the main activity one by setting the attachToRoot flag. Then it should be possible to find them with findViewById in the main activity
It is unclear on what you mean by save. If you want to store the data locally on the phone:
Android Storage options
From these I strongly recommend SQLite for more complex data and Shared Preferences for simple (String or int) type data.
When You Entering the data in First Fragment that all data you can store it into one String by comma separated value and then access that values into second fragment and split that string and store it into Sqlite DB .
If I understand correctly you want to save data to your database from various parts of your app. I would suggest you use ContentProvider/ContentResolver for this. With this approach you would implement a ContentProvider which interacts with your database and from anywhere else in the app you would use a ContentResolver to interact with the ContentProvider.
In your ContentProvider you would have to implement the methods, query(), insert(), delete(), update(), onCreate() and getType(). Uris are used to identify what you want to insert or select from the ContentProvider. You can use a static UriMatcher to make parsing of the Uris very simple. I will give you an example on how to implement the query method with a sqlite database:
This is how you would define an UriMatcher in your Provider:
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
// Here you define your Uris, in this case for a table I called TABLE_ONE.
// If you want to know what each of these parameters means I suggest you view the documentation
sURIMatcher.addURI(AUTHORITY, BASE_PATH, TABLE_ONE_ID);
}
// I suggest you define all constants like the AUTHORITY and BASEPATH and Uri's in a Contract class.
// You create the Uris from the value of AUTHORITY and BASE_PATH like this:
public static final Uri TABLE_ONE_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
And this is a rudimentary implementation of the query method:
public Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor c = null;
// The UriMatcher gives you the id of the uri if you added it like in the above example
int uriId = sURIMatcher.match(uri);
switch (uriId ) {
case TABLE_ONE_ID:
SQLiteDatabase db = database.getWritableDatabase();
c = db.query(TABLE_ONE_NAME, projecton, selection, selectionArgs, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
return c;
}
And then in your app you can select data from the db using a ContentResolver like this:
// Note that getContentResolver is a method of Activity, in a Fragment you have to call getActivity().getContentResolver()
getContentResolver().query(TABLE_ONE_URI, projection, selection, selectionArgs, sortOrder);
Here is the link to a complete Tutorial about pretty much anything important regarding SQLite and ContentProviders in Android:
http://www.vogella.com/articles/AndroidSQLite/article.html
Here you can find the official guide from Google on how to implement a ContentProvider:
http://developer.android.com/guide/topics/providers/content-provider-creating.html
In the class MediaStore.Files class, its mentioned that,
Media provider table containing an index of all files in the media storage, including non-media files.
I'm interested in querying for non-media files like PDF.
I'm using CursorLoader to query the database. The second parameter for the constructor requires an Uri argument which is easy to get for the media types Audio, Images and Video as each of them have a EXTERNAL_CONTENT_URI and INTERNAL_CONTENT_URI constant defined for them.
For MediaStore.Files there is no such defined constant. I tried using the getContentUri() method but couldn't figure out the argument value for volumeName. I tried giving "/mnt/sdcard" and also the volume name that appears when I connect the device to my system but in vain.
I saw a similar question on Google Groups but that is not resolved.
EDIT: I also tried using Uri.fromFile(new File("/mnt/sdcard/")) and Uri.parse(new File("/mnt/sdcard").toString()) but that didn't work out either.
It is "external" or "internal" although internal (system files) is probably not useful here.
ContentResolver cr = context.getContentResolver();
Uri uri = MediaStore.Files.getContentUri("external");
// every column, although that is huge waste, you probably need
// BaseColumns.DATA (the path) only.
String[] projection = null;
// exclude media files, they would be here also.
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;
String[] selectionArgs = null; // there is no ? in selection so null here
String sortOrder = null; // unordered
Cursor allNonMediaFiles = cr.query(uri, projection, selection, selectionArgs, sortOrder);
If you want .pdf only you could check the mimetype
// only pdf
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
String[] selectionArgsPdf = new String[]{ mimeType };
Cursor allPdfFiles = cr.query(uri, projection, selectionMimeType, selectionArgsPdf, sortOrder);