blob: 2e2db31e909871d45a511f4169c83bcc2d5b4050 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.phone;
import static android.view.Window.PROGRESS_VISIBILITY_OFF;
import static android.view.Window.PROGRESS_VISIBILITY_ON;
import android.app.ListActivity;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Window;
import android.widget.CursorAdapter;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
/**
* Abbreviated Dial Numbers (ADN) list activity for the Phone app. By default, this class will show
* you all Service Dialing Numbers (SDN) that are supported by a service provider. SDNs are a form
* of speed dial for accessing service provider contacts like "#MIN" for getting user minutes.
* To see this class in use, trigger the radio info screen by dialing *#*#INFO#*#* and open the
* menu.
* This class can also be used as a base class for simple contact lists that can be represented with
* only labels and numbers.
*/
public class ADNList extends ListActivity {
protected static final String TAG = "ADNList";
protected static final boolean DBG = false;
private static final String[] COLUMN_NAMES = new String[] {
"name",
"number",
"emails"
};
protected static final int NAME_COLUMN = 0;
protected static final int NUMBER_COLUMN = 1;
protected static final int EMAILS_COLUMN = 2;
private static final int[] VIEW_NAMES = new int[] {
android.R.id.text1,
android.R.id.text2
};
protected static final int QUERY_TOKEN = 0;
protected static final int INSERT_TOKEN = 1;
protected static final int UPDATE_TOKEN = 2;
protected static final int DELETE_TOKEN = 3;
protected QueryHandler mQueryHandler;
protected CursorAdapter mCursorAdapter;
protected Cursor mCursor = null;
private TextView mEmptyText;
protected int mInitialSelection = -1;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.adn_list);
mEmptyText = (TextView) findViewById(android.R.id.empty);
mQueryHandler = new QueryHandler(getContentResolver());
}
@Override
protected void onResume() {
super.onResume();
query();
}
@Override
protected void onStop() {
super.onStop();
if (mCursor != null) {
mCursor.deactivate();
}
}
protected Uri resolveIntent() {
Intent intent = getIntent();
if (intent.getData() == null) {
intent.setData(Uri.parse("content://icc/adn"));
}
return intent.getData();
}
private void query() {
Uri uri = resolveIntent();
if (DBG) log("query: starting an async query");
mQueryHandler.startQuery(QUERY_TOKEN, null, uri, COLUMN_NAMES,
null, null, null);
displayProgress(true);
}
private void reQuery() {
query();
}
private void setAdapter() {
// NOTE:
// As it it written, the positioning code below is NOT working.
// However, this current non-working state is in compliance with
// the UI paradigm, so we can't really do much to change it.
// In the future, if we wish to get this "positioning" correct,
// we'll need to do the following:
// 1. Change the layout to in the cursor adapter to:
// android.R.layout.simple_list_item_checked
// 2. replace the selection / focus code with:
// getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// getListView().setItemChecked(mInitialSelection, true);
// Since the positioning is really only useful for the dialer's
// SpecialCharSequence case (dialing '2#' to get to the 2nd
// contact for instance), it doesn't make sense to mess with
// the usability of the activity just for this case.
// These artifacts include:
// 1. UI artifacts (checkbox and highlight at the same time)
// 2. Allowing the user to edit / create new SIM contacts when
// the user is simply trying to retrieve a number into the d
// dialer.
if (mCursorAdapter == null) {
mCursorAdapter = newAdapter();
setListAdapter(mCursorAdapter);
} else {
mCursorAdapter.changeCursor(mCursor);
}
if (mInitialSelection >=0 && mInitialSelection < mCursorAdapter.getCount()) {
setSelection(mInitialSelection);
getListView().setFocusableInTouchMode(true);
boolean gotfocus = getListView().requestFocus();
}
}
protected CursorAdapter newAdapter() {
return new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_2,
mCursor, COLUMN_NAMES, VIEW_NAMES);
}
private void displayProgress(boolean loading) {
if (DBG) log("displayProgress: " + loading);
mEmptyText.setText(loading ? R.string.simContacts_emptyLoading:
(isAirplaneModeOn(this) ? R.string.simContacts_airplaneMode :
R.string.simContacts_empty));
getWindow().setFeatureInt(
Window.FEATURE_INDETERMINATE_PROGRESS,
loading ? PROGRESS_VISIBILITY_ON : PROGRESS_VISIBILITY_OFF);
}
private static boolean isAirplaneModeOn(Context context) {
return Settings.System.getInt(context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) != 0;
}
private class QueryHandler extends AsyncQueryHandler {
public QueryHandler(ContentResolver cr) {
super(cr);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor c) {
if (DBG) log("onQueryComplete: cursor.count=" + c.getCount());
mCursor = c;
setAdapter();
displayProgress(false);
// Cursor is refreshed and inherited classes may have menu items depending on it.
invalidateOptionsMenu();
}
@Override
protected void onInsertComplete(int token, Object cookie, Uri uri) {
if (DBG) log("onInsertComplete: requery");
reQuery();
}
@Override
protected void onUpdateComplete(int token, Object cookie, int result) {
if (DBG) log("onUpdateComplete: requery");
reQuery();
}
@Override
protected void onDeleteComplete(int token, Object cookie, int result) {
if (DBG) log("onDeleteComplete: requery");
reQuery();
}
}
protected void log(String msg) {
Log.d(TAG, "[ADNList] " + msg);
}
}