Android get all details of a contact - android

I didn't find any solution in the Internet, only a tutorial on Android Developers, which unfortunately gives only a small part of code needed for it. I ended up having something like this:
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.Data;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
// Defines the selection clause
private static final String SELECTION = Data.LOOKUP_KEY + " = ?"; // Defines the array to hold the search criteria
private String[] mSelectionArgs = { "" };
private String mLookupKey;
private static final String SORT_ORDER = Data.MIMETYPE;
final int DETAILS_QUERY_ID = 0;
private static final String PROJECTION[] = {
Data._ID, Data.MIMETYPE, Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5, Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11, Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// getLoaderManager().initLoader(DETAILS_QUERY_ID, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
switch (loaderId) {
case DETAILS_QUERY_ID:
// Assigns the selection parameter
mSelectionArgs[0] = mLookupKey; // Starts the query
CursorLoader mLoader = new CursorLoader(this, Data.CONTENT_URI, PROJECTION,
SELECTION, mSelectionArgs, SORT_ORDER);
}
return null; // TODO what should be here ?
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// switch (loader.getId()) {
// case DETAILS_QUERY_ID:
// }
// break;
// }
}
}
How can I make it work ? https://developer.android.com/training/contacts-provider/retrieve-details.html is really lacking some code and explanation

Related

How to load data in listview after inserting into database using Loader automatically?

