I followed the effective navigation example. to build a new app. Basically what I want is each SMS should appear in my app on a new screen (Fragment), and scrollable, like Gmail messages in Gmail App
Here is the code for the same
package com.example.android.effectivenavigation;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Locale;
import android.app.ActionBar;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.NavUtils;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class CollectionDemoActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide fragments representing each object in a
* collection. We use a {@link android.support.v4.app.FragmentStatePagerAdapter} derivative, which will destroy and
* re-create fragments as needed, saving and restoring their state in the process. This is important to conserve
* memory and is a best practice when allowing navigation between objects in a potentially large collection.
*/
DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
/**
* The {@link android.support.v4.view.ViewPager} that will display the object collection.
*/
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collection_demo);
//-----------------------THIS BLOCK WORK JUST FINE--------------------------
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
cursor.moveToFirst();
do {
String msgData = "a";
for (int idx = 0; idx < cursor.getColumnCount(); idx++) {
msgData += " " + cursor.getColumnName(idx) + ":" + cursor.getString(idx);
}
Date date = new Date(Long.parseLong(cursor.getString(5)));
SimpleDateFormat sdf = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz",Locale.ENGLISH);
System.out.println("Cursor123"+msgData + "\r Dateeeee" + sdf.format(date));
} while (cursor.moveToNext());
//-----------------------------END BLOCK ----------------------------------
// Create an adapter that when requested, will return a fragment representing an object in
// the collection.
//
// ViewPager and its adapters use support library fragments, so we must use
// getSupportFragmentManager.
mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter(getSupportFragmentManager());
// Set up action bar.
final ActionBar actionBar = getActionBar();
// Specify that the Home button should show an "Up" caret, indicating that touching the
// button will take the user one step up in the application's hierarchy.
actionBar.setDisplayHomeAsUpEnabled(true);
// Set up the ViewPager, attaching the adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
getSupportLoaderManager().initLoader(0, null, this);
mAdapter = new SimpleCursorAdapter(this, R.layout.activity_collection_demo, null, null, null, 0);
Cursor cursor1 = mAdapter.getCursor();
mDemoCollectionPagerAdapter.setCount(cursor1.getCount());
mViewPager.setAdapter(mDemoCollectionPagerAdapter);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent upIntent = new Intent(this, MainActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is not part of the application's task, so create a new task
// with a synthesized back stack.
TaskStackBuilder.from(this)
// If there are ancestor activities, they should be added here.
.addNextIntent(upIntent).startActivities();
finish();
} else {
// This activity is part of the application's task, so simply
// navigate up to the hierarchical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A {@link android.support.v4.app.FragmentStatePagerAdapter} that returns a fragment representing an object in the
* collection.
*/
public static class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
public DemoCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
private int count;
@Override
public Fragment getItem(int i) {
Fragment fragment = new DemoObjectFragment();
Bundle args = new Bundle();
args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
fragment.setArguments(args);
return fragment;
}
@Override
public int getCount() {
// temporarily setting count to 5
return 5;
}
public void setCount( int iCount) {
this.count=iCount;
}
@Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
}
/**
* A dummy fragment representing a section of the app, but that simply displays dummy text.
*/
public static class DemoObjectFragment extends Fragment {
public static final String ARG_OBJECT = "object";
Cursor cursor;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_collection_object, container, false);
Bundle args = getArguments();
((TextView) rootView.findViewById(android.R.id.text1)).setText(Integer.toString(args.getInt(ARG_OBJECT)));
// cursor.move(args.getInt(ARG_OBJECT));
TextView tv1 = (TextView) getActivity().findViewById(R.id.editText1);
tv1.setText("Test");
return rootView;
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri baseUri = Uri.parse("content://sms/inbox");
return new CursorLoader(this, baseUri, null, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
Here is the stacktrace for the exception:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.effectivenavigation/com.example.android.effectivenavigation.CollectionDemoActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.android.effectivenavigation.CollectionDemoActivity.onCreate(CollectionDemoActivity.java:108)
at android.app.Activity.performCreate(Activity.java:4465)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
... 11 more
Line 108 corresponds to
“mDemoCollectionPagerAdapter.setCount(cursor1.getCount());”
Your
SimpleCursorAdapterstarts(and has until theLoaderdoes it’s job) with a nullCursorat that moment so :will throw that exception because
cursor1isnull. Instead you should update theViewPager‘scountvariable in theonLoadFinishedcallback because at that moment theCursorshould be valid and you can get the number of rows there are in it.