CIS 470 Mobile App Development

Slides:



Advertisements
Similar presentations
Android – CoNTENT PRoViders
Advertisements

ContentProviders.  Databases for reading & writing data  Support typical database operations  e.g., query, insert, update & delete.
Cosc 5/4730 Android Content Providers and Intents.
CONTENT PROVIDER. Content Provider  A content provider makes a specific set of the application's data available to other applications => Share data to.
Chien-Chung Shen Manifest and Activity Chien-Chung Shen
SQLite Database. SQLite Public domain database – Advantages Small (about 150 KB) – Used on devices with limited resources Each database contained within.
Data Storage: Part 3 (SQLite)
Content providers Accessing shared data in a uniform way 1Content providers.
Cosc 5/4730 Android Content Providers and Intents.
Data Storage: Part 4 (Content Providers). Content Providers Content providers allow the sharing of data between applications. Inter-process communication.
Package org.androidtown.database.query; import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase;
Android - Broadcast Receivers
Persistence Dr. David Janzen Except as otherwise noted, the content of this presentation is licensed under the Creative Commons Attribution 2.5 License.
Mobile Software Development ISCG 7424 Department of Computing UNITEC John Casey and Richard Rabeder SQLite and Permissions.
Address Book App 1 Fall 2014 CS7020: Game Design and Development.
By: Eliav Menachi.  On Android, all application data (including files) are private to that application  Android provides a standard way for an application.
CMPE419 Mobile Application Development Asst.Prof.Dr.Ahmet Ünveren SPRING Computer Engineering Department Asst.Prof.Dr.Ahmet Ünveren
CMPE419 Mobile Application Development Asst.Prof.Dr.Ahmet Ünveren SPRING Computer Engineering Department Asst.Prof.Dr.Ahmet Ünveren
CMPE419 Mobile Application Development Asst.Prof.Dr.Ahmet Ünveren SPRING Computer Engineering Department Asst.Prof.Dr.Ahmet Ünveren
CMPE419 Mobile Application Development Asst.Prof.Dr.Ahmet Ünveren SPRING Computer Engineering Department Asst.Prof.Dr.Ahmet Ünveren
Content Providers.
Making content providers
Lab7 – Appendix.
Content provider.
Android Content Providers & SQLite
Data Storage: Part 4 (Content Providers)
Mobile Software Development for Android - I397
CS240: Advanced Programming Concepts
Reactive Android Development
Android Dr. Vaishali D. Khairnar IT Department
CS499 – Mobile Application Development
Android – Read/Write to External Storage
Mobile Software Development for Android - I397
Mobile Device Development
Picasso Revisted.
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
Android Programming Lecture 6
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
Android Sensor Programming
CIS 470 Mobile App Development
BMI Android Application will take weight and height from the users to calculate Body Mass Index (BMI) with the information, whether user is underweight,
Mobile Computing With Android ACST 4550 Android Database Storage
CIS 470 Mobile App Development
CIS 493/EEC 492 Android Sensor Programming
CIS 470 Mobile App Development
Android Developer Fundamentals V2
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
CIS 470 Mobile App Development
BLP 4216 MOBİL UYGULAMA GELİŞTİRME-2
CMPE419 Mobile Application Development
CIS 470 Mobile App Development
Mobile Programming Broadcast Receivers.
Android Sensor Programming
Android Sensor Programming
CIS 694/EEC 693 Android Sensor Programming
CIS 694/EEC 693 Android Sensor Programming
CIS 694/EEC 693 Android Sensor Programming
Presentation transcript:

CIS 470 Mobile App Development Lecture 11 Wenbing Zhao Department of Electrical Engineering and Computer Science Cleveland State University wenbing@ieee.org 4/4/2019 CIS 470: Mobile App Development

Sharing Data Through Content Providers What content providers are How to use a content provider in Android How to create and use your own content provider 4/4/2019 CIS 470: Mobile App Development

Sharing Data Through Content Providers Think of a content provider as a data store Using a content provider is the recommended way to share data across packages Unlike a database, a content provider can use different ways to store its data The data can be stored in a database, in files, or even over a network Android ships with many useful content providers Browser—Stores data such as browser bookmarks, browser history, and so on CallLog—Stores data such as missed calls, call details, and so on Contacts—Stores contact details MediaStore—Stores media files such as audio, video, and images Settings—Stores the device’s settings and preferences 4/4/2019 CIS 470: Mobile App Development