I've created demo application which insert some data into sqlite database and update on listview [Fragment]. But i want to add one another data by click on button which data comes from EditText and update on listview with new data.
I write my demo code below. pls let me know how do i show all data in listview which after adding into database at the same time.
####################################### Step 1
package com.example.locationsample.database;
import java.util.List;
import android.database.sqlite.SQLiteDatabase;
public abstract class DataSource<T> {
public final SQLiteDatabase mDatabase;
public DataSource(final SQLiteDatabase database) {
mDatabase = database;
}
public abstract boolean insert(T entity);
public abstract boolean delete(T entity);
public abstract boolean update(T entity);
public abstract List read();
public abstract List read(String selection, String[] selectionArgs,
String groupBy, String having, String orderBy);
}
####################################### Step 2
package com.example.locationsample.model;
public class Test {
public Test() {
}
public Test(String name) {
this.name = name;
}
private int id;
private String name;
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id
* the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name
* the name to set
*/
public void setName(final String name) {
this.name = name;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return name;
// return "Test [name=" + name + "]";
}
}
####################################### Step 3
package com.example.locationsample.database;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.example.locationsample.model.Test;
public class TestDataSource extends DataSource<Test> {
public static final String TABLE_NAME = "test";
private static final String COLUMN_ID = "_id";
private static final String COLUMN_NAME = "name";
public static final String CREATE_COMMAND = "create table " + TABLE_NAME
+ " (" + COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_NAME + " text not null);";
public TestDataSource(final SQLiteDatabase database) {
super(database);
}
#Override
public boolean insert(final Test entity) {
if (entity == null) {
return false;
}
final long result = mDatabase.insert(TABLE_NAME, null,
generateContentValueFromObject(entity));
return result != -1;
}
#Override
public boolean delete(final Test entity) {
if (entity == null) {
return false;
}
final int result = mDatabase.delete(TABLE_NAME, COLUMN_ID + "=?",
new String[] { String.valueOf(entity.getId()) });
return result != 0;
}
#Override
public boolean update(final Test entity) {
if (entity == null) {
return false;
}
final int result = mDatabase.update(TABLE_NAME,
generateContentValueFromObject(entity), COLUMN_ID + "=?",
new String[] { String.valueOf(entity.getId()) });
return result != 0;
}
#Override
public List<Test> read() {
final Cursor cursor = mDatabase.query(TABLE_NAME, getAllColumns(),
null, null, null, null, null);
final List<Test> tests = new ArrayList<Test>();
if (cursor != null && cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
tests.add(generateObjectFromCursor(cursor));
cursor.moveToNext();
}
cursor.close();
}
return tests;
}
#Override
public List<Test> read(final String selection,
final String[] selectionArgs, final String groupBy,
final String having, final String orderBy) {
final Cursor cursor = mDatabase.query(TABLE_NAME, getAllColumns(),
selection, selectionArgs, groupBy, having, orderBy);
final List<Test> tests = new ArrayList<Test>();
if (cursor != null && cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
tests.add(generateObjectFromCursor(cursor));
cursor.moveToNext();
}
cursor.close();
}
return tests;
}
private String[] getAllColumns() {
return new String[] { COLUMN_ID, COLUMN_NAME };
}
private Test generateObjectFromCursor(final Cursor cursor) {
if (cursor == null) {
return null;
}
final Test test = new Test();
test.setId(cursor.getInt(cursor.getColumnIndex(COLUMN_ID)));
test.setName(cursor.getString(cursor.getColumnIndex(COLUMN_NAME)));
return test;
}
private ContentValues generateContentValueFromObject(final Test entity) {
if (entity == null) {
return null;
}
final ContentValues values = new ContentValues();
values.put(COLUMN_NAME, entity.getName());
return values;
}
}
####################################### Step 4
package com.example.locationsample.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "test.db";
private static final int DATABASE_VERSION = 1;
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TestDataSource.CREATE_COMMAND);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TestDataSource.TABLE_NAME);
onCreate(db);
}
}
####################################### Step 5
package com.example.locationsample.loader;
import android.content.Loader;
import android.os.AsyncTask;
import android.util.Log;
public abstract class ContentChangingTask<T1, T2, T3> extends
AsyncTask<T1, T2, T3> {
private static final String TAG = "ContentChangingTask";
private Loader<?> mLoader = null;
public ContentChangingTask(final Loader<?> loader) {
mLoader = loader;
}
#Override
protected void onPostExecute(final T3 result) {
// super.onPostExecute(result);
Log.i(TAG, "+++ onPostExecute() called! +++");
mLoader.onContentChanged();
}
}
####################################### Step 6
package com.example.locationsample.loader;
import java.util.List;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.util.Log;
public abstract class AbstractDataLoader<E extends List<?>> extends
AsyncTaskLoader<E> {
private static final String TAG = "AbstractDataLoader";
protected E mLastDataList = null;
protected abstract E buildList();
public AbstractDataLoader(final Context context) {
super(context);
}
/**
* Runs on a worker thread, loading in our data. Delegates the real work to
* concrete subclass' buildList() method.
*/
#Override
public E loadInBackground() {
Log.d(TAG, "+++ loadInBackground() called! +++");
return buildList();
}
/**
* Runs on the UI thread, routing the results from the background thread to
* whatever is using the dataList.
*/
#Override
public void deliverResult(final E dataList) {
Log.d(TAG, "+++ deliverResult() called! +++");
if (isReset()) {
// An async query came in while the loader is stopped
emptyDataList(dataList);
return;
}
final E oldDataList = mLastDataList;
mLastDataList = dataList;
if (isStarted()) {
super.deliverResult(dataList);
}
if (oldDataList != null && oldDataList != dataList
&& oldDataList.size() > 0) {
emptyDataList(oldDataList);
}
}
/**
* Starts an asynchronous load of the list data. When the result is ready
* the callbacks will be called on the UI thread. If a previous load has
* been completed and is still valid the result may be passed to the
* callbacks immediately.
*
* Must be called from the UI thread.
*/
#Override
protected void onStartLoading() {
//super.onStartLoading();
Log.d(TAG, "+++ onStartLoading() called! +++");
if (mLastDataList != null) {
deliverResult(mLastDataList);
}
if (takeContentChanged() || mLastDataList == null
|| mLastDataList.size() == 0) {
forceLoad();
}
}
/**
* Must be called from the UI thread, triggered by a call to stopLoading().
*/
#Override
protected void onStopLoading() {
Log.d(TAG, "+++ onStopLoading() called! +++");
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Must be called from the UI thread, triggered by a call to cancel(). Here,
* we make sure our Cursor is closed, if it still exists and is not already
* closed.
*/
#Override
public void onCanceled(final E dataList) {
Log.d(TAG, "+++ onCanceled() called! +++");
if (dataList != null && dataList.size() > 0) {
emptyDataList(dataList);
}
}
/**
* Must be called from the UI thread, triggered by a call to reset(). Here,
* we make sure our Cursor is closed, if it still exists and is not already
* closed.
*/
#Override
protected void onReset() {
super.onReset();
Log.d(TAG, "+++ onReset() called! +++");
// Ensure the loader is stopped
onStopLoading();
if (mLastDataList != null && mLastDataList.size() > 0) {
emptyDataList(mLastDataList);
}
mLastDataList = null;
}
protected void emptyDataList(final E dataList) {
if (dataList != null && dataList.size() > 0) {
for (int i = 0; i < dataList.size(); i++) {
dataList.remove(i);
}
}
}
}
####################################### Step 7
package com.example.locationsample.loader;
import java.util.List;
import android.content.Context;
import android.util.Log;
import com.example.locationsample.database.DataSource;
import com.example.locationsample.model.Test;
public class SQLiteTestDataLoader extends AbstractDataLoader<List<Test>> {
private static final String TAG = "SQLiteTestDataLoader";
private final DataSource<Test> mDataSource;
private String mSelection;
private String[] mSelectionArgs;
private String mGroupBy;
private String mHaving;
private String mOrderBy;
public SQLiteTestDataLoader(final Context context,
final DataSource<Test> dataSource, final String selection,
final String[] selectionArgs, final String groupBy,
final String having, final String orderBy) {
super(context);
mDataSource = dataSource;
}
#SuppressWarnings("unchecked")
#Override
protected List<Test> buildList() {
final List<Test> testList = mDataSource.read(mSelection,
mSelectionArgs, mGroupBy, mHaving, mOrderBy);
return testList;
}
public void insert(final Test entity) {
new InsertTask(this).execute(entity);
}
public void update(final Test entity) {
new UpdateTask(this).execute(entity);
}
public void delete(final Test entity) {
new DeleteTask(this).execute(entity);
}
private class InsertTask extends ContentChangingTask<Test, Void, Void> {
InsertTask(final SQLiteTestDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(final Test... params) {
Log.i(TAG, "+++ Inserting... +++");
mDataSource.insert(params[0]);
return (null);
}
}
private class UpdateTask extends ContentChangingTask<Test, Void, Void> {
UpdateTask(final SQLiteTestDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(final Test... params) {
Log.i(TAG, "+++ Updating... +++");
mDataSource.update(params[0]);
return (null);
}
}
private class DeleteTask extends ContentChangingTask<Test, Void, Void> {
DeleteTask(final SQLiteTestDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(final Test... params) {
Log.i(TAG, "+++ Deleting... +++");
mDataSource.delete(params[0]);
return (null);
}
}
}
####################################### Step 8
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="#+id/txt_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<EditText
android:id="#+id/edtxt_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#+id/btn_add"
android:inputType="text"
android:labelFor="#+id/edtxt_add" />
<Button
android:id="#+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="ADD" />
<fragment
android:id="#+id/titles"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/btn_add"
android:layout_below="#id/txt_data"
class="com.example.locationsample.MainFragment" />
</RelativeLayout>
####################################### Step 9
package com.example.locationsample;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.database.sqlite.SQLiteDatabase;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
import com.example.locationsample.database.DbHelper;
import com.example.locationsample.database.TestDataSource;
import com.example.locationsample.loader.SQLiteTestDataLoader;
import com.example.locationsample.model.Test;
import com.example.locationsample.utilities.Utils;
public class MainActivity extends Activity implements
OnClickListener {
private static final String TAG = "MainActivity";
private TextView mTxtData;
private EditText mEdTxtAdd;
private LocationManager mLocationManager;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTxtData = (TextView) findViewById(R.id.txt_data);
mEdTxtAdd = (EditText) findViewById(R.id.edtxt_add);
findViewById(R.id.btn_add).setOnClickListener(this);
DbHelper helper = new DbHelper(MainActivity.this);
SQLiteDatabase database = helper.getWritableDatabase();
TestDataSource dataSource = new TestDataSource(database);
List<Test> testList = dataSource.read();
if (testList == null || testList.size() == 0) {
dataSource.insert(new Test("11111"));
dataSource.insert(new Test("22222"));
dataSource.insert(new Test("33333"));
}
database.close();
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_add:
if (mEdTxtAdd == null
|| TextUtils.isEmpty(mEdTxtAdd.getText().toString())) {
return;
}
DbHelper helper = new DbHelper(MainActivity.this);
SQLiteDatabase database = helper.getWritableDatabase();
TestDataSource dataSource = new TestDataSource(database);
SQLiteTestDataLoader loader = new SQLiteTestDataLoader(
MainActivity.this, dataSource, null, null, null, null, null);
loader.insert(new Test(mEdTxtAdd.getText().toString()));
break;
default:
break;
}
}
}
####################################### Step 10
package com.example.locationsample;
import java.util.List;
import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Loader;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import com.example.locationsample.database.DbHelper;
import com.example.locationsample.database.TestDataSource;
import com.example.locationsample.loader.SQLiteTestDataLoader;
import com.example.locationsample.model.Test;
public class MainFragment extends ListFragment implements
LoaderCallbacks<List<Test>> {
private ArrayAdapter<Test> mAdapter;
// The Loader's id (this id is specific to the ListFragment's LoaderManager)
private static final int LOADER_ID = 1;
private static final boolean DEBUG = true;
private static final String TAG = "MainFragment";
private SQLiteDatabase mDatabase;
private TestDataSource mDataSource;
private DbHelper mDbHelper;
#Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mDbHelper = new DbHelper(getActivity());
mDatabase = mDbHelper.getWritableDatabase();
mDataSource = new TestDataSource(mDatabase);
mAdapter = new ArrayAdapter<Test>(getActivity(),
android.R.layout.simple_list_item_1);
setEmptyText("No data, please add from menu.");
setListAdapter(mAdapter);
setListShown(false);
if (DEBUG) {
Log.i(TAG, "+++ Calling initLoader()! +++");
if (getLoaderManager().getLoader(LOADER_ID) == null) {
Log.i(TAG, "+++ Initializing the new Loader... +++");
} else {
Log.i(TAG,
"+++ Reconnecting with existing Loader (id '1')... +++");
}
}
// Initialize a Loader with id '1'. If the Loader with this id already
// exists, then the LoaderManager will reuse the existing Loader.
getLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public Loader<List<Test>> onCreateLoader(final int id, final Bundle arg1) {
final SQLiteTestDataLoader loader = new SQLiteTestDataLoader(
getActivity(), mDataSource, null, null, null, null, null);
return loader;
}
#Override
public void onLoadFinished(final Loader<List<Test>> loader,
final List<Test> data) {
Log.d(TAG, "+++### onLoadFinished() called! ###+++");
if (DEBUG)
Log.i(TAG, "+++ onLoadFinished() called! +++");
mAdapter.clear();
for (final Test test : data) {
mAdapter.add(test);
}
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
#Override
public void onLoaderReset(final Loader<List<Test>> arg0) {
Log.i(TAG, "+++ onLoadReset() called! +++");
mAdapter.clear();
}
#Override
public void onDestroy() {
super.onDestroy();
mDbHelper.close();
mDatabase.close();
mDataSource = null;
mDbHelper = null;
mDatabase = null;
}
}
#
Whenever i write something in edittext and click on Add button, it stores data only to database, But it doesn't any update into listview which we are showing at there.
Pls, check where do i mistake???
Add this line in the main activity inside the onClick
getLoaderManager().restartLoader(0,null,this);

onLoadFinished is never called

It seems that there is a bug in the Support library v4, I want to access the MediaStore Audio using CursorLoader and LoaderManager and I have followed the protocol to the T, and no matter what I do, OnLoaderFinished is not called.
Here are some code snippets, I created something I called MediaStoreInterface,
the relevant parts of MediaStoreInterface are as follows:
public class MediaStoreInterface extends Observable
{
protected Cursor cursor;
protected static final int LOADER_ID1 = 1;
protected static final int LOADER_ID2 = 2;
protected static int lastLoaderId = 0;
protected static String function = "SONGS";
protected static PaudioActivity act;
protected static Sound selectedSound = null;
protected static final String[] projections = {MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DATA};
protected static final String[] projectionsPlaylist = {MediaStore.Audio.Playlists._ID,MediaStore.Audio.Playlists.NAME};
protected static final Uri sourceUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
protected static final Uri uriPlaylists = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
protected static ArrayList<String> ret;
protected static boolean done = false;
//Singleton
protected static MediaStoreInterface ref = null;
public static MediaStoreInterface getMusicLibrary(Activity act_)
{
if (ref == null)
ref = new MediaStoreInterface(act_);
return ref;
}
protected MediaStoreInterface(Activity act_)
{
act = (PaudioActivity) act_;
}
public static MediaStoreInterface getMSI()
{
if (android.os.Build.VERSION.SDK_INT < 11)
return MediaStoreInterfaceFrodo.getMusicLibrary(act);
else
return MediaStoreInterfaceHoneyComb.getMusicLibrary(act);
}
protected void loadArray(Cursor data)
{
int num = data.getColumnCount();
if (data == null || !data.moveToFirst())
return;
while(!data.isLast())
{
String s = data.getString(0);
int col = 1;
while(col < num)
s += "|" + data.getString(col++);
ret.add(s);
data.moveToNext();
}
if (function == "SONGS")
numSongs = ret.size();
if (function == "PLAYLISTS")
numPlaylists = ret.size();
cursor = data;
}
public static void setDone()
{
done = true;
}
}
It's a Singleton, that is supposed to return the right MediaStoreInterface for each API,
I extend Frodo from this, as follows:
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.content.Loader.OnLoadCompleteListener;
public class MediaStoreInterfaceFrodo extends MediaStoreInterface implements LoaderManager.LoaderCallbacks<Cursor>, OnLoadCompleteListener<Cursor>
{
public static MediaStoreInterface getMusicLibrary(Activity act_)
{
if (ref == null)
ref = new MediaStoreInterfaceFrodo(act_);
return ref;
}
public void setPaudioActivity(PaudioActivity act_)
{
act = act_;
}
protected MediaStoreInterfaceFrodo(Activity act_)
{
super(act_);
}
public ArrayList<String> getSongList()
{
function = "SONGS";
done = false;
if (ret == null)
ret = new ArrayList<String>();
else
ret.clear();
lastLoaderId = LOADER_ID1;
LoaderManager lm = act.getSupportLoaderManager();
Loader<Cursor> loader1 = lm.getLoader(LOADER_ID1);
if (loader1 != null && loader1.isReset())
loader1 = lm.restartLoader(LOADER_ID1, null, this);
else
{
loader1 = lm.initLoader(LOADER_ID1, null, this);
}
while(!done)
{
waitabit();
}
return ret;
}
public static void editSelectedSongTitle(String newtitle)
{
// TODO Auto-generated method stub
}
public static void setContinuePlayMode(PlayMode pm_)
{
pm = pm_;
}
public List<String> getPlayListNames()
{
function = "PLAYLISTS";
done = false;
if (ret == null)
ret = new ArrayList<String>();
else
ret.clear();
lastLoaderId = LOADER_ID2;
LoaderManager lm = act.getSupportLoaderManager();
lm.initLoader(LOADER_ID2, null, this);
while(!done)
{
waitabit();
}
function = "SONGS";
return ret;
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1)
{
CursorLoader cursorLoader = null;
switch (id)
{
case LOADER_ID1:
cursorLoader = new CursorLoader(act, sourceUri, projections, null, null, MediaStore.Audio.Media.TITLE);
break;
case LOADER_ID2:
cursorLoader = new CursorLoader(act, uriPlaylists, projectionsPlaylist, null, null, MediaStore.Audio.Playlists.NAME);
break;
default:
break;
}
cursorLoader.forceLoad();
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data)
{
cursor = data;
loadArray(cursor);
done = true;
}
#Override
public void onLoaderReset(Loader<Cursor> arg0)
{
act.getSupportLoaderManager().restartLoader(lastLoaderId, null, ( android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>) this);
}
#Override
public void onLoadComplete(Loader<Cursor> loader, Cursor data)
{
onLoadFinished( loader, data);
}
}
I have tried to separate the database query from the usual nukes and crannies of my activity, long story short I have a button that if one clicks, getSongList is called,
I also have setActivity to turn the act member into the calling Activity,
I have read ALL relevant StackOverflow articles and everything on android development site. Some of you might object that I have to call some of my functions on the UI thread, I have done that too, to no avail. I have implemented the same set of code, in my main Activity, but still no matter what I do. OnLoadFinished is never called.
I'm unsure what is causing the problem, as your code is incomplete, however your imports imply you might not use the activity from the support package:
import android.app.Activity;
should be
import android.support.v4.app.FragmentActivity;
i actually don't see how your code could even compile, as the non-support-activity doesn't have a method called getSupportLoaderManager()
without knowing what the actual problem is, i'll post a sample i just created, i boiled down the code to what is actually necessary. Note however that you don't have to implement the LoaderCallback in an activity. This code is working, as i tested it.
package com.suhw.samples.mediastore;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
public class QueryMediaStoreActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private final static String TAG = "QueryMediaStoreActivity";
private static final int LOADER_ID1 = 1;
private static final String[] audioMediaProjection = {MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DATA};
private static final Uri audioMediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LoaderManager loaderManager = getSupportLoaderManager();
loaderManager.initLoader(LOADER_ID1, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
switch (id) {
case LOADER_ID1:
return new CursorLoader(this, audioMediaUri, audioMediaProjection, null, null, MediaStore.Audio.Media.TITLE);
default:
return null;
}
}
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
switch (cursorLoader.getId()) {
case LOADER_ID1:
Log.d(TAG, "onLoadFinished called:\n\tcursorCount:" + cursor.getCount());
break;
}
}
#Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
}
}
Change your OncreateLoader(), If dealing with multiple Loader then better use switch() statement.
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1)
{
CursorLoader cursorLoader = null;
switch (id) {
case LOADER_ID1:
cursorLoader = new CursorLoader(getActivity(), sourceUri, projections, null, null, MediaStore.Audio.Media.TITLE);
break;
case LOADER_ID2:
cursorLoader = new CursorLoader(getActivity(), uriPlaylists, projectionsPlaylist, null, null, MediaStore.Audio.Playlists.NAME);
break;
default:
break;
}
cursorLoader.forceLoad();
return cursorLoader;
}
Edit:-
Use getActivity() instead of act for details CursorLoader
Note:-
The method getLoaderManager() is only available in the Fragment class. To get a LoaderManager in a FragmentActivity, call getSupportLoaderManager().
Try like this.

