| /* |
| * Copyright (C) 2014 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.interactions; |
| |
| import android.content.AsyncTaskLoader; |
| import android.content.ContentValues; |
| import android.content.Context; |
| import android.content.pm.PackageManager; |
| import android.database.Cursor; |
| import android.database.DatabaseUtils; |
| import android.provider.Telephony; |
| import android.util.Log; |
| |
| import com.android.contacts.common.compat.TelephonyThreadsCompat; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * Loads the most recent sms between the passed in phone numbers. |
| * |
| * This is a two part process. The first step is retrieving the threadIds for each of the phone |
| * numbers using fuzzy matching. The next step is to run another query against these threadIds |
| * to retrieve the actual sms. |
| */ |
| public class SmsInteractionsLoader extends AsyncTaskLoader<List<ContactInteraction>> { |
| |
| private static final String TAG = SmsInteractionsLoader.class.getSimpleName(); |
| |
| private String[] mPhoneNums; |
| private int mMaxToRetrieve; |
| private List<ContactInteraction> mData; |
| |
| /** |
| * Loads a list of SmsInteraction from the supplied phone numbers. |
| */ |
| public SmsInteractionsLoader(Context context, String[] phoneNums, |
| int maxToRetrieve) { |
| super(context); |
| Log.v(TAG, "SmsInteractionsLoader"); |
| mPhoneNums = phoneNums; |
| mMaxToRetrieve = maxToRetrieve; |
| } |
| |
| @Override |
| public List<ContactInteraction> loadInBackground() { |
| Log.v(TAG, "loadInBackground"); |
| // Confirm the device has Telephony and numbers were provided before proceeding |
| if (!getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY) |
| || mPhoneNums == null || mPhoneNums.length == 0) { |
| return Collections.emptyList(); |
| } |
| |
| // Retrieve the thread IDs |
| List<String> threadIdStrings = new ArrayList<>(); |
| for (String phone : mPhoneNums) { |
| // TODO: the phone numbers added to the ContactInteraction result should retain their |
| // original formatting since TalkBack is not reading the normalized numbers correctly |
| try { |
| threadIdStrings.add(String.valueOf( |
| TelephonyThreadsCompat.getOrCreateThreadId(getContext(), phone))); |
| } catch (Exception e) { |
| // Do nothing. Telephony.Threads.getOrCreateThreadId() throws exceptions when |
| // it can't find/create a threadId (b/17657656). |
| } |
| } |
| |
| // Query the SMS database for the threads |
| Cursor cursor = getSmsCursorFromThreads(threadIdStrings); |
| if (cursor != null) { |
| try { |
| List<ContactInteraction> interactions = new ArrayList<>(); |
| while (cursor.moveToNext()) { |
| ContentValues values = new ContentValues(); |
| DatabaseUtils.cursorRowToContentValues(cursor, values); |
| interactions.add(new SmsInteraction(values)); |
| } |
| |
| return interactions; |
| } finally { |
| cursor.close(); |
| } |
| } |
| |
| return Collections.emptyList(); |
| } |
| |
| /** |
| * Return the most recent messages between a list of threads |
| */ |
| private Cursor getSmsCursorFromThreads(List<String> threadIds) { |
| if (threadIds.size() == 0) { |
| return null; |
| } |
| String selection = Telephony.Sms.THREAD_ID + " IN " |
| + ContactInteractionUtil.questionMarks(threadIds.size()); |
| |
| return getContext().getContentResolver().query( |
| Telephony.Sms.CONTENT_URI, |
| /* projection = */ null, |
| selection, |
| threadIds.toArray(new String[threadIds.size()]), |
| Telephony.Sms.DEFAULT_SORT_ORDER |
| + " LIMIT " + mMaxToRetrieve); |
| } |
| |
| @Override |
| protected void onStartLoading() { |
| super.onStartLoading(); |
| |
| if (mData != null) { |
| deliverResult(mData); |
| } |
| |
| if (takeContentChanged() || mData == null) { |
| forceLoad(); |
| } |
| } |
| |
| @Override |
| protected void onStopLoading() { |
| // Attempt to cancel the current load task if possible. |
| cancelLoad(); |
| } |
| |
| @Override |
| public void deliverResult(List<ContactInteraction> data) { |
| mData = data; |
| if (isStarted()) { |
| super.deliverResult(data); |
| } |
| } |
| |
| @Override |
| protected void onReset() { |
| super.onReset(); |
| |
| // Ensure the loader is stopped |
| onStopLoading(); |
| if (mData != null) { |
| mData.clear(); |
| } |
| } |
| } |