Reputation: 77
I am creating an address book application and I want to get contact images from the Contact address book database. I keep getting this Uri error. It seems the error is at line: 97 that is @ thumb.setImageURI(uri);
. Please assist me on what to do. Thanks.
This is my AddressBook.java class
package com.rufflez.viewpagerexample;
import android.support.v4.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
public class AddressBook extends ListFragment implements
LoaderCallbacks<Cursor>{
private CursorAdapter mAdapter;
public ListView listView;
public Cursor cursor;
public static final String[] FROM = { ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_THUMBNAIL_URI };
private static final int[] TO = { R.id.text_name, R.id.contact_thumbnail };
int layout = R.layout.contact_list_item;
// Name should be displayed in the text1 TextView in item layout
private Context context;
public View view;
public static Uri uri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// delete list if already there (old version)
if (!(listView == null)){
listView.setAdapter(null);
}
// create adapter once
context = getActivity();
int layout = android.R.layout.simple_list_item_1;
Cursor c = null; // there is no cursor yet
int flags = 0; // no auto-requery! Loader requeries.
// put List in adapter
mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);
} // end onCreate
// columns requested from the database
private static final String[] PROJECTION = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.IN_VISIBLE_GROUP
};
// this goes in the CursorLoader parameter list, it filters
// out only those contacts who have a phone number
private static final String SELECTION =
ContactsContract.Contacts.HAS_PHONE_NUMBER + "='1'";
// Empty public constructor, required by the system
public AddressBook() {}
// A UI Fragment must inflate its View (all fragments must override onCreateView)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the fragment layout
View view = inflater.inflate(R.layout.contact_list_view,
container, false);
listView = (ListView) view.findViewById(R.id.list);
// set Contact photo to ImageView
AddressBook frag = new AddressBook();
ImageView thumb = (ImageView)view.findViewById(R.id.contact_thumbnail);
frag.getPhotoUriFromID(ContactsContract.Contacts._ID);
thumb.setImageURI(uri);
return view;
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// and tell loader manager to start loading
// getLoaderManager().initLoader(0, null, this);
listView.setAdapter(mAdapter);
listView.setFastScrollEnabled(true);
}
// a CursorLoader does a query in the background
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// load from the "Contacts table"
Uri contentUri = Contacts.CONTENT_URI;
// no sub-selection, no sort order, simply every row
// projection says we want just the _id and the name column
return new CursorLoader(getActivity(),
contentUri,
PROJECTION,
SELECTION,
null,
ContactsContract.Contacts.DISPLAY_NAME
);
}
private Uri getPhotoUriFromID(String id) {
try {
Cursor cur = context.getContentResolver()
.query(ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.CONTACT_ID
+ "="
+ id
+ " AND "
+ ContactsContract.Data.MIMETYPE
+ "='"
+ ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
+ "'", null, null);
if (cur != null) {
if (!cur.moveToFirst()) {
return null; // no photo
}
} else {
return null; // error in cursor process
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
Uri person = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
uri = Uri.withAppendedPath(person,
ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
return uri;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Once cursor is loaded, give it to adapter
mAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// Delete the reference to the existing Cursor,
// so it can recycle it
mAdapter.swapCursor(null);
}
}
This is contact_list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
This is my contact_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/contact_thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/text_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"/>
</LinearLayout>
This is my Logcat error
09-03 20:08:15.241: E/AndroidRuntime(5257): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageURI(android.net.Uri)' on a null object reference
09-03 20:08:15.241: E/AndroidRuntime(5257): at com.rufflez.viewpagerexample.AddressBook.onCreateView(AddressBook.java:97)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:478)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.view.ViewPager.populate(ViewPager.java:1068)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1436)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.view.View.measure(View.java:18580)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.widget.LinearLayout.measureVertical(LinearLayout.java:874)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.widget.LinearLayout.onMeasure(LinearLayout.java:612)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.view.View.measure(View.java:18580)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5827)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.view.View.measure(View.java:18580)
09-03 20:08:15.241: E/AndroidRuntime(5257): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5827)
09-03 20:08:15.241: E/AndroidRuntime(5257): at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:447)
Upvotes: 0
Views: 820
Reputation: 7686
You're trying to set a uri that "doesn't exist"... thumb.setImageURI(uri); will always be null.
The thumbnail image I assume it goes in your listview, so... you need to set:
thumb.setImageURI(uri); inside your custom adapter.
The way you do it now (with the details of bad location in your code), once the app loads, is trying to get an uri even before setting an adapter, getting the data, etc... uri gets always null.
Upvotes: 1
Reputation: 8572
i had an issue with Uri. When my activity recreated, it setted a value of variable Uri to null. And this fact crashed my app because it saved instance with it. How to prevent this? Somehow save value of Uri variable. To sqlite, sharedpreferences or bundle or any other choose. And when recreates check it's value to be not null. And if it is true, get saved value from memory. As i remind call Uri.parseString or smth similar. i think you have such issue. Good luck!
Upvotes: 0
Reputation: 67259
Your Fragment uses the contact_list_view.xml
layout, which contains only a single ListView
. When that list is first inflated, it contains no children, and thus (ImageView)view.findViewById(R.id.contact_thumbnail);
will return null because all you have is a single ListView
.
The core issue is that it is the adapter's job to inflate and populate the child views for the ListView
. You should not be trying to reference any of the Views in contact_list_item.xml
from within your Fragment. Not only is it entirely possible that those views don't exist yet, doing so would also limit you to working with only one row of the list instead of populating each row with its respective data.
Upvotes: 0