diff options
-rw-r--r-- | AndroidManifest.xml | 5 | ||||
-rw-r--r-- | res/layout/contact_memory_list.xml | 72 | ||||
-rw-r--r-- | res/layout/memory_account_list_item.xml | 129 | ||||
-rw-r--r-- | res/menu/people_options.xml | 4 | ||||
-rw-r--r-- | src/com/android/contacts/activities/MemoryStatusActivity.java | 278 | ||||
-rw-r--r-- | src/com/android/contacts/activities/PeopleActivity.java | 6 |
6 files changed, 494 insertions, 0 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 926ae8bd3..d8532ff2c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -209,6 +209,11 @@ android:label="@string/activity_title_contacts_filter" android:theme="@style/ContactListFilterTheme" /> + <activity + android:name=".activities.MemoryStatusActivity" + android:label="@string/memory_status_title" + android:theme="@style/ContactListFilterTheme" /> + <!-- Used to select display and sync groups --> <activity android:name=".common.list.CustomContactListFilterActivity" diff --git a/res/layout/contact_memory_list.xml b/res/layout/contact_memory_list.xml new file mode 100644 index 000000000..81e1d11ed --- /dev/null +++ b/res/layout/contact_memory_list.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:fillViewport="true"> + + <ListView + android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="0dip" + android:layout_weight="1" + android:divider="@null" + android:layout_marginLeft="@dimen/contact_filter_left_margin" + android:layout_marginRight="@dimen/contact_filter_right_margin" + android:layout_marginStart="@dimen/contact_filter_left_margin" + android:layout_marginEnd="@dimen/contact_filter_right_margin" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_marginLeft="16dip" + android:layout_marginRight="16dip" + android:layout_marginStart="16dip" + android:layout_marginEnd="16dip" + android:background="?android:attr/dividerHorizontal" /> + + <ScrollView android:id="@+id/empty" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fadingEdge="none" + android:fillViewport="true" + android:visibility="gone"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/calculating_status_now" + android:textSize="20sp" + android:textColor="?android:attr/textColorSecondary" + android:gravity="center"/> + </ScrollView> +</LinearLayout> diff --git a/res/layout/memory_account_list_item.xml b/res/layout/memory_account_list_item.xml new file mode 100644 index 000000000..868905e6d --- /dev/null +++ b/res/layout/memory_account_list_item.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginTop="10dip" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/list_section_divider_holo_custom" + android:orientation="horizontal" + android:paddingStart="10dip" + android:paddingEnd="10dip" > + + <TextView + android:id="@+id/account_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:ellipsize="middle" + android:singleLine="true" + android:textSize="12sp" /> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="48dp" + android:layout_centerVertical="true" + android:layout_marginStart="10dp" + android:orientation="horizontal" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:singleLine="true" + android:layout_gravity="center_vertical" + android:text="@string/memory_used" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <TextView + android:id="@+id/count_cur" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:paddingStart="5dip" + android:layout_gravity="center_vertical" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:attr/textColorSecondary" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/totally" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:orientation="vertical" + android:visibility="gone" > + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?android:attr/dividerHorizontal"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="48dp" + android:layout_centerVertical="true" + android:layout_marginStart="10dp" + android:orientation="horizontal" > + <TextView + android:id="@+id/totalLabel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:singleLine="true" + android:layout_gravity="center_vertical" + android:text="@string/memory_size" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <TextView + android:id="@+id/count_max" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:paddingStart="5dip" + android:layout_gravity="center_vertical" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:attr/textColorSecondary" /> + </LinearLayout> + </LinearLayout> + </LinearLayout> + +</LinearLayout> diff --git a/res/menu/people_options.xml b/res/menu/people_options.xml index 1dd4dc4db..e561f6137 100644 --- a/res/menu/people_options.xml +++ b/res/menu/people_options.xml @@ -41,6 +41,10 @@ android:title="@string/menu_settings" /> <item + android:id="@+id/menu_memory_status" + android:title="@string/menu_memory_status" /> + + <item android:id="@+id/menu_help" android:title="@string/menu_help" /> diff --git a/src/com/android/contacts/activities/MemoryStatusActivity.java b/src/com/android/contacts/activities/MemoryStatusActivity.java new file mode 100644 index 000000000..57304b2f5 --- /dev/null +++ b/src/com/android/contacts/activities/MemoryStatusActivity.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * + * Not a Contribution. + * + * Copyright (C) 2011 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.contacts.activities; + +import android.app.ActionBar; +import android.content.Context; +import android.content.ContentResolver; +import android.content.Intent; +import android.database.Cursor; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Bundle; +import android.os.Message; +import android.provider.ContactsContract.RawContacts; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; + +import com.android.contacts.ContactsActivity; +import com.android.contacts.common.model.account.AccountType; +import com.android.contacts.common.model.account.AccountWithDataSet; +import com.android.contacts.common.model.AccountTypeManager; +import com.android.contacts.common.MoreContactUtils; +import com.android.contacts.common.SimContactsConstants; +import com.android.contacts.R; +import com.google.android.collect.Lists; + +import java.util.ArrayList; +import java.util.List; + +/** + * Shows a list of all available accounts, letting the user select under which + * account to view contacts. + */ +public class MemoryStatusActivity extends ContactsActivity { + private static final String TAG = "MemoryStatusActivity"; + private static final int INVALID_COUNT = 0; + private ListView mListView; + private View empty; + private List<AccountListItem> mFilters; + private AccountListAdapter mAdapter; + private Handler mHandler; + private LoaderThread mThread = null; + + private final class AccountListItem { + public final String accountType; + public final String accountName; + public final String dataSet; + public final Drawable icon; + public final int total; + public final int count; + + public AccountListItem(String accountType, String accountName, String dataSet, + Drawable icon, int total, int count) { + this.accountType = accountType; + this.accountName = accountName; + this.dataSet = dataSet; + this.icon = icon; + this.total = total; + this.count = count; + } + } + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.contact_memory_list); + + mListView = (ListView) findViewById(android.R.id.list); + empty = (View) findViewById(R.id.empty); + mListView.setEmptyView(empty); + + ActionBar actionBar = getActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + mFilters = Lists.newArrayList(); + mAdapter = new AccountListAdapter(this); + mListView.setAdapter(mAdapter); + + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + mFilters = (List<AccountListItem>) msg.obj; + mAdapter.notifyDataSetChanged(); + } + }; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + onBackPressed(); + return true; + default: + break; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onResume() { + super.onResume(); + if (mFilters.isEmpty()) { + if (mThread == null) { + mThread = new LoaderThread(); + } + try { + mThread.start(); + } catch (Exception e) { + } + } + } + + public class LoaderThread extends Thread { + @Override + public void run() { + List<AccountListItem> list = loadAccountFilters(MemoryStatusActivity.this); + Message msg = Message.obtain(); + msg.obj = list; + mHandler.sendMessage(msg); + } + } + + private List<AccountListItem> loadAccountFilters(Context context) { + final ArrayList<AccountListItem> accountFilters = Lists.newArrayList(); + final AccountTypeManager accountTypes = AccountTypeManager.getInstance(context); + List<AccountWithDataSet> accounts = accountTypes.getAccounts(true); + ContentResolver cr = context.getContentResolver(); + + for (AccountWithDataSet account : accounts) { + AccountType accountType = accountTypes.getAccountType(account.type, account.dataSet); + if (accountType.isExtension() && !account.hasData(context)) { + // Hide extensions with no raw_contacts. + continue; + } + Drawable icon = accountType != null ? accountType.getDisplayIcon(context) : null; + int total = INVALID_COUNT; + int count = INVALID_COUNT; + if (!TextUtils.isEmpty(account.type)) { + if (account.type.equals(SimContactsConstants.ACCOUNT_TYPE_SIM)) { + total = MoreContactUtils.getAdnCount(MoreContactUtils + .getSubscription(account.type, account.name)); + if (total > 0) { + Cursor cursor = cr.query(RawContacts.CONTENT_URI, new String[] { + RawContacts._ID + }, RawContacts.ACCOUNT_NAME + " = '" + account.name + "' AND " + + RawContacts.DELETED + " = 0", null, null); + if (cursor != null) { + try { + count = cursor.getCount(); + } finally { + cursor.close(); + } + } + } + } else { + Cursor cursor = cr.query(RawContacts.CONTENT_URI, new String[] { + RawContacts._ID + }, RawContacts.ACCOUNT_NAME + " = '" + account.name + "' AND " + + RawContacts.DELETED + " = 0", null, null); + if (cursor != null) { + try { + count = cursor.getCount(); + } finally { + cursor.close(); + } + } + } + } + accountFilters.add(new AccountListItem( + account.type, account.name, account.dataSet, icon, total, count)); + } + + return accountFilters; + } + + private class AccountListAdapter extends BaseAdapter { + private final LayoutInflater mLayoutInflater; + private Context accountContext; + + public AccountListAdapter(Context context) { + mLayoutInflater = (LayoutInflater) context.getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + accountContext = context; + } + + @Override + public int getCount() { + return mFilters.size(); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public AccountListItem getItem(int position) { + return mFilters.get(position); + } + + public View getView(int position, View convertView, ViewGroup parent) { + final View view; + AccountListItemViewCache viewCache; + if (convertView != null) { + view = convertView; + viewCache = (AccountListItemViewCache) view.getTag(); + } else { + view = mLayoutInflater.inflate(R.layout.memory_account_list_item, parent, false); + viewCache = new AccountListItemViewCache(view); + view.setTag(viewCache); + } + bindView(position, convertView, parent, viewCache); + return view; + } + + private void bindView(int position, View convertView, ViewGroup parent, + AccountListItemViewCache viewCache) { + final AccountListItem filter = mFilters.get(position); + final AccountTypeManager accountTypes = AccountTypeManager.getInstance(accountContext); + final AccountType accountType = + accountTypes.getAccountType(filter.accountType, filter.dataSet); + viewCache.accountName.setText(accountType.getDisplayLabel(accountContext) + + "<" + filter.accountName + ">"); + viewCache.totally.setVisibility((filter.total != INVALID_COUNT) ? View.VISIBLE + : View.GONE); + viewCache.count_total.setText(Integer.toString(filter.total)); + viewCache.count_cur.setText(Integer.toString(filter.count)); + } + + /** + * Cache of the children views of a contact detail entry represented by + * a {@link GroupListItem} + */ + public class AccountListItemViewCache { + public final TextView accountName; + public final TextView count_total; + public final TextView count_cur; + public final LinearLayout totally; + + public AccountListItemViewCache(View view) { + accountName = (TextView) view.findViewById(R.id.account_name); + count_total = (TextView) view.findViewById(R.id.count_max); + count_cur = (TextView) view.findViewById(R.id.count_cur); + totally = (LinearLayout) view.findViewById(R.id.totally); + } + } + } +} diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java index 2f8b2abe3..aa6f7dc08 100644 --- a/src/com/android/contacts/activities/PeopleActivity.java +++ b/src/com/android/contacts/activities/PeopleActivity.java @@ -1281,6 +1281,12 @@ public class PeopleActivity extends ContactsActivity implements ImplicitIntentsUtil.startActivityOutsideApp(this, intent); return true; } + + case R.id.menu_memory_status: { + final Intent intent = new Intent(this, MemoryStatusActivity.class); + startActivity(intent); + return true; + } } return false; } |