Maintain filtered listview after rotation in android

I'm using customized ListView in android, and using search with customized EditText. When I search for a name, I will get the result using getFilter().filter(cs);. But, when I rotate, the ListView shows the full list (without filtering), then after a delay, it shows the filtered list.
When I rotate without filtering, it maintains the listview position.
So I have to maintain the filtered ListView when I rotate the screen.
Please help. Thanks in advance...
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Loader;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Display;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
#SuppressLint("HandlerLeak")
public class ContactsListActivity
extends Activity
implements LoaderManager.LoaderCallbacks<ArrayList<ListViewItem>> {
private LetterScrollListView mLSListView;
private ProgressBar mProgressBar;
private EditText mSearchText;
private ProgressBar mSearchProgressBar;
private LinearLayout mViewsLl;
private ContactAdapter mFullContactAdapter = null;
private ArrayList<ListViewItem> mFullContactsArrayList = null;
public boolean isSoftKeyOn = false;
public boolean isPortrait;
private long mLastTimeTextChanged = 0L;
private long mCurrentTime = 0L;
private Filter mFilter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts_list);
RelativeLayout windowRl = (RelativeLayout) findViewById(R.id.window_RelativeLayout);
LinearLayout progressBarLl = (LinearLayout) windowRl.findViewById(R.id.progressBar_LinearLayout);
mViewsLl = (LinearLayout) windowRl.findViewById(R.id.views_LinearLayout);
mSearchText = (EditText) mViewsLl.findViewById(R.id.contact_SearchEditText);
mSearchProgressBar = (ProgressBar) mViewsLl.findViewById(R.id.search_ProgressBar);
mLSListView = (LetterScrollListView) mViewsLl.findViewById(R.id.contacts_LetterScrollListView);
mLSListView.setSearchText(mSearchText);
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
isPortrait = true;
} else {
isPortrait = false;
}
final View activityRootView = windowRl;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView()
.getHeight() - activityRootView.getHeight();
// if heightDiff > 100 pixels, its probably a keyboard...
if (heightDiff > 100) {
// Toast.makeText(getApplicationContext(), "Key ON",
// Toast.LENGTH_SHORT).show();
isSoftKeyOn = true;
} else {
// Toast.makeText(getApplicationContext(), "Key OFF",
// Toast.LENGTH_SHORT).show();
isSoftKeyOn = false;
mSearchText.clearFocus();
}
}
});
mSearchText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2,
int arg3) {
mCurrentTime = System.currentTimeMillis();
if( (mCurrentTime - mLastTimeTextChanged) <= USER_TYPE_DELAY ) {
mSearchInputHandler.removeMessages(WHAT_SEARCH);
}
// preparing message
Bundle bundle = new Bundle();
bundle.putCharSequence(USER_INPUT_KEY, cs);
Message message = mSearchInputHandler.obtainMessage(WHAT_SEARCH);
message.setData(bundle);
mSearchInputHandler.sendMessageDelayed(message, USER_TYPE_DELAY);
mLastTimeTextChanged = mCurrentTime;
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
// Create a progress bar to display while the list loads
mProgressBar = new ProgressBar(this);
mProgressBar.setIndeterminate(true);
progressBarLl.addView(mProgressBar);
getLoaderManager().initLoader(0, null, this).forceLoad();
}
#SuppressLint("HandlerLeak")
private final Handler mSearchInputHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
CharSequence cs = msg.getData().getCharSequence(USER_INPUT_KEY);
int what = msg.what;
switch(what) {
case WHAT_SEARCH:
// When user changed the Text after a delay
mSearchProgressBar.setVisibility(View.VISIBLE);
mFilter.filter(cs);
break;
}
}
};
public void removeSearchProgressBar() {
mSearchProgressBar.setVisibility(View.INVISIBLE);
}
/**
* Called when a new Loader needs to be created
*/
public Loader<ArrayList<ListViewItem>> onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME
};
boolean showInvisible = false;
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
(showInvisible ? "0" : "1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return new ContactArrayListLoader(this, uri, projection, selection, selectionArgs, sortOrder);
}
/**
* Called when a previously created loader has finished loading
*/
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {
mProgressBar.setVisibility(View.INVISIBLE);
if(mLSListView.getAdapter() == null) {
mFullContactsArrayList = data;
mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, mFullContactsArrayList);
mFilter = mFullContactAdapter.getFilter();
mLSListView.setAdapter(mFullContactAdapter);
}
}
/**
* Called when a previously created loader is reset, making the data unavailable
*/
public void onLoaderReset(Loader<ArrayList<ListViewItem>> 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.
//////mListView.setAdapter(new ContactAdapter(this, R.layout.contact_tuple, null));
mProgressBar.setVisibility(View.VISIBLE);
}
}
SOLVED
The problem is on the method
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {....}
On rotation/starting the app, the parameter data in this method is always the complete list and not the filtered list. So to get the filtered list on rotation, just create a static member
private static ArrayList<ListViewItem> sCurrentContactsArrayList = null;
and save before screen rotation like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if( TextUtils.isEmpty(mSearchText.getText()) ) {
sCurrentContactsArrayList = null;
} else {
sCurrentContactsArrayList = mFullContactAdapter.getCurrentItems();
}
}
also modify onLoadFinished():
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {
mProgressBar.setVisibility(View.INVISIBLE);
if(mLSListView.getAdapter() == null) {
ArrayList<ListViewItem> contactsAL = null;
if(sCurrentContactsArrayList == null) {
contactsAL = data;
} else {
contactsAL = sCurrentContactsArrayList;
}
mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, contactsAL, data);
if(mFilter == null) mFilter = mFullContactAdapter.getFilter();
mLSListView.setAdapter(mFullContactAdapter);
}
mSearchText.setVisibility(View.VISIBLE);
}