Query a Content Provider Query a content provider using Uniform Resource Identifier (URI): <standard_prefix>://<authority>/<data_path>/<id> The standard prefix for content providers is always content:// The authority specifies the name of the content provider An example would be contacts for the built-in Contacts content provider. For third-party content providers, this could be the fully qualified name, such as com.wrox.provider or com.jfdimarzio.provider The data path specifies the kind of data requested For example, if you are getting all the ontacts from the Contacts content provider then the data path would be people, and the URI would look like this: content://contacts/people The id specifies the specific record requested For example, if you are looking for contact number 2 in the Contacts content provider, the URI would look like this: content://contacts/people/2 4/4/2019 CIS 470: Mobile App Development

Query a Content Provider Query String Description content://media/internal/images Returns a list of the internal images on the device content://media/external/images Returns a list of the images stored on the external storage (for example, SD card) on the device content://call_log/calls Returns a list of calls registered in the Call Log content://browser/bookmarks Returns a list of bookmarks stored in the browser 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Create a new app and name it UseProvider Modify activity_main.xml <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.wenbing.useprovider.MainActivity"> <TextView android:text="TextView" android:layout_width="0dp" android:layout_height="60dp" android:id="@+id/contactName" app:layout_constraintLeft_toLeftOf="@+id/activity_main" android:layout_marginStart="63dp" tools:layout_constraintLeft_creator="1" app:layout_constraintRight_toRightOf="@+id/activity_main" android:layout_marginEnd="63dp" tools:layout_constraintRight_creator="1" app:layout_constraintBottom_toTopOf="@+id/contactID" android:layout_marginBottom="40dp" tools:layout_constraintBottom_creator="1" /> 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Modify activity_main.xml <TextView android:text="TextView" android:layout_width="0dp" android:layout_height="64dp" android:id="@+id/contactID" app:layout_constraintLeft_toLeftOf="@+id/activity_main" android:layout_marginStart="63dp" tools:layout_constraintLeft_creator="1" app:layout_constraintRight_toRightOf="@+id/activity_main" android:layout_marginEnd="63dp" tools:layout_constraintRight_creator="1" app:layout_constraintBottom_toBottomOf="@+id/activity_main" android:layout_marginBottom="56dp" tools:layout_constraintBottom_creator="1" /> <ListView android:layout_height="0dp" android:id="@android:id/list" android:layout_width="wrap_content" app:layout_constraintLeft_toLeftOf="@+id/activity_main" app:layout_constraintTop_toTopOf="@+id/activity_main" tools:layout_constraintTop_creator="1" app:layout_constraintRight_toRightOf="@+id/activity_main" app:layout_constraintBottom_toTopOf="@+id/contactName" android:layout_marginBottom="5dp" tools:layout_constraintBottom_creator="1" /> </android.support.constraint.ConstraintLayout> 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider import android.os.Bundle; import android.Manifest; import android.app.ListActivity; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v4.content.CursorLoader; import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.SimpleCursorAdapter; import android.widget.Toast; public class MainActivity extends ListActivity { final private int REQUEST_READ_CONTACTS = 123; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS); } else{ ListContacts(); } } Using a Content Provider Modify MainActivity.java 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development @Override public void onRequestPermissionsResult(int requestCode , String[] permissions, int[] grantResults) { switch (requestCode) { case REQUEST_READ_CONTACTS: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { ListContacts(); } else { Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show(); } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } protected void ListContacts(){ Uri allContacts = Uri.parse("content://contacts/people"); Cursor c; CursorLoader cursorLoader = new CursorLoader(this, allContacts, null, null, null, null); c = cursorLoader.loadInBackground(); int numberofrecords = c.getCount(); System.out.println("number of contacts returned: "+numberofrecords); String[] columns = new String[]{ ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts._ID}; int[] views = new int[]{R.id.contactName, R.id.contactID}; SimpleCursorAdapter adapter; adapter = new SimpleCursorAdapter( this, R.layout.activity_main, c, columns, views, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); this.setListAdapter(adapter); } } The SimpleCursorAdapter object maps a cursor to TextViews defined in your XML file (activity_main.xml) The flag registers the adapter to be informed when there is a change in the content provider 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Modify AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wenbing.useprovider"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.READ_CONTACTS"/> </manifest> 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Make sure you have at least one contact in your contents 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Retrieve contact information import android.util.Log; private void PrintContacts(Cursor c) { if (c.moveToFirst()) { do { String contactID = c.getString(c.getColumnIndex( ContactsContract.Contacts._ID)); String contactDisplayName = c.getString(c.getColumnIndex( ContactsContract.Contacts.DISPLAY_NAME)); Log.v("Content Providers", contactID + ", " + contactDisplayName); Cursor phoneCursor = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactID, null, null); while (phoneCursor.moveToNext()) { Log.v("Content Providers", phoneCursor.getString(phoneCursor.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER))); } phoneCursor.close(); } while (c.moveToNext()); } } 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Projections: third parameter in the CursorLoader constructor String[] projection = new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER}; Cursor c; CursorLoader cursorLoader = new CursorLoader( this, allContacts, projection, null, null, null); 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Filtering: fourth and fifth parameters in the CursorLoader constructor CursorLoader cursorLoader = new CursorLoader( this, allContacts, projection, ContactsContract.Contacts.DISPLAY_NAME + " LIKE '%Lee'", null, null); 4/4/2019 CIS 470: Mobile App Development