LoaderManager not initializing... a issue with getLoaderManager().initLoader

I know there is a lot of common questions like this out there but I just can't seem to find the solution. When I attempt to initialize my loader using getLoaderManager().initLoader(LOADER_ID, null, this); The error The method initLoader(int, Bundle, LoaderManager.LoaderCallbacks) in the type LoaderManager is not applicable for the arguments (int, null, Gridview) comes up.
This leads me to believe that the program is not recognizing that Gridview implements the loader manager. I'm not sure why this is and where to go from here. I tried playing around with different imports but that didn't work. I also made sure I had the proper downloads to support loaders. The code I am using is below.
package com.example.camerapreview;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
//Omissis imports
public class Gridview extends Activity implements LoaderManager.LoaderCallbacks<Cursor>{
private static final String TAG = "Checking Database";
private static final String TAG1 = "Checking Thumbnail";
Cursor cursor;
int columnindexid;
int columnindexdata;
int videoidindex;
int videopathindex;
GridviewData entry;
GridView gridview;
VideoAdapter videoadapter;
Cursor curs;
ImageLoaderConfiguration config;
String[] mediaColumns = {
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.MIME_TYPE
};
private static final int LOADER_ID = 1;
int flags = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preview);
gridview = (GridView) this.findViewById(R.id.gridview);
cursor = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, mediaColumns, null, null, null);
columnindexid = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
columnindexdata = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
entry = new GridviewData(this);
entry.open();
getLoaderManager().initLoader(LOADER_ID, null, this);
DataEntry putitin = new DataEntry(entry, this);
putitin.execute();
//the cursor used in the cursor adapater
curs = entry.adapterCursor();
videoidindex = entry.Indexfinder(curs);
videopathindex = entry.Indexfinder2(curs);
config = new ImageLoaderConfiguration.Builder(this)
.imageDownloader(new BaseImageDownloader(this))
.build();
ImageLoader.getInstance().init(config);
Log.i(TAG, "Before set adapater");
gridview.setAdapter(new VideoAdapter(this, curs, flags));
}
}
EDIT:
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { GridviewData.VIDEOID, GridviewData.VIDEOFILEPATH };
return new CursorLoader(Gridview.this, MyContentProvider.CONTENT_URI, projection, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
cursoradapter.swapCursor(c);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
cursoradapter.swapCursor(null);
}
The error is caused by your imports:
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
they would be fine for FragmentActivity but you are using a normal Activity so they should be:
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.widget.CursorAdapter;
Please note that in this case your android:minSdkVersion should be 11. If you need compatibility with lower versions, just keep the imports as they are and use FragmentActivity.

Android: Database help -Return all items in a specific column

i am really stuck. I am familiar in Java and Android development but i do not have any experience with databases. This is my first time. I have been going through multiple tutorials but i cannot figure out how return all the values from a specific row and set it to a single string.
Below is my database console. I was able to get all the items and display it in my view but i intended on writing a specific function to do something with all the data in only the TITLE column. Can anyone shed any light or provide a small routine to get all the items from the TITLE column into a single string? The very last function is my getTitleList that is where i would like to gather the data
Here is the function:
public void getTitleList(){
cursor = db.rawQuery("SELECT TITLE FROM table", null);
cursor.close();
}
Here is my class
package edu.asu;
import java.util.ArrayList;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import android.view.View;
import android.app.ListActivity;
import static android.provider.BaseColumns._ID;
public class DbBookConsole extends ListActivity {
private static String[] FROM = { _ID, DbConstants.TITLE, DbConstants.PRICE,
DbConstants.ISBN, DbConstants.CHECKIN };
private DbCreate books;
private static SQLiteDatabase db;
private static int[] TO = { R.id.rowid, R.id.name, R.id.price, R.id.isbn, R.id.checkin};
private ListView lv1;
private static String itemId;
private static String titles;
private static String test;
private Cursor cursor;
static final int BOOK_CANCELED = 0;
static final int BOOK_ADDED = 1;
static final int BOOK_MODIFIED = 2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showDatabaseContent();
lv1 = getListView();
lv1.setTextFilterEnabled(true);
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position,
long id) {
cursor = (Cursor) a.getItemAtPosition(position);
itemId = cursor.getString(0);
openOptionsMenu();
}
});
lv1.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
// selected item index from ListView
public void showDialogItemId(long itemId) {
Toast.makeText(this,
"Menu item selected index is" + Long.toString(itemId),
Toast.LENGTH_LONG).show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.modifyitem:
if (null != itemId) {
Bundle bookToModify = new Bundle();
bookToModify.putString("cTitle", cursor.getString(1));
bookToModify.putString("cPrice", cursor.getString(2));
bookToModify.putString("cISBN", cursor.getString(3));
bookToModify.putString("cCheckin", cursor.getString(4));
bookToModify.putString("mod_type", "modifyBook");
Intent intent = new Intent(this, BookDetails.class);
intent.setClass(this, BookDetails.class);
intent.putExtras(bookToModify);
startActivityForResult(intent, BOOK_MODIFIED);
} else {
Toast
.makeText(this, "Select Book to modify",
Toast.LENGTH_LONG).show();
}
break;
case R.id.additem:
Intent i = new Intent(this, BookDetails.class);
Bundle bun = new Bundle();
bun.putString("mod_type", "addBook");
i.setClass(this, BookDetails.class);
i.putExtras(bun);
startActivityForResult(i, BOOK_ADDED);
break;
case R.id.removeitem:
if (null != itemId) {
removeBook(itemId);
showDatabaseContent();
} else {
Toast
.makeText(this, "Select Book to delete",
Toast.LENGTH_LONG).show();
}
break;
}
return true;
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
// See which child activity is calling us back.
switch (resultCode) {
case BOOK_ADDED:
// This is the standard resultCode that is sent back if the
// activity crashed or didn't doesn't supply an explicit result.
if (resultCode == RESULT_FIRST_USER) {
Bundle bundle = new Bundle();
bundle = intent.getBundleExtra("bookData");
addBook(bundle);
showDatabaseContent();
} else {
Toast.makeText(this, "CANCEL BOOK BUTTON PRESSED",
Toast.LENGTH_LONG).show();
}
break;
case BOOK_MODIFIED:
if (resultCode == 2) {
Bundle bundle = new Bundle();
bundle = intent.getBundleExtra("bookData");
modifyBook(bundle);
showDatabaseContent();
} else {
Toast.makeText(this, "MODIFY BOOK FAILED", Toast.LENGTH_LONG)
.show();
}
break;
default:
break;
}
}
// method removes item from database
private void removeBook(String itemId) {
db = books.getWritableDatabase();
db.delete(DbConstants.TABLE_NAME, "_ID=" + itemId, null);
}
private void addBook(Bundle bundle) {
// Insert a new record into the Events data source.
// You would do something similar for delete and update.
db = books.getWritableDatabase();
ContentValues vals = new ContentValues();
vals.put(DbConstants.TITLE, bundle.getString("bookTitle"));
vals.put(DbConstants.PRICE, bundle.getString("bookPrice"));
vals.put(DbConstants.ISBN, bundle.getString("bookISBN"));
vals.put(DbConstants.CHECKIN, bundle.getString("bookCheck"));
db.insertOrThrow(DbConstants.TABLE_NAME, null, vals);
}
// method should modify existing Contact
private void modifyBook(Bundle bundle) {
db = books.getWritableDatabase();
ContentValues vals = new ContentValues();
vals.put(DbConstants.TITLE, bundle.getString("bookTitle"));
vals.put(DbConstants.PRICE, bundle.getString("bookPrice"));
vals.put(DbConstants.ISBN, bundle.getString("bookISBN"));
vals.put(DbConstants.CHECKIN, bundle.getString("bookCheck"));
db.update(DbConstants.TABLE_NAME, vals, _ID + "=" + itemId, null);
}
private Cursor getBooks() {
db = books.getReadableDatabase();
cursor = db.query(DbConstants.TABLE_NAME, FROM, null, null, null, null, null,
null);
startManagingCursor(cursor);
return cursor;
}
public void showDatabaseContent() {
books = new DbCreate(this);
try {
cursor = getBooks();
showBooks(cursor);
} finally {
books.close();
db.close();
}
}
private void showBooks(Cursor cursor) {
// set up data binding
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.item, cursor, FROM, TO);
setListAdapter(adapter);
}
public void getTitleList(){
cursor = db.rawQuery("SELECT TITLE FROM table", null);
cursor.close();
}
}
unless i missunderstood the Question to get all items from your query in a cursor, loop through all items and concatenate into a string you would do something like this:
// constants of column indexes
int INDEX_ROWID = 0;
int INDEX_TITLE = 1;
...
db = new MyDBAdapter(this);
db.open();
Cursor c = db.getTitleList();
startManagingCursor(c);
String allTitles;
// loop through cursor
while(c.moveToNext()) {
allTitles += c.getString(INDEX_TITLE);
}
Hope that helps

Categories

Resources