Using a Content Provider Sorting: last parameter in the CursorLoader constructor CursorLoader cursorLoader = new CursorLoader( this, allContacts, projection, ContactsContract.Contacts.DISPLAY_NAME + " LIKE '%Lee'", null, ContactsContract.Contacts.DISPLAY_NAME + " ASC"); ); sorts the contact names in ascending order 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; public class BooksProvider extends ContentProvider { static final String PROVIDER_NAME = "com.wenbing.provider.Books"; static final Uri CONTENT_URI = Uri.parse("content://"+ PROVIDER_NAME + "/books"); static final String _ID = "_id"; static final String TITLE = "title"; static final String ISBN = "isbn"; static final int BOOKS = 1; static final int BOOK_ID = 2; private static final UriMatcher uriMatcher; static{ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "books", BOOKS); uriMatcher.addURI(PROVIDER_NAME, "books/#", BOOK_ID); } Create a project and name it MyContentProvider Add a Java class BooksProvider.java: 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider //---for database use--- SQLiteDatabase booksDB; static final String DATABASE_NAME = "Books"; static final String DATABASE_TABLE = "titles"; static final int DATABASE_VERSION = 1; static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " (_id integer primary key autoincrement, " + "title text not null, isbn text not null);"; private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w("Provider database", "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS titles"); onCreate(db); } } 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider @Override public int delete(Uri arg0, String arg1, String[] arg2) { // arg0 = uri arg1 = selection arg2 = selectionArgs int count=0; switch (uriMatcher.match(arg0)){ case BOOKS: count = booksDB.delete(DATABASE_TABLE, arg1, arg2); break; case BOOK_ID: String id = arg0.getPathSegments().get(1); count = booksDB.delete(DATABASE_TABLE, _ID + " = " + id + (!TextUtils.isEmpty(arg1) ? " AND (" + arg1 + ')' : ""), arg2); break; default: throw new IllegalArgumentException("Unknown URI " + arg0); } getContext().getContentResolver().notifyChange(arg0, null); return count; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)){ case BOOKS: return "vnd.android.cursor.dir/vnd.learn2develop.books "; case BOOK_ID: return "vnd.android.cursor.item/vnd.learn2develop.books "; default: throw new IllegalArgumentException("Unsupported URI: " + uri); } } Add a Java class BooksProvider.java: 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development @Override public Uri insert(Uri uri, ContentValues values) { long rowID = booksDB.insert( DATABASE_TABLE, "", values); if (rowID>0) { Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID); getContext().getContentResolver().notifyChange(_uri, null); return _uri; } throw new SQLException("Failed to insert row into " + uri); } @Override public boolean onCreate() { Context context = getContext(); DatabaseHelper dbHelper = new DatabaseHelper(context); booksDB = dbHelper.getWritableDatabase(); return (booksDB == null)? false:true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder(); sqlBuilder.setTables(DATABASE_TABLE); if (uriMatcher.match(uri) == BOOK_ID) sqlBuilder.appendWhere( _ID + " = " + uri.getPathSegments().get(1)); if (sortOrder==null || sortOrder=="") sortOrder = TITLE; Cursor c = sqlBuilder.query(booksDB, projection, selection, selectionArgs, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } Creating a Provider Add a Java class BooksProvider.java: 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count = 0; switch (uriMatcher.match(uri)){ case BOOKS: count = booksDB.update( DATABASE_TABLE, values, selection, selectionArgs); break; case BOOK_ID: count = booksDB.update( DATABASE_TABLE, values, _ID + " = " + 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; } Add a Java class BooksProvider.java: 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wenbing.mycontentprovider"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="BooksProvider" android:authorities="com.wenbing.provider.Books"> </provider> </application> </manifest> Modify manifest 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.wenbing.mycontentprovider.MainActivity"> <TextView android:text="ISBN" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView" app:layout_constraintLeft_toLeftOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toTopOf="@+id/activity_main" android:layout_marginTop="16dp" app:layout_constraintRight_toRightOf="@+id/activity_main" tools:layout_constraintRight_creator="1" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="text" android:ems="10" android:id="@+id/txtISBN" app:layout_constraintLeft_toLeftOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toBottomOf="@+id/textView" android:layout_marginTop="8dp" app:layout_constraintRight_toRightOf="@+id/activity_main" tools:layout_constraintRight_creator="1" app:layout_constraintBottom_toTopOf="@+id/textView2" android:layout_marginBottom="8dp" app:layout_constraintHorizontal_bias="0.46" app:layout_constraintVertical_bias="0.100000024" /> Creating a Provider Modify activity_main.xml 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider <TextView android:text="Title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView2" app:layout_constraintLeft_toLeftOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toTopOf="@+id/activity_main" android:layout_marginTop="142dp" tools:layout_constraintTop_creator="1" app:layout_constraintRight_toRightOf="@+id/activity_main" tools:layout_constraintRight_creator="1" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="text" android:ems="10" android:id="@+id/txtTitle" app:layout_constraintLeft_toLeftOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toBottomOf="@+id/textView2" android:layout_marginTop="8dp" app:layout_constraintRight_toRightOf="@+id/activity_main" tools:layout_constraintRight_creator="1" /> Modify activity_main.xml 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider <Button android:text="Add Title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnAdd" app:layout_constraintLeft_toLeftOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toBottomOf="@+id/txtTitle" android:layout_marginTop="112dp" app:layout_constraintRight_toRightOf="@+id/activity_main" tools:layout_constraintRight_creator="1" android:onClick="onClickAddTitle" /> <Button android:text="Retrieve Titles" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnRetrieve" app:layout_constraintLeft_toLeftOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toBottomOf="@+id/btnAdd" android:layout_marginTop="32dp" app:layout_constraintRight_toRightOf="@+id/activity_main" tools:layout_constraintRight_creator="1" android:onClick="onClickRetrieveTitles" /> </android.support.constraint.ConstraintLayout> Modify activity_main.xml 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Creating a Provider import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.content.ContentValues; import android.content.CursorLoader; import android.database.Cursor; import android.net.Uri; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onClickAddTitle(View view) { //---add a book--- ContentValues values = new ContentValues(); values.put(BooksProvider.TITLE, ((EditText) findViewById(R.id.txtTitle)).getText().toString()); values.put(BooksProvider.ISBN, ((EditText) findViewById(R.id.txtISBN)).getText().toString()); Uri uri = getContentResolver().insert( BooksProvider.CONTENT_URI, values); Toast.makeText(getBaseContext(),uri.toString(), Toast.LENGTH_LONG).show(); } Modify MainActivity.java 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development public void onClickRetrieveTitles(View view) { //---retrieve the titles--- Uri allTitles = Uri.parse( "content://com.wenbing.provider.Books/books"); Cursor c; CursorLoader cursorLoader = new CursorLoader( this, allTitles, null, null, null, "title desc"); c = cursorLoader.loadInBackground(); if (c.moveToFirst()) { do{ Toast.makeText(this, c.getString(c.getColumnIndex( BooksProvider._ID)) + ", " + c.getString(c.getColumnIndex( BooksProvider.TITLE)) + ", " + c.getString(c.getColumnIndex( BooksProvider.ISBN)), Toast.LENGTH_SHORT).show(); } while (c.moveToNext()); } } } 4/4/2019 CIS 470: Mobile App Development

CIS 470: Mobile App Development Homework #15 Create a separate app that use the Books provider you just build: Add a button to retrieve all books in the provider and display them in a scrollable ListView (a new Activity). On clicking a book in the list, display it in yet another Activity to show the details of the book In the display Activity, add a button so that you can sort the list based on ascending or descending order Add another button to search for particular book based on a search term and display the result in a new Activity 4/4/2019 CIS 470: Mobile App Development