android.database.ContentObserver

Here are the examples of the java api android.database.ContentObserver taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

145 Examples 7

19 Source : SMSHelper.java
with GNU General Public License v2.0
from ZorinOS

/**
 * Register a ContentObserver for the Messages database
 *
 * @param observer ContentObserver to alert on Message changes
 */
public static void registerObserver(@NonNull ContentObserver observer, @NonNull Context context) {
    context.getContentResolver().registerContentObserver(SMSHelper.getConversationUri(), true, observer);
}

19 Source : ContactsProvider.java
with GNU General Public License v3.0
from TBog

public clreplaced ContactsProvider extends Provider<ContactEntry> {

    private final static String TAG = "ContactsProvider";

    private final ContentObserver cObserver = new ContentObserver(null) {

        @Override
        public void onChange(boolean selfChange) {
            // reload contacts
            Log.i(TAG, "Contacts changed, reloading provider.");
            reload(true);
        }
    };

    public void reload(boolean cancelCurrentLoadTask) {
        super.reload(cancelCurrentLoadTask);
        if (!isLoaded() && !isLoading())
            this.initialize(new LoadContactsEntry(this));
    }

    @Override
    public void onCreate() {
        super.onCreate();
        // register content observer if we have permission
        if (Permission.checkPermission(this, Permission.PERMISSION_READ_CONTACTS)) {
            getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, false, cObserver);
        } else {
            Permission.askPermission(Permission.PERMISSION_READ_CONTACTS, new Permission.PermissionResultListener() {

                @Override
                public void onGranted() {
                    // Great! Reload the contact provider. We're done :)
                    reload(true);
                }
            });
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // deregister content observer
        getContentResolver().unregisterContentObserver(cObserver);
    }

    @Override
    public void requestResults(String query, Searcher searcher) {
        StringNormalizer.Result queryNormalized = StringNormalizer.normalizeWithResult(query, false);
        if (queryNormalized.codePoints.length == 0) {
            return;
        }
        FuzzyScore fuzzyScore = new FuzzyScore(queryNormalized.codePoints);
        FuzzyScore.MatchInfo matchInfo;
        boolean match;
        for (ContactEntry pojo : pojos) {
            matchInfo = fuzzyScore.match(pojo.normalizedName.codePoints);
            match = matchInfo.match;
            pojo.setRelevance(pojo.normalizedName, matchInfo);
            if (pojo.normalizedNickname != null) {
                matchInfo = fuzzyScore.match(pojo.normalizedNickname.codePoints);
                if (matchInfo.match && (!match || matchInfo.score > pojo.getRelevance())) {
                    match = true;
                    pojo.setRelevance(pojo.normalizedNickname, matchInfo);
                }
            }
            if (!match && queryNormalized.length() > 2) {
                // search for the phone number
                matchInfo = fuzzyScore.match(pojo.normalizedPhone.codePoints);
                match = matchInfo.match;
                pojo.setRelevance(pojo.normalizedPhone, matchInfo);
            }
            if (match) {
                int boost = Math.min(30, pojo.timesContacted);
                if (pojo.starred) {
                    boost += 40;
                }
                pojo.boostRelevance(boost);
                if (!searcher.addResult(pojo))
                    return;
            }
        }
    }

    /**
     * Find a ContactsPojo from a phoneNumber
     * If many contacts match, the one most often contacted will be returned
     *
     * @param phoneNumber phone number to find (will be normalized)
     * @return a contactpojo, or null.
     */
    public ContactEntry findByPhone(String phoneNumber) {
        StringNormalizer.Result simplifiedPhoneNumber = PhoneNormalizer.simplifyPhoneNumber(phoneNumber);
        for (ContactEntry pojo : pojos) {
            if (pojo.normalizedPhone.equals(simplifiedPhoneNumber)) {
                return pojo;
            }
        }
        return null;
    }
}

19 Source : AMapStateListenerImpl.java
with Apache License 2.0
from skyinu

/**
 * 接口实现类
 * Created by chen on 2017/1/26.
 */
clreplaced AMapStateListenerImpl implements LocationSource, AMapLocationListener, AMap.OnMapLoadedListener {

    /**
     * SDK自身的位置变化监听对象
     */
    private OnLocationChangedListener mLocationChangedListener;

    private AMapStateListener mStateListener;

    public AMapStateListenerImpl() {
    }

    public void setStateListener(@NonNull AMapStateListener stateListener) {
        this.mStateListener = stateListener;
    }

    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        CFLog.i("TAG", "activate");
        this.mLocationChangedListener = onLocationChangedListener;
        mStateListener.notifyServiceActive();
        GlobalApplication.getAppContext().getContentResolver().registerContentObserver(Settings.Secure.getUriFor(android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED), false, mGpsMonitor);
    }

    @Override
    public void deactivate() {
        CFLog.i("TAG", "deactivate");
        mStateListener.notifyServiceDeactivate();
        mLocationChangedListener = null;
        mStateListener = null;
        GlobalApplication.getAppContext().getContentResolver().unregisterContentObserver(mGpsMonitor);
    }

    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        CFLog.i("TAG", "onLocationChanged=" + aMapLocation.toString());
        if (mLocationChangedListener != null && aMapLocation != null && aMapLocation.getErrorCode() == 0) {
            mStateListener.notifyLocationChanged(mLocationChangedListener, aMapLocation);
        }
    }

    @Override
    public void onMapLoaded() {
        mStateListener.notifyMapLoaded();
    }

    private final ContentObserver mGpsMonitor = new ContentObserver(null) {

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            mStateListener.notifyGPSSwitchChanged();
        }
    };
}

19 Source : UserBinaryDictionary.java
with Apache License 2.0
from sergchil

/**
 * An expandable dictionary that stores the words in the user dictionary provider into a binary
 * dictionary file to use it from native code.
 */
public clreplaced UserBinaryDictionary extends ExpandableBinaryDictionary {

    private static final String TAG = ExpandableBinaryDictionary.clreplaced.getSimpleName();

    // The user dictionary provider uses an empty string to mean "all languages".
    private static final String USER_DICTIONARY_ALL_LANGUAGES = "";

    private static final int HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY = 250;

    private static final int LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY = 160;

    private static final String[] PROJECTION_QUERY = new String[] { Words.WORD, Words.FREQUENCY };

    private static final String NAME = "userunigram";

    private ContentObserver mObserver;

    final private String mLocaleString;

    final private boolean mAlsoUseMoreRestrictiveLocales;

    protected UserBinaryDictionary(final Context context, final Locale locale, final boolean alsoUseMoreRestrictiveLocales, final File dictFile, final String name) {
        super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_USER, dictFile);
        // Catch the error earlier
        if (null == locale)
            throw new NullPointerException();
        final String localeStr = locale.toString();
        if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
            // If we don't have a locale, insert into the "all locales" user dictionary.
            mLocaleString = USER_DICTIONARY_ALL_LANGUAGES;
        } else {
            mLocaleString = localeStr;
        }
        mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
        ContentResolver cres = context.getContentResolver();
        mObserver = new ContentObserver(null) {

            @Override
            public void onChange(final boolean self) {
                // This hook is deprecated as of API level 16 (Build.VERSION_CODES.JELLY_BEAN),
                // but should still be supported for cases where the IME is running on an older
                // version of the platform.
                onChange(self, null);
            }

            // The following hook is only available as of API level 16
            // (Build.VERSION_CODES.JELLY_BEAN), and as such it will only work on JellyBean+
            // devices. On older versions of the platform, the hook above will be called instead.
            @Override
            public void onChange(final boolean self, final Uri uri) {
                setNeedsToRecreate();
            }
        };
        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
        reloadDictionaryIfRequired();
    }

    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
    @ExternallyReferenced
    public static UserBinaryDictionary getDictionary(final Context context, final Locale locale, final File dictFile, final String dictNamePrefix, @Nullable final String account) {
        return new UserBinaryDictionary(context, locale, false, /* alsoUseMoreRestrictiveLocales */
        dictFile, dictNamePrefix + NAME);
    }

    @Override
    public synchronized void close() {
        if (mObserver != null) {
            mContext.getContentResolver().unregisterContentObserver(mObserver);
            mObserver = null;
        }
        super.close();
    }

    @Override
    public void loadInitialContentsLocked() {
        // Split the locale. For example "en" => ["en"], "de_DE" => ["de", "DE"],
        // "en_US_foo_bar_qux" => ["en", "US", "foo_bar_qux"] because of the limit of 3.
        // This is correct for locale processing.
        // For this example, we'll look at the "en_US_POSIX" case.
        final String[] localeElements = TextUtils.isEmpty(mLocaleString) ? new String[] {} : mLocaleString.split("_", 3);
        final int length = localeElements.length;
        final StringBuilder request = new StringBuilder("(locale is NULL)");
        String localeSoFar = "";
        // At start, localeElements = ["en", "US", "POSIX"] ; localeSoFar = "" ;
        // and request = "(locale is NULL)"
        for (int i = 0; i < length; ++i) {
            // i | localeSoFar    | localeElements
            // 0 | ""             | ["en", "US", "POSIX"]
            // 1 | "en_"          | ["en", "US", "POSIX"]
            // 2 | "en_US_"       | ["en", "en_US", "POSIX"]
            localeElements[i] = localeSoFar + localeElements[i];
            localeSoFar = localeElements[i] + "_";
            // i | request
            // 0 | "(locale is NULL)"
            // 1 | "(locale is NULL) or (locale=?)"
            // 2 | "(locale is NULL) or (locale=?) or (locale=?)"
            request.append(" or (locale=?)");
        }
        // At the end, localeElements = ["en", "en_US", "en_US_POSIX"]; localeSoFar = en_US_POSIX_"
        // and request = "(locale is NULL) or (locale=?) or (locale=?) or (locale=?)"
        final String[] requestArguments;
        // If length == 3, we already have all the arguments we need (common prefix is meaningless
        // inside variants
        if (mAlsoUseMoreRestrictiveLocales && length < 3) {
            request.append(" or (locale like ?)");
            // The following creates an array with one more (null) position
            final String[] localeElementsWithMoreRestrictiveLocalesIncluded = Arrays.copyOf(localeElements, length + 1);
            localeElementsWithMoreRestrictiveLocalesIncluded[length] = localeElements[length - 1] + "_%";
            requestArguments = localeElementsWithMoreRestrictiveLocalesIncluded;
        // If for example localeElements = ["en"]
        // then requestArguments = ["en", "en_%"]
        // and request = (locale is NULL) or (locale=?) or (locale like ?)
        // If localeElements = ["en", "en_US"]
        // then requestArguments = ["en", "en_US", "en_US_%"]
        } else {
            requestArguments = localeElements;
        }
        final String requestString = request.toString();
        addWordsFromProjectionLocked(PROJECTION_QUERY, requestString, requestArguments);
    }

    private void addWordsFromProjectionLocked(final String[] query, String request, final String[] requestArguments) throws IllegalArgumentException {
        Cursor cursor = null;
        try {
            cursor = mContext.getContentResolver().query(Words.CONTENT_URI, query, request, requestArguments, null);
            addWordsLocked(cursor);
        } catch (final SQLiteException e) {
            Log.e(TAG, "SQLiteException in the remote User dictionary process.", e);
        } finally {
            try {
                if (null != cursor)
                    cursor.close();
            } catch (final SQLiteException e) {
                Log.e(TAG, "SQLiteException in the remote User dictionary process.", e);
            }
        }
    }

    private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
        // The default frequency for the user dictionary is 250 for historical reasons.
        // Latin IME considers a good value for the default user dictionary frequency
        // is about 160 considering the scale we use. So we are scaling down the values.
        if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
            return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY) * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY;
        }
        return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
    }

    private void addWordsLocked(final Cursor cursor) {
        if (cursor == null)
            return;
        if (cursor.moveToFirst()) {
            final int indexWord = cursor.getColumnIndex(Words.WORD);
            final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
            while (!cursor.isAfterLast()) {
                final String word = cursor.getString(indexWord);
                final int frequency = cursor.getInt(indexFrequency);
                final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency);
                // Safeguard against adding really long words.
                if (word.length() <= MAX_WORD_LENGTH) {
                    runGCIfRequiredLocked(true);
                    addUnigramLocked(word, adjustedFrequency, false, /* isNotAWord */
                    false, /* isPossiblyOffensive */
                    BinaryDictionary.NOT_A_VALID_TIMESTAMP);
                }
                cursor.moveToNext();
            }
        }
    }
}

19 Source : RadioModel.java
with MIT License
from roadrover

/**
 * 收音机数据.
 */
public clreplaced RadioModel {

    public static clreplaced Station {

        // 名字
        public String mName;

        // 频率
        public int mFreq;

        // 频率
        public int mKind;

        // 波段,取值见{@link IVIRadio#Band}
        public int mBand;

        // 
        public int mPosition;

        public int mIsLove;

        // 
        public String mDesp;

        @Override
        public String toString() {
            return "mName = " + mName + ", mFreq = " + mFreq + ", mKind = " + mKind + ", mBand = " + mBand + ", mPosition = " + mPosition + ", mIsLove = " + mIsLove + ", mDesp = " + mDesp;
        }
    }

    /**
     * 获取收音机站台频率列表,该方法时直接获取收音机数据库的数据
     *
     * @param context
     * @return
     */
    public static List<RadioModel.Station> getStationList(Context context) {
        List<RadioModel.Station> stations = new ArrayList<>();
        if (context != null && checkValidProvider(Provider.TableColumns.CONTENT_URI, context)) {
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver().query(Provider.TableColumns.CONTENT_URI, new String[] { Provider.TableColumns.KEY_ID, Provider.TableColumns.KEY_NAME, Provider.TableColumns.KEY_FREQ, Provider.TableColumns.KEY_DESP, Provider.TableColumns.KEY_BAND, Provider.TableColumns.KEY_KIND, Provider.TableColumns.KEY_POSITION, Provider.TableColumns.KEY_ISLOVE }, null, null, null);
                if (cursor != null && cursor.moveToFirst()) {
                    do {
                        // 获取收音机站台频率数据
                        RadioModel.Station station = new RadioModel.Station();
                        station.mName = cursor.getString(cursor.getColumnIndex(Provider.TableColumns.KEY_NAME));
                        station.mFreq = cursor.getInt(cursor.getColumnIndex(Provider.TableColumns.KEY_FREQ));
                        station.mDesp = cursor.getString(cursor.getColumnIndex(Provider.TableColumns.KEY_DESP));
                        station.mBand = cursor.getInt(cursor.getColumnIndex(Provider.TableColumns.KEY_BAND));
                        station.mKind = cursor.getInt(cursor.getColumnIndex(Provider.TableColumns.KEY_KIND));
                        station.mPosition = cursor.getInt(cursor.getColumnIndex(Provider.TableColumns.KEY_POSITION));
                        station.mIsLove = cursor.getInt(cursor.getColumnIndex(Provider.TableColumns.KEY_ISLOVE));
                        stations.add(station);
                        Logcat.d("station = " + station.toString());
                    } while (cursor.moveToNext());
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                if (cursor != null) {
                    cursor.close();
                    cursor = null;
                }
            }
        }
        return stations;
    }

    public interface ModelListener {

        void onChange(List<RadioModel.Station> stations);
    }

    private static ContentObserver mContentObserver = null;

    /**
     * 监听收音站台频率的接口,语音等应用需要知道收音站台频率发生改变
     *
     * @param context
     * @param listener
     */
    public static void registerStationListener(final Context context, final ModelListener listener) {
        if (context != null && listener != null) {
            if (mContentObserver != null) {
                return;
            }
            mContentObserver = new ContentObserver(new Handler()) {

                @Override
                public void onChange(boolean selfChange) {
                    Logcat.d("selfChange:" + selfChange);
                    if (!selfChange) {
                        if (listener != null) {
                            listener.onChange(getStationList(context));
                        }
                    }
                }
            };
            context.getContentResolver().registerContentObserver(Provider.TableColumns.CONTENT_URI, false, mContentObserver);
        }
    }

    /**
     * 不再监听收音站台频率的改变消息
     *
     * @param context
     */
    public static void unregisterStationListener(Context context) {
        if (context != null && mContentObserver != null) {
            context.getContentResolver().unregisterContentObserver(mContentObserver);
            mContentObserver = null;
        }
    }

    /**
     * 检测这个contentprovider是否合法
     *
     * @param uri
     * @return 合法返回true, 否则返回false
     */
    private static boolean checkValidProvider(Uri uri, Context context) {
        if (null == context) {
            return false;
        }
        ContentProviderClient client = context.getContentResolver().acquireContentProviderClient(uri);
        if (null == client) {
            return false;
        } else {
            client.release();
            return true;
        }
    }
}

19 Source : BluetoothModel.java
with MIT License
from roadrover

/**
 * 获取蓝牙应用里面的数据.
 * 可以获取到电话本的数据,主要方式是通过aidl连接蓝牙app的数据库
 * 注:要使用该类,必须你的蓝牙app,要实现联系人数据库的ContentProvider
 */
public clreplaced BluetoothModel {

    /**
     * 联系人定义类
     */
    public static clreplaced Contact {

        // 名字
        public String mName;

        // 电话号码
        public String mPhoneNumber;

        @Override
        public String toString() {
            return "Contact{" + "mName='" + mName + '\'' + ", mPhoneNumber='" + mPhoneNumber + '\'' + '}';
        }
    }

    /**
     * 历史记录定义类
     */
    public static clreplaced CallHistory {

        // 状态
        public int mStatus = 0;

        // 名字
        public String mName = "";

        // 电话号码
        public String mPhoneNumber = "";

        // 显示时间
        public String mTime = "";

        // 排序
        public String mSort = "";

        @Override
        public String toString() {
            return "CallHistory{" + "mStatus=" + mStatus + ", mName='" + mName + '\'' + ", mPhoneNumber='" + mPhoneNumber + '\'' + ", mTime='" + mTime + '\'' + ", mSort='" + mSort + '\'' + '}';
        }
    }

    /**
     * 蓝牙电话表格
     */
    public static clreplaced BluetoothTable {

        /**
         * 联系人表格
         */
        public static final String TABLE_CONTACT = "tbl_stPhoneBook";

        /**
         * 通话记录表格
         */
        public static final String TABLE_CALL_HISTORY = "tbl_stCallHistory";
    }

    /**
     * 联系人的ContentProvider的数据接口
     */
    public static clreplaced Provider {

        public static final String AUTHORITY = "com.roadrover.bluetooth";

        public static final Uri URI = Uri.parse("content://" + AUTHORITY + "/" + BluetoothTable.TABLE_CONTACT);

        /**
         * 通话记录表
         */
        public static final Uri URI_CALL_HISTORY = Uri.parse("content://" + AUTHORITY + "/" + BluetoothTable.TABLE_CALL_HISTORY);

        private static final String KEY_STATUS = "status";

        private static final String KEY_NAME = "name";

        private static final String KEY_PHONE_NUMBER = "phoneNumber";

        private static final String KEY_TIME = "time";

        private static final String KEY_SORT = "sort";

        private static final String KEY_ADDR = "addr";
    }

    // 判断两个电话号码是否一样,只判断最后7位
    private static final int EQUALS_PHONE_NUMBER_COUNT = 7;

    /**
     * 获取蓝牙历史通话记录列表,该方法时直接获取蓝牙联系数据库的数据,不是从串口获取
     * @param context 上下文
     * @param address 蓝牙设备地址
     * @return 返回历史通话记录列表
     */
    public static List<CallHistory> getCallHistoryList(Context context, String address) {
        List<CallHistory> callHistorys = new ArrayList<>();
        if (context != null && checkValidProvider(Provider.URI_CALL_HISTORY, context)) {
            Cursor cursor = null;
            try {
                String selection = Provider.KEY_ADDR + "=?";
                String[] selectionArgs = new String[] { address };
                cursor = context.getContentResolver().query(Provider.URI_CALL_HISTORY, new String[] { Provider.KEY_STATUS, Provider.KEY_NAME, Provider.KEY_PHONE_NUMBER, Provider.KEY_TIME, Provider.KEY_SORT }, selection, selectionArgs, null);
                if (cursor != null && cursor.moveToFirst()) {
                    do {
                        // 获取蓝牙联系人数据
                        CallHistory callHistory = new CallHistory();
                        callHistory.mStatus = cursor.getInt(cursor.getColumnIndex(Provider.KEY_STATUS));
                        callHistory.mName = cursor.getString(cursor.getColumnIndex(Provider.KEY_NAME));
                        callHistory.mPhoneNumber = cursor.getString(cursor.getColumnIndex(Provider.KEY_PHONE_NUMBER));
                        callHistory.mTime = cursor.getString(cursor.getColumnIndex(Provider.KEY_TIME));
                        callHistory.mSort = cursor.getString(cursor.getColumnIndex(Provider.KEY_SORT));
                        callHistorys.add(callHistory);
                    } while (cursor.moveToNext());
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                if (cursor != null) {
                    cursor.close();
                    cursor = null;
                }
            }
        }
        return callHistorys;
    }

    /**
     * 获取蓝牙联系人列表,该方法时直接获取蓝牙联系数据库的数据,不是从串口获取
     * @param context 上下文
     * @return 返回当前联系人列表
     */
    public static List<Contact> getContactList(Context context) {
        List<Contact> contacts = new ArrayList<>();
        if (context != null && checkValidProvider(Provider.URI, context)) {
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver().query(Provider.URI, new String[] { Provider.KEY_NAME, Provider.KEY_PHONE_NUMBER }, null, null, null);
                if (cursor != null && cursor.moveToFirst()) {
                    do {
                        // 获取蓝牙联系人数据
                        Contact contact = new Contact();
                        contact.mName = cursor.getString(cursor.getColumnIndex(Provider.KEY_NAME));
                        contact.mPhoneNumber = cursor.getString(cursor.getColumnIndex(Provider.KEY_PHONE_NUMBER));
                        contacts.add(contact);
                    } while (cursor.moveToNext());
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                if (cursor != null) {
                    cursor.close();
                    cursor = null;
                }
            }
        }
        return contacts;
    }

    /**
     * 通过电话号码,获取联系人名字
     * @param phoneNumber 电话号码
     * @param contacts    联系人列表
     * @return 返回联系人名字
     */
    public static String getContactName(String phoneNumber, List<Contact> contacts) {
        if (!ListUtils.isEmpty(contacts) && !TextUtils.isEmpty(phoneNumber)) {
            for (Contact contact : contacts) {
                if (isPhoneNumberEquals(phoneNumber, contact.mPhoneNumber)) {
                    return contact.mName;
                }
            }
        }
        return "";
    }

    /**
     * 判断两个电话号码是否完全相等
     * @param src 源电话号码
     * @param dest 目标电话号码
     * @return 相等返回true,否则返回false
     */
    public static boolean isPhoneNumberEquals(String src, String dest) {
        if (src != null && dest != null) {
            String srcCompare = src.replace(" ", "");
            // 去掉空格之后再比较
            String destCompare = dest.replace(" ", "");
            if (TextUtils.equals(srcCompare, destCompare)) {
                // 完全相等
                return true;
            }
            // 有些地区会在前面+86等,所以只判断最后7位
            if (srcCompare.length() >= EQUALS_PHONE_NUMBER_COUNT && destCompare.length() >= EQUALS_PHONE_NUMBER_COUNT) {
                String lastNumberCount = destCompare.substring(destCompare.length() - EQUALS_PHONE_NUMBER_COUNT);
                if (srcCompare.endsWith(lastNumberCount)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 监听数据库的改变接口定义
     */
    public interface ModelListener {

        void onChange(List<Contact> contacts);
    }

    /**
     * 监听数据库的改变接口定义
     */
    public interface ModelCallHistoryListener {

        void onChange();
    }

    private static ContentObserver mContentObserver = null;

    private static ContentObserver mCallHistoryObserver = null;

    /**
     * 监听下载联系人的接口,语音等应用需要知道蓝牙联系人发生改变
     * @param context
     * @param listener
     */
    public static void registerContactListener(final Context context, final ModelListener listener) {
        if (context != null && listener != null) {
            if (mContentObserver != null) {
                return;
            }
            mContentObserver = new ContentObserver(new Handler()) {

                @Override
                public void onChange(boolean selfChange) {
                    Logcat.d("selfChange:" + selfChange);
                    if (!selfChange) {
                        if (listener != null) {
                            listener.onChange(getContactList(context));
                        }
                    }
                }
            };
            context.getContentResolver().registerContentObserver(Provider.URI, false, mContentObserver);
        }
    }

    /**
     * 监听通话记录数据改变
     *
     * @param context
     * @param listener
     */
    public static void registerCallHistoryListener(final Context context, final ModelCallHistoryListener listener) {
        if (context != null && listener != null) {
            if (mCallHistoryObserver != null) {
                return;
            }
            mCallHistoryObserver = new ContentObserver(new Handler()) {

                @Override
                public void onChange(boolean selfChange) {
                    Logcat.d("selfChange:" + selfChange);
                    if (!selfChange) {
                        if (listener != null) {
                            listener.onChange();
                        }
                    }
                }
            };
            context.getContentResolver().registerContentObserver(Provider.URI_CALL_HISTORY, false, mCallHistoryObserver);
        }
    }

    /**
     * 不再监听联系人的改变消息
     * @param context
     */
    public static void unregisterContactListener(Context context) {
        if (context != null && mContentObserver != null) {
            context.getContentResolver().unregisterContentObserver(mContentObserver);
            mContentObserver = null;
        }
    }

    /**
     * 不再监听通话记录的改变消息
     *
     * @param context
     */
    public static void unregisterCallHistoryListener(Context context) {
        if (context != null && mCallHistoryObserver != null) {
            context.getContentResolver().unregisterContentObserver(mCallHistoryObserver);
            mCallHistoryObserver = null;
        }
    }

    /**
     * 检测这个contentprovider是否合法
     *
     * @param uri
     * @return 合法返回true,否则返回false
     */
    private static boolean checkValidProvider(Uri uri, Context context) {
        if (null == context) {
            return false;
        }
        ContentProviderClient client = context.getContentResolver().acquireContentProviderClient(uri);
        if (null == client) {
            return false;
        } else {
            client.release();
            return true;
        }
    }
}

19 Source : UserDictionary.java
with GNU General Public License v3.0
from PhilippC

public clreplaced UserDictionary extends ExpandableDictionary {

    private static final String[] PROJECTION = { Words._ID, Words.WORD, Words.FREQUENCY };

    private static final int INDEX_WORD = 1;

    private static final int INDEX_FREQUENCY = 2;

    private ContentObserver mObserver;

    private String mLocale;

    public UserDictionary(Context context, String locale) {
        super(context, Suggest.DIC_USER);
        mLocale = locale;
        // Perform a managed query. The Activity will handle closing and requerying the cursor
        // when needed.
        ContentResolver cres = context.getContentResolver();
        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean self) {
                setRequiresReload(true);
            }
        });
        loadDictionary();
    }

    @Override
    public synchronized void close() {
        if (mObserver != null) {
            getContext().getContentResolver().unregisterContentObserver(mObserver);
            mObserver = null;
        }
        super.close();
    }

    @Override
    public void loadDictionaryAsync() {
    // Cursor cursor = getContext().getContentResolver()
    // .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)",
    // new String[] { mLocale }, null);
    // addWords(cursor);
    }

    /**
     * Adds a word to the dictionary and makes it persistent.
     * @param word the word to add. If the word is capitalized, then the dictionary will
     * recognize it as a capitalized word when searched.
     * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
     * the highest.
     * @TODO use a higher or float range for frequency
     */
    @Override
    public synchronized void addWord(String word, int frequency) {
        // Force load the dictionary here synchronously
        if (getRequiresReload())
            loadDictionaryAsync();
        // Safeguard against adding long words. Can cause stack overflow.
        if (word.length() >= getMaxWordLength())
            return;
        super.addWord(word, frequency);
        // Update the user dictionary provider
        final ContentValues values = new ContentValues(5);
        values.put(Words.WORD, word);
        values.put(Words.FREQUENCY, frequency);
        values.put(Words.LOCALE, mLocale);
        values.put(Words.APP_ID, 0);
        final ContentResolver contentResolver = getContext().getContentResolver();
        new Thread("addWord") {

            public void run() {
                contentResolver.insert(Words.CONTENT_URI, values);
            }
        }.start();
        // In case the above does a synchronous callback of the change observer
        setRequiresReload(false);
    }

    @Override
    public synchronized void getWords(final WordComposer codes, final WordCallback callback, int[] nextLettersFrequencies) {
        super.getWords(codes, callback, nextLettersFrequencies);
    }

    @Override
    public synchronized boolean isValidWord(CharSequence word) {
        return super.isValidWord(word);
    }

    private void addWords(Cursor cursor) {
        clearDictionary();
        final int maxWordLength = getMaxWordLength();
        if (cursor.moveToFirst()) {
            while (!cursor.isAfterLast()) {
                String word = cursor.getString(INDEX_WORD);
                int frequency = cursor.getInt(INDEX_FREQUENCY);
                // Safeguard against adding really long words. Stack may overflow due
                // to recursion
                if (word.length() < maxWordLength) {
                    super.addWord(word, frequency);
                }
                cursor.moveToNext();
            }
        }
        cursor.close();
    }
}

19 Source : ContactsDictionary.java
with GNU General Public License v3.0
from PhilippC

public clreplaced ContactsDictionary extends ExpandableDictionary {

    private static final String[] PROJECTION = { Contacts._ID, Contacts.DISPLAY_NAME };

    private static final String TAG = "ContactsDictionary";

    /**
     * Frequency for contacts information into the dictionary
     */
    private static final int FREQUENCY_FOR_CONTACTS = 128;

    private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;

    private static final int INDEX_NAME = 1;

    private ContentObserver mObserver;

    private long mLastLoadedContacts;

    public ContactsDictionary(Context context, int dicTypeId) {
        super(context, dicTypeId);
        // Perform a managed query. The Activity will handle closing and requerying the cursor
        // when needed.
        ContentResolver cres = context.getContentResolver();
        cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean self) {
                setRequiresReload(true);
            }
        });
        loadDictionary();
    }

    @Override
    public synchronized void close() {
        if (mObserver != null) {
            getContext().getContentResolver().unregisterContentObserver(mObserver);
            mObserver = null;
        }
        super.close();
    }

    @Override
    public void startDictionaryLoadingTaskLocked() {
        long now = SystemClock.uptimeMillis();
        if (mLastLoadedContacts == 0 || now - mLastLoadedContacts > 30 * 60 * 1000) /* 30 minutes */
        {
            super.startDictionaryLoadingTaskLocked();
        }
    }

    @Override
    public void loadDictionaryAsync() {
    /*try {
            Cursor cursor = getContext().getContentResolver()
                    .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
            if (cursor != null) {
                addWords(cursor);
            }
        } catch(IllegalStateException e) {
            Log.e(TAG, "Contacts DB is having problems");
        }
        mLastLoadedContacts = SystemClock.uptimeMillis();*/
    }

    private void addWords(Cursor cursor) {
        clearDictionary();
        final int maxWordLength = getMaxWordLength();
        try {
            if (cursor.moveToFirst()) {
                while (!cursor.isAfterLast()) {
                    String name = cursor.getString(INDEX_NAME);
                    if (name != null) {
                        int len = name.length();
                        String prevWord = null;
                        // TODO: Better tokenization for non-Latin writing systems
                        for (int i = 0; i < len; i++) {
                            if (Character.isLetter(name.charAt(i))) {
                                int j;
                                for (j = i + 1; j < len; j++) {
                                    char c = name.charAt(j);
                                    if (!(c == '-' || c == '\'' || Character.isLetter(c))) {
                                        break;
                                    }
                                }
                                String word = name.substring(i, j);
                                i = j - 1;
                                // Safeguard against adding really long words. Stack
                                // may overflow due to recursion
                                // Also don't add single letter words, possibly confuses
                                // capitalization of i.
                                final int wordLen = word.length();
                                if (wordLen < maxWordLength && wordLen > 1) {
                                    super.addWord(word, FREQUENCY_FOR_CONTACTS);
                                    if (!TextUtils.isEmpty(prevWord)) {
                                        // TODO Do not add email address
                                        // Not so critical
                                        super.setBigram(prevWord, word, FREQUENCY_FOR_CONTACTS_BIGRAM);
                                    }
                                    prevWord = word;
                                }
                            }
                        }
                    }
                    cursor.moveToNext();
                }
            }
            cursor.close();
        } catch (IllegalStateException e) {
            Log.e(TAG, "Contacts DB is having problems");
        }
    }
}

19 Source : SettingsCursor.java
with GNU General Public License v3.0
from MuntashirAkon

@Override
public void unregisterContentObserver(ContentObserver contentObserver) {
    if (cursor != null)
        cursor.unregisterContentObserver(contentObserver);
}

19 Source : ObservingLiveData.java
with GNU General Public License v3.0
from mollyim

/**
 * Implementation of {@link androidx.lifecycle.LiveData} that will handle closing the contained
 * {@link Closeable} when the value changes.
 */
public clreplaced ObservingLiveData<E extends ObservableContent> extends MutableLiveData<E> {

    private ContentObserver observer;

    @Override
    public void setValue(E value) {
        E previous = getValue();
        if (previous != null) {
            previous.unregisterContentObserver(observer);
            StreamUtil.close(previous);
        }
        value.registerContentObserver(observer);
        super.setValue(value);
    }

    public void close() {
        E value = getValue();
        if (value != null) {
            value.unregisterContentObserver(observer);
            StreamUtil.close(value);
        }
    }

    public void registerContentObserver(@NonNull ContentObserver observer) {
        this.observer = observer;
    }
}

19 Source : ObservingLiveData.java
with GNU General Public License v3.0
from mollyim

public void registerContentObserver(@NonNull ContentObserver observer) {
    this.observer = observer;
}

19 Source : MediaDatabase.java
with GNU General Public License v3.0
from mollyim

public void unsubscribeToMediaChanges(@NonNull ContentObserver observer) {
    context.getContentResolver().unregisterContentObserver(observer);
}

19 Source : MediaDatabase.java
with GNU General Public License v3.0
from mollyim

public void subscribeToMediaChanges(@NonNull ContentObserver observer) {
    registerAttachmentListeners(observer);
}

19 Source : VideoActivity.java
with Apache License 2.0
from komamj

/**
 * Created by koma on 11/28/16.
 */
public clreplaced VideoActivity extends BaseMenuActivity {

    private static final String TAG = "VideoActivity";

    private VideoContract.Presenter mPresenter;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LogUtils.i(TAG, "onCreate");
        init();
    }

    private void init() {
        VideoFragment videoFragment = (VideoFragment) getSupportFragmentManager().findFragmentById(R.id.content);
        if (videoFragment == null) {
            videoFragment = new VideoFragment();
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.content, videoFragment).commit();
        }
        mPresenter = new VideoPresenter(videoFragment, FileRepository.getInstance());
        mPresenter.subscribe();
        getContentResolver().registerContentObserver(FileCategoryUtils.getAudioUri(), true, mVideoObserver);
    }

    private final ContentObserver mVideoObserver = new ContentObserver(new Handler()) {

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            LogUtils.i(TAG, "Video uri change so refresh");
            if (mPresenter != null) {
                mPresenter.getVideoFiles();
            }
        }
    };

    @Override
    public void onStart() {
        super.onStart();
        LogUtils.i(TAG, "onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        LogUtils.i(TAG, "onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        LogUtils.i(TAG, "onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        LogUtils.i(TAG, "onStop");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtils.i(TAG, "onDestroy");
    }

    @Override
    protected int getLayoutId() {
        return R.layout.common_layout;
    }

    @Override
    protected void sortByType() {
        LogUtils.i(TAG, "sortByType");
    }

    @Override
    protected void sortByName() {
        LogUtils.i(TAG, "sortByName");
    }

    @Override
    protected void sortBySize() {
        LogUtils.i(TAG, "sortBySize");
    }

    @Override
    protected void sortByDate() {
        LogUtils.i(TAG, "sortByDate");
    }
}

19 Source : AudioActivity.java
with Apache License 2.0
from komamj

/**
 * Created by koma on 11/19/16.
 */
public clreplaced AudioActivity extends BaseMenuActivity {

    private static final String TAG = "AudioActivity";

    AudioPresenter mPresenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LogUtils.i(TAG, "onCreate");
        init();
    }

    private void init() {
        AudioFragment audioFragment = (AudioFragment) getSupportFragmentManager().findFragmentById(R.id.content);
        if (audioFragment == null) {
            audioFragment = new AudioFragment();
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.content, audioFragment).commit();
        }
        mPresenter = new AudioPresenter(audioFragment, FileRepository.getInstance());
        getContentResolver().registerContentObserver(FileCategoryUtils.getAudioUri(), true, mAudioObserver);
    }

    private final ContentObserver mAudioObserver = new ContentObserver(new Handler()) {

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            LogUtils.i(TAG, "Audio uri change so refresh");
            if (mPresenter != null) {
                mPresenter.getAudioFiles();
            }
        }
    };

    @Override
    public void onStart() {
        super.onStart();
        LogUtils.i(TAG, "onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        LogUtils.i(TAG, "onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        LogUtils.i(TAG, "onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        LogUtils.i(TAG, "onStop");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtils.i(TAG, "onDestroy");
        if (mAudioObserver != null) {
            getContentResolver().unregisterContentObserver(mAudioObserver);
        }
    }

    @Override
    protected int getLayoutId() {
        return R.layout.common_layout;
    }

    @Override
    protected void sortByType() {
    }

    @Override
    protected void sortByName() {
    }

    @Override
    protected void sortBySize() {
    }

    @Override
    protected void sortByDate() {
    }
}

19 Source : SettingsFragment.java
with Apache License 2.0
from KeikaiLauncher

public clreplaced SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {

    /**
     * This field generates a ContentObserver to enable or disable the orientation locked setting depending if
     * rotation is locked or unlocked.
     */
    private final ContentObserver mAccSettingObserver = new ContentObserver(new Handler()) {

        @Override
        public void onChange(boolean selfChange) {
            final Preference orientationPreference = findPreference(R.string.pref_key_allow_rotation);
            orientationPreference.setEnabled(isOrientationLocked());
            super.onChange(selfChange);
        }
    };

    /**
     * This method returns whether the system orientation is locked.
     *
     * @return True if orientation is locked, false otherwise.
     */
    private boolean isOrientationLocked() {
        return Settings.System.getInt(getPreferenceScreen().getContext().getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 1;
    }

    private Preference findPreference(@StringRes final int prefKey) {
        return findPreference(getString(prefKey));
    }

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            findPreference(R.string.pref_key_notification_priority).setEnabled(false);
        }
        setUsageStatisticsStatus();
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onPause() {
        final PreferenceScreen prefs = getPreferenceScreen();
        prefs.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
        prefs.getContext().getContentResolver().unregisterContentObserver(mAccSettingObserver);
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        final Preference orientationPreference = findPreference(R.string.pref_key_allow_rotation);
        final Context context = orientationPreference.getContext();
        final Uri accUri = Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION);
        context.getContentResolver().registerContentObserver(accUri, false, mAccSettingObserver);
        orientationPreference.setEnabled(isOrientationLocked());
        orientationPreference.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
        final Context context = getPreferenceScreen().getContext();
        // Fragments suck.
        if (context != null) {
            final SharedLauncherPrefs prefs = new SharedLauncherPrefs(context);
            if (key.equals(getString(R.string.pref_key_notification)) || key.equals(getString(R.string.pref_key_notification_priority))) {
                ShortcutNotificationManager.cancelNotification(context);
                if (prefs.isNotificationEnabled()) {
                    ShortcutNotificationManager.showNotification(context);
                }
            }
        }
    }

    /**
     * This method sets the usage statistics preference status by checking the availability of the
     * UsageStats subsystem.
     */
    private void setUsageStatisticsStatus() {
        final Preference pref = findPreference(R.string.pref_key_modify_usage_statistics);
        final PackageManager pm = pref.getContext().getPackageManager();
        pref.setEnabled(pref.getIntent().resolveActivity(pm) != null);
    }
}

19 Source : UserBinaryDictionary.java
with GNU General Public License v3.0
from dslul

/**
 * An expandable dictionary that stores the words in the user dictionary provider into a binary
 * dictionary file to use it from native code.
 */
public clreplaced UserBinaryDictionary extends ExpandableBinaryDictionary {

    private static final String TAG = ExpandableBinaryDictionary.clreplaced.getSimpleName();

    // The user dictionary provider uses an empty string to mean "all languages".
    private static final String USER_DICTIONARY_ALL_LANGUAGES = "";

    private static final int HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY = 250;

    private static final int LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY = 160;

    // Shortcut frequency is 0~15, with 15 = whitelist. We don't want user dictionary entries
    // to auto-correct, so we set this to the highest frequency that won't, i.e. 14.
    private static final int USER_DICT_SHORTCUT_FREQUENCY = 14;

    private static final String[] PROJECTION_QUERY_WITH_SHORTCUT = new String[] { Words.WORD, Words.SHORTCUT, Words.FREQUENCY };

    private static final String[] PROJECTION_QUERY_WITHOUT_SHORTCUT = new String[] { Words.WORD, Words.FREQUENCY };

    private static final String NAME = "userunigram";

    private ContentObserver mObserver;

    final private String mLocaleString;

    final private boolean mAlsoUseMoreRestrictiveLocales;

    protected UserBinaryDictionary(final Context context, final Locale locale, final boolean alsoUseMoreRestrictiveLocales, final File dictFile, final String name) {
        super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_USER, dictFile);
        // Catch the error earlier
        if (null == locale)
            throw new NullPointerException();
        final String localeStr = locale.toString();
        if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
            // If we don't have a locale, insert into the "all locales" user dictionary.
            mLocaleString = USER_DICTIONARY_ALL_LANGUAGES;
        } else {
            mLocaleString = localeStr;
        }
        mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
        ContentResolver cres = context.getContentResolver();
        mObserver = new ContentObserver(null) {

            @Override
            public void onChange(final boolean self) {
                // This hook is deprecated as of API level 16 (Build.VERSION_CODES.JELLY_BEAN),
                // but should still be supported for cases where the IME is running on an older
                // version of the platform.
                onChange(self, null);
            }

            // The following hook is only available as of API level 16
            // (Build.VERSION_CODES.JELLY_BEAN), and as such it will only work on JellyBean+
            // devices. On older versions of the platform, the hook above will be called instead.
            @Override
            public void onChange(final boolean self, final Uri uri) {
                setNeedsToRecreate();
            }
        };
        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
        reloadDictionaryIfRequired();
    }

    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
    @ExternallyReferenced
    public static UserBinaryDictionary getDictionary(final Context context, final Locale locale, final File dictFile, final String dictNamePrefix, @Nullable final String account) {
        return new UserBinaryDictionary(context, locale, false, /* alsoUseMoreRestrictiveLocales */
        dictFile, dictNamePrefix + NAME);
    }

    @Override
    public synchronized void close() {
        if (mObserver != null) {
            mContext.getContentResolver().unregisterContentObserver(mObserver);
            mObserver = null;
        }
        super.close();
    }

    @Override
    public void loadInitialContentsLocked() {
        // Split the locale. For example "en" => ["en"], "de_DE" => ["de", "DE"],
        // "en_US_foo_bar_qux" => ["en", "US", "foo_bar_qux"] because of the limit of 3.
        // This is correct for locale processing.
        // For this example, we'll look at the "en_US_POSIX" case.
        final String[] localeElements = TextUtils.isEmpty(mLocaleString) ? new String[] {} : mLocaleString.split("_", 3);
        final int length = localeElements.length;
        final StringBuilder request = new StringBuilder("(locale is NULL)");
        String localeSoFar = "";
        // At start, localeElements = ["en", "US", "POSIX"] ; localeSoFar = "" ;
        // and request = "(locale is NULL)"
        for (int i = 0; i < length; ++i) {
            // i | localeSoFar    | localeElements
            // 0 | ""             | ["en", "US", "POSIX"]
            // 1 | "en_"          | ["en", "US", "POSIX"]
            // 2 | "en_US_"       | ["en", "en_US", "POSIX"]
            localeElements[i] = localeSoFar + localeElements[i];
            localeSoFar = localeElements[i] + "_";
            // i | request
            // 0 | "(locale is NULL)"
            // 1 | "(locale is NULL) or (locale=?)"
            // 2 | "(locale is NULL) or (locale=?) or (locale=?)"
            request.append(" or (locale=?)");
        }
        // At the end, localeElements = ["en", "en_US", "en_US_POSIX"]; localeSoFar = en_US_POSIX_"
        // and request = "(locale is NULL) or (locale=?) or (locale=?) or (locale=?)"
        final String[] requestArguments;
        // If length == 3, we already have all the arguments we need (common prefix is meaningless
        // inside variants
        if (mAlsoUseMoreRestrictiveLocales && length < 3) {
            request.append(" or (locale like ?)");
            // The following creates an array with one more (null) position
            final String[] localeElementsWithMoreRestrictiveLocalesIncluded = Arrays.copyOf(localeElements, length + 1);
            localeElementsWithMoreRestrictiveLocalesIncluded[length] = localeElements[length - 1] + "_%";
            requestArguments = localeElementsWithMoreRestrictiveLocalesIncluded;
        // If for example localeElements = ["en"]
        // then requestArguments = ["en", "en_%"]
        // and request = (locale is NULL) or (locale=?) or (locale like ?)
        // If localeElements = ["en", "en_US"]
        // then requestArguments = ["en", "en_US", "en_US_%"]
        } else {
            requestArguments = localeElements;
        }
        final String requestString = request.toString();
        try {
            addWordsFromProjectionLocked(PROJECTION_QUERY_WITH_SHORTCUT, requestString, requestArguments);
        } catch (IllegalArgumentException e) {
            // This may happen on some non-compliant devices where the declared API is JB+ but
            // the SHORTCUT column is not present for some reason.
            addWordsFromProjectionLocked(PROJECTION_QUERY_WITHOUT_SHORTCUT, requestString, requestArguments);
        }
    }

    private void addWordsFromProjectionLocked(final String[] query, String request, final String[] requestArguments) throws IllegalArgumentException {
        Cursor cursor = null;
        try {
            cursor = mContext.getContentResolver().query(Words.CONTENT_URI, query, request, requestArguments, null);
            addWordsLocked(cursor);
        } catch (final SQLiteException e) {
            Log.e(TAG, "SQLiteException in the remote User dictionary process.", e);
        } finally {
            try {
                if (null != cursor)
                    cursor.close();
            } catch (final SQLiteException e) {
                Log.e(TAG, "SQLiteException in the remote User dictionary process.", e);
            }
        }
    }

    private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
        // The default frequency for the user dictionary is 250 for historical reasons.
        // Latin IME considers a good value for the default user dictionary frequency
        // is about 160 considering the scale we use. So we are scaling down the values.
        if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
            return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY) * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY;
        }
        return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
    }

    private void addWordsLocked(final Cursor cursor) {
        final boolean hreplacedhortcutColumn = true;
        if (cursor == null)
            return;
        if (cursor.moveToFirst()) {
            final int indexWord = cursor.getColumnIndex(Words.WORD);
            final int indexShortcut = hreplacedhortcutColumn ? cursor.getColumnIndex(Words.SHORTCUT) : 0;
            final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
            while (!cursor.isAfterLast()) {
                final String word = cursor.getString(indexWord);
                final String shortcut = hreplacedhortcutColumn ? cursor.getString(indexShortcut) : null;
                final int frequency = cursor.getInt(indexFrequency);
                final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency);
                // Safeguard against adding really long words.
                if (word.length() <= MAX_WORD_LENGTH) {
                    runGCIfRequiredLocked(true);
                    addUnigramLocked(word, adjustedFrequency, null, /* shortcutTarget */
                    0, /* shortcutFreq */
                    false, /* isNotAWord */
                    false, /* isPossiblyOffensive */
                    BinaryDictionary.NOT_A_VALID_TIMESTAMP);
                    if (null != shortcut && shortcut.length() <= MAX_WORD_LENGTH) {
                        runGCIfRequiredLocked(true);
                        addUnigramLocked(shortcut, adjustedFrequency, word, USER_DICT_SHORTCUT_FREQUENCY, true, /* isNotAWord */
                        false, /* isPossiblyOffensive */
                        BinaryDictionary.NOT_A_VALID_TIMESTAMP);
                    }
                }
                cursor.moveToNext();
            }
        }
    }
}

18 Source : PhotoSetLoader.java
with Apache License 2.0
from yuchuangu85

public clreplaced PhotoSetLoader extends CursorLoader implements LoaderCompatShim<Cursor> {

    public static final String SUPPORTED_OPERATIONS = "supported_operations";

    private static final Uri CONTENT_URI = Files.getContentUri("external");

    public static final String[] PROJECTION = new String[] { FileColumns._ID, FileColumns.DATA, FileColumns.WIDTH, FileColumns.HEIGHT, FileColumns.DATE_ADDED, FileColumns.MEDIA_TYPE, SUPPORTED_OPERATIONS };

    private static final String SORT_ORDER = FileColumns.DATE_ADDED + " DESC";

    private static final String SELECTION = FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_IMAGE + " OR " + FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_VIDEO;

    public static final int INDEX_ID = 0;

    public static final int INDEX_DATA = 1;

    public static final int INDEX_WIDTH = 2;

    public static final int INDEX_HEIGHT = 3;

    public static final int INDEX_DATE_ADDED = 4;

    public static final int INDEX_MEDIA_TYPE = 5;

    public static final int INDEX_SUPPORTED_OPERATIONS = 6;

    private static final Uri GLOBAL_CONTENT_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/external/");

    private final ContentObserver mGlobalObserver = new ForceLoadContentObserver();

    public PhotoSetLoader(Context context) {
        super(context, CONTENT_URI, PROJECTION, SELECTION, null, SORT_ORDER);
    }

    @Override
    protected void onStartLoading() {
        super.onStartLoading();
        getContext().getContentResolver().registerContentObserver(GLOBAL_CONTENT_URI, true, mGlobalObserver);
    }

    @Override
    protected void onReset() {
        super.onReset();
        getContext().getContentResolver().unregisterContentObserver(mGlobalObserver);
    }

    @Override
    public Drawable drawableForItem(Cursor item, Drawable recycle) {
        DataUriThumbnailDrawable drawable = null;
        if (recycle == null || !(recycle instanceof DataUriThumbnailDrawable)) {
            drawable = new DataUriThumbnailDrawable();
        } else {
            drawable = (DataUriThumbnailDrawable) recycle;
        }
        drawable.setImage(item.getString(INDEX_DATA), item.getInt(INDEX_WIDTH), item.getInt(INDEX_HEIGHT));
        return drawable;
    }

    @Override
    public Uri uriForItem(Cursor item) {
        return null;
    }

    @Override
    public ArrayList<Uri> urisForSubItems(Cursor item) {
        return null;
    }

    @Override
    public void deleteItemWithPath(Object path) {
    }

    @Override
    public Object getPathForItem(Cursor item) {
        return null;
    }
}

18 Source : FavLoader.java
with GNU General Public License v3.0
from treasure-lau

public clreplaced FavLoader extends AsyncTaskLoader<Cursor> {

    private Cursor currentResult;

    public FavLoader(Context context) {
        super(context);
    }

    private ContentObserver loaderObserver = new ForceLoadContentObserver();

    @Override
    public Cursor loadInBackground() {
        // First of all, get all active accounts
        ArrayList<SipProfile> accounts = SipProfile.getAllProfiles(getContext(), true, new String[] { SipProfile.FIELD_ID, SipProfile.FIELD_ACC_ID, SipProfile.FIELD_ACTIVE, SipProfile.FIELD_DISPLAY_NAME, SipProfile.FIELD_WIZARD, SipProfile.FIELD_PRIORITY, SipProfile.FIELD_ANDROID_GROUP, SipProfile.FIELD_PUBLISH_ENABLED, SipProfile.FIELD_REG_URI, SipProfile.FIELD_PROXY });
        Cursor[] cursorsToMerge = new Cursor[2 * accounts.size()];
        int i = 0;
        for (SipProfile acc : accounts) {
            cursorsToMerge[i++] = createHeaderCursorFor(acc);
            cursorsToMerge[i++] = createContentCursorFor(acc);
        }
        getContext().getContentResolver().registerContentObserver(SipProfile.ACCOUNT_STATUS_URI, true, loaderObserver);
        if (cursorsToMerge.length > 0) {
            MergeCursor mg = new MergeCursor(cursorsToMerge);
            mg.registerContentObserver(loaderObserver);
            return mg;
        } else {
            return null;
        }
    }

    /**
     * Called when there is new data to deliver to the client. The super clreplaced
     * will take care of delivering it; the implementation here just adds a
     * little more logic.
     */
    @Override
    public void deliverResult(Cursor c) {
        if (isReset()) {
            // An async query came in while the loader is stopped. We
            // don't need the result.
            if (currentResult != null) {
                onReleaseResources(currentResult);
            }
        }
        currentResult = c;
        if (isStarted()) {
            // If the Loader is currently started, we can immediately
            // deliver its results.
            super.deliverResult(c);
        }
    }

    /**
     * Handles a request to start the Loader.
     */
    @Override
    protected void onStartLoading() {
        if (currentResult != null && !takeContentChanged()) {
            // If we currently have a result available, deliver it
            // immediately.
            deliverResult(currentResult);
        } else {
            forceLoad();
        }
    }

    /**
     * Handles a request to stop the Loader.
     */
    @Override
    protected void onStopLoading() {
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    /**
     * Handles a request to cancel a load.
     */
    @Override
    public void onCanceled(Cursor c) {
        super.onCanceled(c);
        // At this point we can release the resources replacedociated with 'apps'
        // if needed.
        onReleaseResources(c);
    }

    /**
     * Handles a request to completely reset the Loader.
     */
    @Override
    protected void onReset() {
        super.onReset();
        // Ensure the loader is stopped
        onStopLoading();
        // At this point we can release the resources replacedociated with 'apps'
        // if needed.
        if (currentResult != null) {
            onReleaseResources(currentResult);
            currentResult = null;
        }
    }

    /**
     * Helper function to take care of releasing resources replacedociated with an
     * actively loaded data set.
     */
    protected void onReleaseResources(Cursor c) {
        if (c != null) {
            c.unregisterContentObserver(loaderObserver);
            c.close();
        }
        getContext().getContentResolver().unregisterContentObserver(loaderObserver);
    }

    /**
     * Creates a cursor that contains a single row and maps the section to the
     * given value.
     */
    private Cursor createHeaderCursorFor(SipProfile account) {
        MatrixCursor matrixCursor = new MatrixCursor(new String[] { BaseColumns._ID, ContactsWrapper.FIELD_TYPE, SipProfile.FIELD_DISPLAY_NAME, SipProfile.FIELD_WIZARD, SipProfile.FIELD_ANDROID_GROUP, SipProfile.FIELD_PUBLISH_ENABLED, SipProfile.FIELD_REG_URI, SipProfile.FIELD_PROXY, SipProfile.FIELD_ACC_ID });
        String proxies = "";
        if (account.proxies != null) {
            proxies = TextUtils.join(SipProfile.PROXIES_SEPARATOR, account.proxies);
        }
        matrixCursor.addRow(new Object[] { account.id, ContactsWrapper.TYPE_GROUP, account.display_name, account.wizard, account.android_group, account.publish_enabled, account.reg_uri, proxies, account.acc_id });
        return matrixCursor;
    }

    /**
     * Creates a cursor that contains contacts group corresponding to an sip
     * account.
     */
    private Cursor createContentCursorFor(SipProfile account) {
        Cursor c = null;
        if (!TextUtils.isEmpty(account.android_group)) {
            c = ContactsWrapper.getInstance().getContactsByGroup(getContext(), account.android_group);
        }
        if (c != null) {
            return c;
        }
        MatrixCursor mc = new MatrixCursor(new String[] { BaseColumns._ID, ContactsWrapper.FIELD_TYPE });
        mc.addRow(new Object[] { account.id, ContactsWrapper.TYPE_CONFIGURE });
        return mc;
    }
}

18 Source : AccountsLoader.java
with GNU General Public License v3.0
from treasure-lau

public clreplaced AccountsLoader extends AsyncTaskLoader<Cursor> {

    public static final String FIELD_FORCE_CALL = "force_call";

    public static final String FIELD_NBR_TO_CALL = "nbr_to_call";

    public static final String FIELD_STATUS_OUTGOING = "status_for_outgoing";

    public static final String FIELD_STATUS_COLOR = "status_color";

    private static final String THIS_FILE = "OutgoingAccountsLoader";

    private Cursor currentResult;

    private final String numberToCall;

    private final boolean ignoreRewritting;

    private final boolean loadStatus;

    private final boolean onlyActive;

    private final boolean loadCallHandlerPlugins;

    /**
     * Constructor for loader for outgoing call context. <br/>
     * This one will care of rewriting number and keep track of accounts status.
     * @param context Your app context
     * @param number Phone number for outgoing call
     * @param ignoreRewrittingRules Should we ignore rewriting rules.
     */
    public AccountsLoader(Context context, String number, boolean ignoreRewrittingRules) {
        super(context);
        numberToCall = number;
        ignoreRewritting = ignoreRewrittingRules;
        loadStatus = true;
        onlyActive = true;
        loadCallHandlerPlugins = true;
        initHandlers();
    }

    public AccountsLoader(Context context, boolean onlyActiveAccounts, boolean withCallHandlerPlugins) {
        super(context);
        numberToCall = "";
        ignoreRewritting = true;
        loadStatus = false;
        onlyActive = onlyActiveAccounts;
        loadCallHandlerPlugins = withCallHandlerPlugins;
        initHandlers();
    }

    private void initHandlers() {
        CallHandlerPlugin.initHandler();
        loaderObserver = new ForceLoadContentObserver();
    }

    private ContentObserver loaderObserver;

    private ArrayList<FilteredProfile> finalAccounts;

    @Override
    public Cursor loadInBackground() {
        // First register for status updates
        if (loadStatus) {
            getContext().getContentResolver().registerContentObserver(SipProfile.ACCOUNT_STATUS_URI, true, loaderObserver);
        }
        ArrayList<FilteredProfile> prefinalAccounts = new ArrayList<FilteredProfile>();
        // Get all sip profiles
        ArrayList<SipProfile> accounts;
        PreferencesProviderWrapper prefsWrapper = new PreferencesProviderWrapper(getContext());
        if (onlyActive && !prefsWrapper.isValidConnectionForOutgoing()) {
            accounts = new ArrayList<SipProfile>();
        } else {
            accounts = SipProfile.getAllProfiles(getContext(), onlyActive, new String[] { SipProfile.FIELD_ID, SipProfile.FIELD_ACC_ID, SipProfile.FIELD_ACTIVE, SipProfile.FIELD_DISPLAY_NAME, SipProfile.FIELD_WIZARD });
        }
        // And all external call handlers
        Map<String, String> externalHandlers;
        if (loadCallHandlerPlugins) {
            externalHandlers = CallHandlerPlugin.getAvailableCallHandlers(getContext());
        } else {
            externalHandlers = new HashMap<String, String>();
        }
        if (TextUtils.isEmpty(numberToCall)) {
            // In case of empty number to call, just add everything without any other question
            for (SipProfile acc : accounts) {
                prefinalAccounts.add(new FilteredProfile(acc, false));
            }
            for (Entry<String, String> extEnt : externalHandlers.entrySet()) {
                prefinalAccounts.add(new FilteredProfile(extEnt.getKey(), false));
            }
        } else {
            // If there is a number to call, add only those callable, and flag must call entries
            // Note that we keep processing all call handlers voluntarily cause we may encounter a sip account that doesn't register
            // But is in force call mode
            for (SipProfile acc : accounts) {
                if (Filter.isCallableNumber(getContext(), acc.id, numberToCall)) {
                    boolean forceCall = Filter.isMustCallNumber(getContext(), acc.id, numberToCall);
                    prefinalAccounts.add(new FilteredProfile(acc, forceCall));
                }
            }
            for (Entry<String, String> extEnt : externalHandlers.entrySet()) {
                long accId = CallHandlerPlugin.getAccountIdForCallHandler(getContext(), extEnt.getKey());
                if (Filter.isCallableNumber(getContext(), accId, numberToCall)) {
                    boolean forceCall = Filter.isMustCallNumber(getContext(), accId, numberToCall);
                    prefinalAccounts.add(new FilteredProfile(extEnt.getKey(), forceCall));
                    if (forceCall) {
                        break;
                    }
                }
            }
        }
        // Build final cursor based on final filtered accounts
        Cursor[] cursorsToMerge = new Cursor[prefinalAccounts.size()];
        int i = 0;
        for (FilteredProfile acc : prefinalAccounts) {
            cursorsToMerge[i++] = createCursorForAccount(acc);
        }
        if (cursorsToMerge.length > 0) {
            MergeCursor mg = new MergeCursor(cursorsToMerge);
            mg.registerContentObserver(loaderObserver);
            finalAccounts = prefinalAccounts;
            return mg;
        } else {
            finalAccounts = prefinalAccounts;
            return null;
        }
    }

    /**
     * Clreplaced to hold information about a possible call handler entry.
     * This could be either a sip profile or a call handler plugin
     */
    private clreplaced FilteredProfile {

        /**
         * Sip profile constructor.
         * To use when input is a sip profile
         * @param acc The corresponding sip profile
         * @param forceCall The force call flag in current context.
         */
        public FilteredProfile(SipProfile acc, boolean forceCall) {
            account = acc;
            isForceCall = forceCall;
            AccountStatusDisplay displayState = AccountListUtils.getAccountDisplay(getContext(), acc.id);
            statusColor = displayState.statusColor;
            statusForOutgoing = displayState.availableForCalls;
            callHandlerPlugin = null;
        }

        /**
         * Call handler plugin constructor.
         * To use when input is a call handler plugin.
         * @param componentName The component name of the plugin
         * @param forceCall The force call flag in current context.
         */
        public FilteredProfile(String componentName, boolean forceCall) {
            account = new SipProfile();
            long accId = CallHandlerPlugin.getAccountIdForCallHandler(getContext(), componentName);
            account.id = accId;
            account.wizard = "EXPERT";
            CallHandlerPlugin ch = new CallHandlerPlugin(getContext());
            final Semapreplaced semapreplaced = new Semapreplaced(0);
            String toCall = numberToCall;
            if (!ignoreRewritting) {
                toCall = Filter.rewritePhoneNumber(getContext(), accId, numberToCall);
            }
            ch.loadFrom(accId, toCall, new OnLoadListener() {

                @Override
                public void onLoad(CallHandlerPlugin ch) {
                    Log.d(THIS_FILE, "Callhandler loaded");
                    semapreplaced.release();
                }
            });
            boolean succeedInLoading = false;
            try {
                succeedInLoading = semapreplaced.tryAcquire(3L, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                Log.e(THIS_FILE, "Not possible to bind callhandler plugin");
            }
            if (!succeedInLoading) {
                Log.e(THIS_FILE, "Unreachable callhandler plugin " + componentName);
            }
            account.display_name = ch.getLabel();
            account.icon = ch.getIcon();
            isForceCall = forceCall;
            statusColor = getContext().getResources().getColor(android.R.color.white);
            statusForOutgoing = true;
            callHandlerPlugin = ch;
        }

        final SipProfile account;

        final boolean isForceCall;

        final private boolean statusForOutgoing;

        final private int statusColor;

        final CallHandlerPlugin callHandlerPlugin;

        /**
         * Rewrite a number for this calling entry
         * @param number The number to rewrite
         * @return Rewritten number.
         */
        public String rewriteNumber(String number) {
            if (ignoreRewritting) {
                return number;
            } else {
                return Filter.rewritePhoneNumber(getContext(), account.id, number);
            }
        }

        /**
         * Is the account available for outgoing calls
         * @return True if a call can be made using this calling entry
         */
        public boolean getStatusForOutgoing() {
            return statusForOutgoing;
        }

        /**
         * The color representing the calling entry status. green for registered
         * sip accounts, red for invalid sip accounts, orange for sip accounts
         * with ongoing registration, white for call handler plugins
         *
         * @return the color for this entry status.
         */
        public int getStatusColor() {
            return statusColor;
        }

        /**
         * Get the eventual replacedociated call handler plugin object.
         *
         * @return The call handler plugin object if any replacedociated to this
         *         calling entry. Null if representing a sip account.
         */
        public CallHandlerPlugin getCallHandlerPlugin() {
            return callHandlerPlugin;
        }
    }

    /**
     * Called when there is new data to deliver to the client. The super clreplaced
     * will take care of delivering it; the implementation here just adds a
     * little more logic.
     */
    @Override
    public void deliverResult(Cursor c) {
        if (isReset()) {
            // An async query came in while the loader is stopped. We
            // don't need the result.
            if (currentResult != null) {
                onReleaseResources(currentResult);
            }
        }
        currentResult = c;
        if (isStarted()) {
            // If the Loader is currently started, we can immediately
            // deliver its results.
            super.deliverResult(c);
        }
    }

    /**
     * Handles a request to start the Loader.
     */
    @Override
    protected void onStartLoading() {
        if (currentResult != null && !takeContentChanged()) {
            // If we currently have a result available, deliver it
            // immediately.
            deliverResult(currentResult);
        } else {
            forceLoad();
        }
    }

    /**
     * Handles a request to stop the Loader.
     */
    @Override
    protected void onStopLoading() {
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    /**
     * Handles a request to cancel a load.
     */
    @Override
    public void onCanceled(Cursor c) {
        super.onCanceled(c);
        // At this point we can release the resources replacedociated with 'apps'
        // if needed.
        onReleaseResources(c);
    }

    /**
     * Handles a request to completely reset the Loader.
     */
    @Override
    protected void onReset() {
        super.onReset();
        // Ensure the loader is stopped
        onStopLoading();
        // At this point we can release the resources replacedociated with 'apps'
        // if needed.
        if (currentResult != null) {
            onReleaseResources(currentResult);
            currentResult = null;
        }
    }

    /**
     * Helper function to take care of releasing resources replacedociated with an
     * actively loaded data set.
     */
    protected void onReleaseResources(Cursor c) {
        if (c != null) {
            c.unregisterContentObserver(loaderObserver);
            c.close();
        }
        if (loadStatus) {
            getContext().getContentResolver().unregisterContentObserver(loaderObserver);
        }
    }

    private static String[] COLUMN_HEADERS = new String[] { BaseColumns._ID, SipProfile.FIELD_ID, SipProfile.FIELD_DISPLAY_NAME, SipProfile.FIELD_WIZARD, FIELD_FORCE_CALL, FIELD_NBR_TO_CALL, FIELD_STATUS_OUTGOING, FIELD_STATUS_COLOR };

    /**
     * Creates a cursor that contains a single row and maps the section to the
     * given value.
     */
    private Cursor createCursorForAccount(FilteredProfile fa) {
        MatrixCursor matrixCursor = new MatrixCursor(COLUMN_HEADERS);
        matrixCursor.addRow(new Object[] { fa.account.id, fa.account.id, fa.account.display_name, fa.account.wizard, fa.isForceCall ? 1 : 0, fa.rewriteNumber(numberToCall), fa.getStatusForOutgoing() ? 1 : 0, fa.getStatusColor() });
        return matrixCursor;
    }

    /**
     * Get the cached call handler plugin loaded for a given position
     * @param position The position to search at
     * @return The call handler plugin if any for this position
     */
    public CallHandlerPlugin getCallHandlerWithAccountId(long accId) {
        for (FilteredProfile filteredAcc : finalAccounts) {
            if (filteredAcc.account.id == accId)
                return filteredAcc.getCallHandlerPlugin();
        }
        return null;
    }
}

18 Source : AndroidWordLevelSpellCheckerSession.java
with Apache License 2.0
from sergchil

public abstract clreplaced AndroidWordLevelSpellCheckerSession extends Session {

    private static final String TAG = AndroidWordLevelSpellCheckerSession.clreplaced.getSimpleName();

    public final static String[] EMPTY_STRING_ARRAY = new String[0];

    // Immutable, but not available in the constructor.
    private Locale mLocale;

    // Cache this for performance
    // One of SCRIPT_LATIN or SCRIPT_CYRILLIC for now.
    private int mScript;

    private final AndroidSpellCheckerService mService;

    protected final SuggestionsCache mSuggestionsCache = new SuggestionsCache();

    private final ContentObserver mObserver;

    private static final String quotesRegexp = "(\\u0022|\\u0027|\\u0060|\\u00B4|\\u2018|\\u2018|\\u201C|\\u201D)";

    private static final clreplaced SuggestionsParams {

        public final String[] mSuggestions;

        public final int mFlags;

        public SuggestionsParams(String[] suggestions, int flags) {
            mSuggestions = suggestions;
            mFlags = flags;
        }
    }

    protected static final clreplaced SuggestionsCache {

        private static final int MAX_CACHE_SIZE = 50;

        private final LruCache<String, SuggestionsParams> mUnigramSuggestionsInfoCache = new LruCache<>(MAX_CACHE_SIZE);

        private static String generateKey(final String query) {
            return query + "";
        }

        public SuggestionsParams getSuggestionsFromCache(final String query) {
            return mUnigramSuggestionsInfoCache.get(query);
        }

        public void putSuggestionsToCache(final String query, final String[] suggestions, final int flags) {
            if (suggestions == null || TextUtils.isEmpty(query)) {
                return;
            }
            mUnigramSuggestionsInfoCache.put(generateKey(query), new SuggestionsParams(suggestions, flags));
        }

        public void clearCache() {
            mUnigramSuggestionsInfoCache.evictAll();
        }
    }

    AndroidWordLevelSpellCheckerSession(final AndroidSpellCheckerService service) {
        mService = service;
        final ContentResolver cres = service.getContentResolver();
        mObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean self) {
                mSuggestionsCache.clearCache();
            }
        };
        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
    }

    @Override
    public void onCreate() {
        final String localeString = getLocale();
        mLocale = (null == localeString) ? null : LocaleUtils.constructLocaleFromString(localeString);
        mScript = ScriptUtils.getScriptFromSpellCheckerLocale(mLocale);
    }

    @Override
    public void onClose() {
        final ContentResolver cres = mService.getContentResolver();
        cres.unregisterContentObserver(mObserver);
    }

    private static final int CHECKABILITY_CHECKABLE = 0;

    private static final int CHECKABILITY_TOO_MANY_NON_LETTERS = 1;

    private static final int CHECKABILITY_CONTAINS_PERIOD = 2;

    private static final int CHECKABILITY_EMAIL_OR_URL = 3;

    private static final int CHECKABILITY_FIRST_LETTER_UNCHECKABLE = 4;

    private static final int CHECKABILITY_TOO_SHORT = 5;

    /**
     * Finds out whether a particular string should be filtered out of spell checking.
     *
     * This will loosely match URLs, numbers, symbols. To avoid always underlining words that
     * we know we will never recognize, this accepts a script identifier that should be one
     * of the SCRIPT_* constants defined above, to rule out quickly characters from very
     * different languages.
     *
     * @param text the string to evaluate.
     * @param script the identifier for the script this spell checker recognizes
     * @return one of the FILTER_OUT_* constants above.
     */
    private static int getCheckabilityInScript(final String text, final int script) {
        if (TextUtils.isEmpty(text) || text.length() <= 1)
            return CHECKABILITY_TOO_SHORT;
        // TODO: check if an equivalent processing can't be done more quickly with a
        // compiled regexp.
        // Filter by first letter
        final int firstCodePoint = text.codePointAt(0);
        // Filter out words that don't start with a letter or an apostrophe
        if (!ScriptUtils.isLetterPartOfScript(firstCodePoint, script) && '\'' != firstCodePoint)
            return CHECKABILITY_FIRST_LETTER_UNCHECKABLE;
        // Filter contents
        final int length = text.length();
        int letterCount = 0;
        for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
            final int codePoint = text.codePointAt(i);
            // Any word containing a COMMERCIAL_AT is probably an e-mail address
            // Any word containing a SLASH is probably either an ad-hoc combination of two
            // words or a URI - in either case we don't want to spell check that
            if (Constants.CODE_COMMERCIAL_AT == codePoint || Constants.CODE_SLASH == codePoint) {
                return CHECKABILITY_EMAIL_OR_URL;
            }
            // If the string contains a period, native returns strange suggestions (it seems
            // to return suggestions for everything up to the period only and to ignore the
            // rest), so we suppress lookup if there is a period.
            // TODO: investigate why native returns these suggestions and remove this code.
            if (Constants.CODE_PERIOD == codePoint) {
                return CHECKABILITY_CONTAINS_PERIOD;
            }
            if (ScriptUtils.isLetterPartOfScript(codePoint, script))
                ++letterCount;
        }
        // Guestimate heuristic: perform spell checking if at least 3/4 of the characters
        // in this word are letters
        return (letterCount * 4 < length * 3) ? CHECKABILITY_TOO_MANY_NON_LETTERS : CHECKABILITY_CHECKABLE;
    }

    /**
     * Helper method to test valid capitalizations of a word.
     *
     * If the "text" is lower-case, we test only the exact string.
     * If the "Text" is capitalized, we test the exact string "Text" and the lower-cased
     *  version of it "text".
     * If the "TEXT" is fully upper case, we test the exact string "TEXT", the lower-cased
     *  version of it "text" and the capitalized version of it "Text".
     */
    private boolean isInDictForAnyCapitalization(final String text, final int capitalizeType) {
        // If the word is in there as is, then it's in the dictionary. If not, we'll test lower
        // case versions, but only if the word is not already all-lower case or mixed case.
        if (mService.isValidWord(mLocale, text))
            return true;
        if (StringUtils.CAPITALIZE_NONE == capitalizeType)
            return false;
        // If we come here, we have a capitalized word (either First- or All-).
        // Downcase the word and look it up again. If the word is only capitalized, we
        // tested all possibilities, so if it's still negative we can return false.
        final String lowerCaseText = text.toLowerCase(mLocale);
        if (mService.isValidWord(mLocale, lowerCaseText))
            return true;
        if (StringUtils.CAPITALIZE_FIRST == capitalizeType)
            return false;
        // If the lower case version is not in the dictionary, it's still possible
        // that we have an all-caps version of a word that needs to be capitalized
        // according to the dictionary. E.g. "GERMANS" only exists in the dictionary as "Germans".
        return mService.isValidWord(mLocale, StringUtils.capitalizeFirstAndDowncaseRest(lowerCaseText, mLocale));
    }

    // Note : this must be reentrant
    /**
     * Gets a list of suggestions for a specific string. This returns a list of possible
     * corrections for the text preplaceded as an argument. It may split or group words, and
     * even perform grammatical replacedysis.
     */
    private SuggestionsInfo onGetSuggestionsInternal(final TextInfo textInfo, final int suggestionsLimit) {
        return onGetSuggestionsInternal(textInfo, null, suggestionsLimit);
    }

    protected SuggestionsInfo onGetSuggestionsInternal(final TextInfo textInfo, final NgramContext ngramContext, final int suggestionsLimit) {
        try {
            final String text = textInfo.getText().replaceAll(AndroidSpellCheckerService.APOSTROPHE, AndroidSpellCheckerService.SINGLE_QUOTE).replaceAll("^" + quotesRegexp, "").replaceAll(quotesRegexp + "$", "");
            if (!mService.hasMainDictionaryForLocale(mLocale)) {
                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
            }
            // Handle special patterns like email, URI, telephone number.
            final int checkability = getCheckabilityInScript(text, mScript);
            if (CHECKABILITY_CHECKABLE != checkability) {
                if (CHECKABILITY_CONTAINS_PERIOD == checkability) {
                    final String[] splitText = text.split(Constants.REGEXP_PERIOD);
                    boolean allWordsAreValid = true;
                    for (final String word : splitText) {
                        if (!mService.isValidWord(mLocale, word)) {
                            allWordsAreValid = false;
                            break;
                        }
                    }
                    if (allWordsAreValid) {
                        return new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS, new String[] { TextUtils.join(Constants.STRING_SPACE, splitText) });
                    }
                }
                return mService.isValidWord(mLocale, text) ? AndroidSpellCheckerService.getInDictEmptySuggestions() : AndroidSpellCheckerService.getNotInDictEmptySuggestions(CHECKABILITY_CONTAINS_PERIOD == checkability);
            }
            // Handle normal words.
            final int capitalizeType = StringUtils.getCapitalizationType(text);
            if (isInDictForAnyCapitalization(text, capitalizeType)) {
                if (DebugFlags.DEBUG_ENABLED) {
                    Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is a valid word");
                }
                return AndroidSpellCheckerService.getInDictEmptySuggestions();
            }
            if (DebugFlags.DEBUG_ENABLED) {
                Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is NOT a valid word");
            }
            final Keyboard keyboard = mService.getKeyboardForLocale(mLocale);
            if (null == keyboard) {
                Log.w(TAG, "onGetSuggestionsInternal() : No keyboard for locale: " + mLocale);
                // If there is no keyboard for this locale, don't do any spell-checking.
                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
            }
            final WordComposer composer = new WordComposer();
            final int[] codePoints = StringUtils.toCodePointArray(text);
            final int[] coordinates;
            coordinates = keyboard.getCoordinates(codePoints);
            composer.setComposingWord(codePoints, coordinates);
            // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
            final SuggestionResults suggestionResults = mService.getSuggestionResults(mLocale, composer.getComposedDataSnapshot(), ngramContext, keyboard);
            final Result result = getResult(capitalizeType, mLocale, suggestionsLimit, mService.getRecommendedThreshold(), text, suggestionResults);
            if (DebugFlags.DEBUG_ENABLED) {
                if (result.mSuggestions != null && result.mSuggestions.length > 0) {
                    final StringBuilder builder = new StringBuilder();
                    for (String suggestion : result.mSuggestions) {
                        builder.append(" [");
                        builder.append(suggestion);
                        builder.append("]");
                    }
                    Log.i(TAG, "onGetSuggestionsInternal() : Suggestions =" + builder);
                }
            }
            // Handle word not in dictionary.
            // This is called only once per unique word, so entering multiple
            // instances of the same word does not result in more than one call
            // to this method.
            // Also, upon changing the orientation of the device, this is called
            // again for every unique invalid word in the text box.
            StatsUtils.onInvalidWordIdentification(text);
            final int flags = SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | (result.mHasRecommendedSuggestions ? SuggestionsInfoCompatUtils.getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() : 0);
            final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
            mSuggestionsCache.putSuggestionsToCache(text, result.mSuggestions, flags);
            return retval;
        } catch (RuntimeException e) {
            // Don't kill the keyboard if there is a bug in the spell checker
            Log.e(TAG, "Exception while spellchecking", e);
            return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
        }
    }

    private static final clreplaced Result {

        public final String[] mSuggestions;

        public final boolean mHasRecommendedSuggestions;

        public Result(final String[] gatheredSuggestions, final boolean hasRecommendedSuggestions) {
            mSuggestions = gatheredSuggestions;
            mHasRecommendedSuggestions = hasRecommendedSuggestions;
        }
    }

    private static Result getResult(final int capitalizeType, final Locale locale, final int suggestionsLimit, final float recommendedThreshold, final String originalText, final SuggestionResults suggestionResults) {
        if (suggestionResults.isEmpty() || suggestionsLimit <= 0) {
            return new Result(null, /* gatheredSuggestions */
            false);
        }
        final ArrayList<String> suggestions = new ArrayList<>();
        for (final SuggestedWordInfo suggestedWordInfo : suggestionResults) {
            final String suggestion;
            if (StringUtils.CAPITALIZE_ALL == capitalizeType) {
                suggestion = suggestedWordInfo.mWord.toUpperCase(locale);
            } else if (StringUtils.CAPITALIZE_FIRST == capitalizeType) {
                suggestion = StringUtils.capitalizeFirstCodePoint(suggestedWordInfo.mWord, locale);
            } else {
                suggestion = suggestedWordInfo.mWord;
            }
            suggestions.add(suggestion);
        }
        StringUtils.removeDupes(suggestions);
        // This returns a String[], while toArray() returns an Object[] which cannot be cast
        // into a String[].
        final List<String> gatheredSuggestionsList = suggestions.subList(0, Math.min(suggestions.size(), suggestionsLimit));
        final String[] gatheredSuggestions = gatheredSuggestionsList.toArray(new String[gatheredSuggestionsList.size()]);
        final int bestScore = suggestionResults.first().mScore;
        final String bestSuggestion = suggestions.get(0);
        final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(originalText, bestSuggestion, bestScore);
        final boolean hasRecommendedSuggestions = (normalizedScore > recommendedThreshold);
        return new Result(gatheredSuggestions, hasRecommendedSuggestions);
    }

    /*
     * The spell checker acts on its own behalf. That is needed, in particular, to be able to
     * access the dictionary files, which the provider restricts to the idenreplacedy of Latin IME.
     * Since it's called externally by the application, the spell checker is using the idenreplacedy
     * of the application by default unless we clearCallingIdenreplacedy.
     * That's what the following method does.
     */
    @Override
    public SuggestionsInfo onGetSuggestions(final TextInfo textInfo, final int suggestionsLimit) {
        long ident = Binder.clearCallingIdenreplacedy();
        try {
            return onGetSuggestionsInternal(textInfo, suggestionsLimit);
        } finally {
            Binder.restoreCallingIdenreplacedy(ident);
        }
    }
}

18 Source : ContentResolver.java
with Apache License 2.0
from oasisfeng

public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
    throw new RuntimeException("Stub!");
}

18 Source : ContentResolver.java
with Apache License 2.0
from oasisfeng

public void notifyChange(Uri uri, ContentObserver observer) {
    throw new RuntimeException("Stub!");
}

18 Source : AndroidWordLevelSpellCheckerSession.java
with Apache License 2.0
from NlptechProduct

public abstract clreplaced AndroidWordLevelSpellCheckerSession extends Session {

    private static final String TAG = AndroidWordLevelSpellCheckerSession.clreplaced.getSimpleName();

    public final static String[] EMPTY_STRING_ARRAY = new String[0];

    // Immutable, but not available in the constructor.
    private Locale mLocale;

    // Cache this for performance
    // One of SCRIPT_LATIN or SCRIPT_CYRILLIC for now.
    private int mScript;

    private final AndroidSpellCheckerService mService;

    protected final SuggestionsCache mSuggestionsCache = new SuggestionsCache();

    private final ContentObserver mObserver;

    private static final String quotesRegexp = "(\\u0022|\\u0027|\\u0060|\\u00B4|\\u2018|\\u2018|\\u201C|\\u201D)";

    private static final clreplaced SuggestionsParams {

        public final String[] mSuggestions;

        public final int mFlags;

        public SuggestionsParams(String[] suggestions, int flags) {
            mSuggestions = suggestions;
            mFlags = flags;
        }
    }

    protected static final clreplaced SuggestionsCache {

        private static final int MAX_CACHE_SIZE = 50;

        private final LruCache<String, SuggestionsParams> mUnigramSuggestionsInfoCache = new LruCache<>(MAX_CACHE_SIZE);

        private static String generateKey(final String query) {
            return query + "";
        }

        public SuggestionsParams getSuggestionsFromCache(final String query) {
            return mUnigramSuggestionsInfoCache.get(query);
        }

        public void putSuggestionsToCache(final String query, final String[] suggestions, final int flags) {
            if (suggestions == null || TextUtils.isEmpty(query)) {
                return;
            }
            mUnigramSuggestionsInfoCache.put(generateKey(query), new SuggestionsParams(suggestions, flags));
        }

        public void clearCache() {
            mUnigramSuggestionsInfoCache.evictAll();
        }
    }

    AndroidWordLevelSpellCheckerSession(final AndroidSpellCheckerService service) {
        mService = service;
        final ContentResolver cres = service.getContentResolver();
        mObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean self) {
                mSuggestionsCache.clearCache();
            }
        };
        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
    }

    @Override
    public void onCreate() {
        final String localeString = getLocale();
        mLocale = (null == localeString) ? null : LocaleUtils.constructLocaleFromString(localeString);
        mScript = ScriptUtils.getScriptFromSpellCheckerLocale(mLocale);
    }

    @Override
    public void onClose() {
        final ContentResolver cres = mService.getContentResolver();
        cres.unregisterContentObserver(mObserver);
    }

    private static final int CHECKABILITY_CHECKABLE = 0;

    private static final int CHECKABILITY_TOO_MANY_NON_LETTERS = 1;

    private static final int CHECKABILITY_CONTAINS_PERIOD = 2;

    private static final int CHECKABILITY_EMAIL_OR_URL = 3;

    private static final int CHECKABILITY_FIRST_LETTER_UNCHECKABLE = 4;

    private static final int CHECKABILITY_TOO_SHORT = 5;

    /**
     * Finds out whether a particular string should be filtered out of spell checking.
     *
     * This will loosely match URLs, numbers, symbols. To avoid always underlining words that
     * we know we will never recognize, this accepts a script identifier that should be one
     * of the SCRIPT_* constants defined above, to rule out quickly characters from very
     * different languages.
     *
     * @param text the string to evaluate.
     * @param script the identifier for the script this spell checker recognizes
     * @return one of the FILTER_OUT_* constants above.
     */
    private static int getCheckabilityInScript(final String text, final int script) {
        if (TextUtils.isEmpty(text) || text.length() <= 1)
            return CHECKABILITY_TOO_SHORT;
        // TODO: check if an equivalent processing can't be done more quickly with a
        // compiled regexp.
        // Filter by first letter
        final int firstCodePoint = text.codePointAt(0);
        // Filter out words that don't start with a letter or an apostrophe
        if (!ScriptUtils.isLetterPartOfScript(firstCodePoint, script) && '\'' != firstCodePoint)
            return CHECKABILITY_FIRST_LETTER_UNCHECKABLE;
        // Filter contents
        final int length = text.length();
        int letterCount = 0;
        for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
            final int codePoint = text.codePointAt(i);
            // Any word containing a COMMERCIAL_AT is probably an e-mail address
            // Any word containing a SLASH is probably either an ad-hoc combination of two
            // words or a URI - in either case we don't want to spell check that
            if (Constants.CODE_COMMERCIAL_AT == codePoint || Constants.CODE_SLASH == codePoint) {
                return CHECKABILITY_EMAIL_OR_URL;
            }
            // If the string contains a period, native returns strange suggestions (it seems
            // to return suggestions for everything up to the period only and to ignore the
            // rest), so we suppress lookup if there is a period.
            // TODO: investigate why native returns these suggestions and remove this code.
            if (Constants.CODE_PERIOD == codePoint) {
                return CHECKABILITY_CONTAINS_PERIOD;
            }
            if (ScriptUtils.isLetterPartOfScript(codePoint, script))
                ++letterCount;
        }
        // Guestimate heuristic: perform spell checking if at least 3/4 of the characters
        // in this word are letters
        return (letterCount * 4 < length * 3) ? CHECKABILITY_TOO_MANY_NON_LETTERS : CHECKABILITY_CHECKABLE;
    }

    /**
     * Helper method to test valid capitalizations of a word.
     *
     * If the "text" is lower-case, we test only the exact string.
     * If the "Text" is capitalized, we test the exact string "Text" and the lower-cased
     *  version of it "text".
     * If the "TEXT" is fully upper case, we test the exact string "TEXT", the lower-cased
     *  version of it "text" and the capitalized version of it "Text".
     */
    private boolean isInDictForAnyCapitalization(final String text, final int capitalizeType) {
        // If the word is in there as is, then it's in the dictionary. If not, we'll test lower
        // case versions, but only if the word is not already all-lower case or mixed case.
        if (mService.isValidWord(mLocale, text))
            return true;
        if (StringUtils.CAPITALIZE_NONE == capitalizeType)
            return false;
        // If we come here, we have a capitalized word (either First- or All-).
        // Downcase the word and look it up again. If the word is only capitalized, we
        // tested all possibilities, so if it's still negative we can return false.
        final String lowerCaseText = text.toLowerCase(mLocale);
        if (mService.isValidWord(mLocale, lowerCaseText))
            return true;
        if (StringUtils.CAPITALIZE_FIRST == capitalizeType)
            return false;
        // If the lower case version is not in the dictionary, it's still possible
        // that we have an all-caps version of a word that needs to be capitalized
        // according to the dictionary. E.g. "GERMANS" only exists in the dictionary as "Germans".
        return mService.isValidWord(mLocale, StringUtils.capitalizeFirstAndDowncaseRest(lowerCaseText, mLocale));
    }

    // Note : this must be reentrant
    /**
     * Gets a list of suggestions for a specific string. This returns a list of possible
     * corrections for the text preplaceded as an argument. It may split or group words, and
     * even perform grammatical replacedysis.
     */
    private SuggestionsInfo onGetSuggestionsInternal(final TextInfo textInfo, final int suggestionsLimit) {
        return onGetSuggestionsInternal(textInfo, null, suggestionsLimit);
    }

    protected SuggestionsInfo onGetSuggestionsInternal(final TextInfo textInfo, final NgramContext ngramContext, final int suggestionsLimit) {
        try {
            final String text = textInfo.getText().replaceAll(AndroidSpellCheckerService.APOSTROPHE, AndroidSpellCheckerService.SINGLE_QUOTE).replaceAll("^" + quotesRegexp, "").replaceAll(quotesRegexp + "$", "");
            if (!mService.hasMainDictionaryForLocale(mLocale)) {
                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
            }
            // Handle special patterns like email, URI, telephone number.
            final int checkability = getCheckabilityInScript(text, mScript);
            if (CHECKABILITY_CHECKABLE != checkability) {
                if (CHECKABILITY_CONTAINS_PERIOD == checkability) {
                    final String[] splitText = text.split(Constants.REGEXP_PERIOD);
                    boolean allWordsAreValid = true;
                    for (final String word : splitText) {
                        if (!mService.isValidWord(mLocale, word)) {
                            allWordsAreValid = false;
                            break;
                        }
                    }
                    if (allWordsAreValid) {
                        return new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS, new String[] { TextUtils.join(Constants.STRING_SPACE, splitText) });
                    }
                }
                return mService.isValidWord(mLocale, text) ? AndroidSpellCheckerService.getInDictEmptySuggestions() : AndroidSpellCheckerService.getNotInDictEmptySuggestions(CHECKABILITY_CONTAINS_PERIOD == checkability);
            }
            // Handle normal words.
            final int capitalizeType = StringUtils.getCapitalizationType(text);
            if (isInDictForAnyCapitalization(text, capitalizeType)) {
                if (DebugFlags.DEBUG_ENABLED) {
                    Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is a valid word");
                }
                return AndroidSpellCheckerService.getInDictEmptySuggestions();
            }
            if (DebugFlags.DEBUG_ENABLED) {
                Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is NOT a valid word");
            }
            final Keyboard keyboard = mService.getKeyboardForLocale(mLocale);
            if (null == keyboard) {
                Log.w(TAG, "onGetSuggestionsInternal() : No keyboard for locale: " + mLocale);
                // If there is no keyboard for this locale, don't do any spell-checking.
                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
            }
            final WordComposer composer = new WordComposer();
            final int[] codePoints = StringUtils.toCodePointArray(text);
            final int[] coordinates;
            coordinates = keyboard.getCoordinates(codePoints);
            composer.setComposingWord(codePoints, coordinates);
            // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
            final SuggestionResults suggestionResults = mService.getSuggestionResults(mLocale, composer.getComposedDataSnapshot(), ngramContext, keyboard);
            final Result result = getResult(capitalizeType, mLocale, suggestionsLimit, mService.getRecommendedThreshold(), text, suggestionResults);
            if (DebugFlags.DEBUG_ENABLED) {
                if (result.mSuggestions != null && result.mSuggestions.length > 0) {
                    final StringBuilder builder = new StringBuilder();
                    for (String suggestion : result.mSuggestions) {
                        builder.append(" [");
                        builder.append(suggestion);
                        builder.append("]");
                    }
                    Log.i(TAG, "onGetSuggestionsInternal() : Suggestions =" + builder);
                }
            }
            // Handle word not in dictionary.
            // This is called only once per unique word, so entering multiple
            // instances of the same word does not result in more than one call
            // to this method.
            // Also, upon changing the orientation of the device, this is called
            // again for every unique invalid word in the text box.
            StatsUtils.onInvalidWordIdentification(text);
            final int flags = SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | (result.mHasRecommendedSuggestions ? SuggestionsInfoCompatUtils.getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() : 0);
            final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
            mSuggestionsCache.putSuggestionsToCache(text, result.mSuggestions, flags);
            return retval;
        } catch (RuntimeException e) {
            // Don't kill the keyboard if there is a bug in the spell checker
            Log.e(TAG, "Exception while spellchecking", e);
            return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
        }
    }

    private static final clreplaced Result {

        public final String[] mSuggestions;

        public final boolean mHasRecommendedSuggestions;

        public Result(final String[] gatheredSuggestions, final boolean hasRecommendedSuggestions) {
            mSuggestions = gatheredSuggestions;
            mHasRecommendedSuggestions = hasRecommendedSuggestions;
        }
    }

    private static Result getResult(final int capitalizeType, final Locale locale, final int suggestionsLimit, final float recommendedThreshold, final String originalText, final SuggestionResults suggestionResults) {
        if (suggestionResults.isEmpty() || suggestionsLimit <= 0) {
            return new Result(null, /* gatheredSuggestions */
            false);
        }
        final ArrayList<String> suggestions = new ArrayList<>();
        for (final SuggestedWords.SuggestedWordInfo suggestedWordInfo : suggestionResults) {
            final String suggestion;
            if (StringUtils.CAPITALIZE_ALL == capitalizeType) {
                suggestion = suggestedWordInfo.mWord.toUpperCase(locale);
            } else if (StringUtils.CAPITALIZE_FIRST == capitalizeType) {
                suggestion = StringUtils.capitalizeFirstCodePoint(suggestedWordInfo.mWord, locale);
            } else {
                suggestion = suggestedWordInfo.mWord;
            }
            suggestions.add(suggestion);
        }
        StringUtils.removeDupes(suggestions);
        // This returns a String[], while toArray() returns an Object[] which cannot be cast
        // into a String[].
        final List<String> gatheredSuggestionsList = suggestions.subList(0, Math.min(suggestions.size(), suggestionsLimit));
        final String[] gatheredSuggestions = gatheredSuggestionsList.toArray(new String[gatheredSuggestionsList.size()]);
        final int bestScore = suggestionResults.first().mScore;
        final String bestSuggestion = suggestions.get(0);
        final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(originalText, bestSuggestion, bestScore);
        final boolean hasRecommendedSuggestions = (normalizedScore > recommendedThreshold);
        return new Result(gatheredSuggestions, hasRecommendedSuggestions);
    }

    /*
     * The spell checker acts on its own behalf. That is needed, in particular, to be able to
     * access the dictionary files, which the provider restricts to the idenreplacedy of Latin IME.
     * Since it's called externally by the application, the spell checker is using the idenreplacedy
     * of the application by default unless we clearCallingIdenreplacedy.
     * That's what the following method does.
     */
    @Override
    public SuggestionsInfo onGetSuggestions(final TextInfo textInfo, final int suggestionsLimit) {
        long ident = Binder.clearCallingIdenreplacedy();
        try {
            return onGetSuggestionsInternal(textInfo, suggestionsLimit);
        } finally {
            Binder.restoreCallingIdenreplacedy(ident);
        }
    }
}

18 Source : SettingsCursor.java
with GNU General Public License v3.0
from MuntashirAkon

@Override
public void registerContentObserver(ContentObserver contentObserver) {
    if (cursor != null)
        cursor.registerContentObserver(contentObserver);
}

18 Source : GroupedThreadMediaLoader.java
with GNU General Public License v3.0
from mollyim

public final clreplaced GroupedThreadMediaLoader extends AsyncTaskLoader<GroupedThreadMediaLoader.GroupedThreadMedia> {

    @SuppressWarnings("unused")
    private static final String TAG = Log.tag(GroupedThreadMediaLoader.clreplaced);

    private final ContentObserver observer;

    private final MediaLoader.MediaType mediaType;

    private final MediaDatabase.Sorting sorting;

    private final long threadId;

    public GroupedThreadMediaLoader(@NonNull Context context, long threadId, @NonNull MediaLoader.MediaType mediaType, @NonNull MediaDatabase.Sorting sorting) {
        super(context);
        this.threadId = threadId;
        this.mediaType = mediaType;
        this.sorting = sorting;
        this.observer = new ForceLoadContentObserver();
        onContentChanged();
    }

    @Override
    protected void onStartLoading() {
        if (takeContentChanged()) {
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading() {
        cancelLoad();
    }

    @Override
    protected void onAbandon() {
        DatabaseFactory.getMediaDatabase(getContext()).unsubscribeToMediaChanges(observer);
    }

    @Override
    public GroupedThreadMedia loadInBackground() {
        Context context = getContext();
        GroupingMethod groupingMethod = sorting.isRelatedToFileSize() ? new RoughSizeGroupingMethod(context) : new DateGroupingMethod(context, CalendarDateOnly.getInstance());
        PopulatedGroupedThreadMedia mediaGrouping = new PopulatedGroupedThreadMedia(groupingMethod);
        DatabaseFactory.getMediaDatabase(context).subscribeToMediaChanges(observer);
        try (Cursor cursor = ThreadMediaLoader.createThreadMediaCursor(context, threadId, mediaType, sorting)) {
            while (cursor != null && cursor.moveToNext()) {
                mediaGrouping.add(MediaDatabase.MediaRecord.from(context, cursor));
            }
        }
        if (sorting == MediaDatabase.Sorting.Oldest || sorting == MediaDatabase.Sorting.Largest) {
            return new ReversedGroupedThreadMedia(mediaGrouping);
        } else {
            return mediaGrouping;
        }
    }

    public interface GroupingMethod {

        int groupForRecord(@NonNull MediaDatabase.MediaRecord mediaRecord);

        @NonNull
        String groupName(int groupNo);
    }

    public static clreplaced DateGroupingMethod implements GroupingMethod {

        private final Context context;

        private final long yesterdayStart;

        private final long todayStart;

        private final long thisWeekStart;

        private final long thisMonthStart;

        private static final int TODAY = Integer.MIN_VALUE;

        private static final int YESTERDAY = Integer.MIN_VALUE + 1;

        private static final int THIS_WEEK = Integer.MIN_VALUE + 2;

        private static final int THIS_MONTH = Integer.MIN_VALUE + 3;

        DateGroupingMethod(@NonNull Context context, @NonNull Calendar today) {
            this.context = context;
            todayStart = today.getTimeInMillis();
            yesterdayStart = getTimeInMillis(today, Calendar.DAY_OF_YEAR, -1);
            thisWeekStart = getTimeInMillis(today, Calendar.DAY_OF_YEAR, -6);
            thisMonthStart = getTimeInMillis(today, Calendar.DAY_OF_YEAR, -30);
        }

        private static long getTimeInMillis(@NonNull Calendar now, int field, int offset) {
            Calendar copy = (Calendar) now.clone();
            copy.add(field, offset);
            return copy.getTimeInMillis();
        }

        @Override
        public int groupForRecord(@NonNull MediaDatabase.MediaRecord mediaRecord) {
            long date = mediaRecord.getDate();
            if (date > todayStart)
                return TODAY;
            if (date > yesterdayStart)
                return YESTERDAY;
            if (date > thisWeekStart)
                return THIS_WEEK;
            if (date > thisMonthStart)
                return THIS_MONTH;
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(date);
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH);
            return -(year * 12 + month);
        }

        @Override
        @NonNull
        public String groupName(int groupNo) {
            switch(groupNo) {
                case TODAY:
                    return context.getString(R.string.BucketedThreadMedia_Today);
                case YESTERDAY:
                    return context.getString(R.string.BucketedThreadMedia_Yesterday);
                case THIS_WEEK:
                    return context.getString(R.string.BucketedThreadMedia_This_week);
                case THIS_MONTH:
                    return context.getString(R.string.BucketedThreadMedia_This_month);
                default:
                    int yearAndMonth = -groupNo;
                    int month = yearAndMonth % 12;
                    int year = yearAndMonth / 12;
                    Calendar calendar = Calendar.getInstance();
                    calendar.set(Calendar.YEAR, year);
                    calendar.set(Calendar.MONTH, month);
                    return new SimpleDateFormat("MMMM, yyyy", Locale.getDefault()).format(calendar.getTime());
            }
        }
    }

    public static clreplaced RoughSizeGroupingMethod implements GroupingMethod {

        private final String largeDescription;

        private final String mediumDescription;

        private final String smallDescription;

        private static final int MB = 1024 * 1024;

        private static final int SMALL = 0;

        private static final int MEDIUM = 1;

        private static final int LARGE = 2;

        RoughSizeGroupingMethod(@NonNull Context context) {
            smallDescription = context.getString(R.string.BucketedThreadMedia_Small);
            mediumDescription = context.getString(R.string.BucketedThreadMedia_Medium);
            largeDescription = context.getString(R.string.BucketedThreadMedia_Large);
        }

        @Override
        public int groupForRecord(@NonNull MediaDatabase.MediaRecord mediaRecord) {
            long size = mediaRecord.getAttachment().getSize();
            if (size < MB)
                return SMALL;
            if (size < 20 * MB)
                return MEDIUM;
            return LARGE;
        }

        @Override
        @NonNull
        public String groupName(int groupNo) {
            switch(groupNo) {
                case SMALL:
                    return smallDescription;
                case MEDIUM:
                    return mediumDescription;
                case LARGE:
                    return largeDescription;
                default:
                    throw new replacedertionError();
            }
        }
    }

    public static abstract clreplaced GroupedThreadMedia {

        public abstract int getSectionCount();

        public abstract int getSectionItemCount(int section);

        @NonNull
        public abstract MediaDatabase.MediaRecord get(int section, int item);

        @NonNull
        public abstract String getName(int section);
    }

    public static clreplaced EmptyGroupedThreadMedia extends GroupedThreadMedia {

        @Override
        public int getSectionCount() {
            return 0;
        }

        @Override
        public int getSectionItemCount(int section) {
            return 0;
        }

        @Override
        @NonNull
        public MediaDatabase.MediaRecord get(int section, int item) {
            throw new replacedertionError();
        }

        @Override
        @NonNull
        public String getName(int section) {
            throw new replacedertionError();
        }
    }

    public static clreplaced ReversedGroupedThreadMedia extends GroupedThreadMedia {

        private final GroupedThreadMedia decorated;

        ReversedGroupedThreadMedia(@NonNull GroupedThreadMedia decorated) {
            this.decorated = decorated;
        }

        @Override
        public int getSectionCount() {
            return decorated.getSectionCount();
        }

        @Override
        public int getSectionItemCount(int section) {
            return decorated.getSectionItemCount(getReversedSection(section));
        }

        @Override
        @NonNull
        public MediaDatabase.MediaRecord get(int section, int item) {
            return decorated.get(getReversedSection(section), item);
        }

        @Override
        @NonNull
        public String getName(int section) {
            return decorated.getName(getReversedSection(section));
        }

        private int getReversedSection(int section) {
            return decorated.getSectionCount() - 1 - section;
        }
    }

    private static clreplaced PopulatedGroupedThreadMedia extends GroupedThreadMedia {

        @NonNull
        private final GroupingMethod groupingMethod;

        private final SparseArray<List<MediaDatabase.MediaRecord>> records = new SparseArray<>();

        private PopulatedGroupedThreadMedia(@NonNull GroupingMethod groupingMethod) {
            this.groupingMethod = groupingMethod;
        }

        private void add(@NonNull MediaDatabase.MediaRecord mediaRecord) {
            int groupNo = groupingMethod.groupForRecord(mediaRecord);
            List<MediaDatabase.MediaRecord> mediaRecords = records.get(groupNo);
            if (mediaRecords == null) {
                mediaRecords = new LinkedList<>();
                records.put(groupNo, mediaRecords);
            }
            mediaRecords.add(mediaRecord);
        }

        @Override
        public int getSectionCount() {
            return records.size();
        }

        @Override
        public int getSectionItemCount(int section) {
            return records.get(records.keyAt(section)).size();
        }

        @Override
        @NonNull
        public MediaDatabase.MediaRecord get(int section, int item) {
            return records.get(records.keyAt(section)).get(item);
        }

        @Override
        @NonNull
        public String getName(int section) {
            return groupingMethod.groupName(records.keyAt(section));
        }
    }
}

18 Source : Database.java
with GNU General Public License v3.0
from mollyim

protected void registerAttachmentListeners(@NonNull ContentObserver observer) {
    context.getContentResolver().registerContentObserver(DatabaseContentProviders.Attachment.CONTENT_URI, true, observer);
}

18 Source : CalendarTracker.java
with Apache License 2.0
from lulululbj

public clreplaced CalendarTracker {

    private static final String TAG = "ConditionProviders.CT";

    private static final boolean DEBUG = Log.isLoggable("ConditionProviders", Log.DEBUG);

    private static final boolean DEBUG_ATTENDEES = false;

    private static final int EVENT_CHECK_LOOKAHEAD = 24 * 60 * 60 * 1000;

    private static final String[] INSTANCE_PROJECTION = { Instances.BEGIN, Instances.END, Instances.replacedLE, Instances.VISIBLE, Instances.EVENT_ID, Instances.CALENDAR_DISPLAY_NAME, Instances.OWNER_ACCOUNT, Instances.CALENDAR_ID, Instances.AVAILABILITY };

    private static final String INSTANCE_ORDER_BY = Instances.BEGIN + " ASC";

    private static final String[] ATTENDEE_PROJECTION = { Attendees.EVENT_ID, Attendees.ATTENDEE_EMAIL, Attendees.ATTENDEE_STATUS };

    private static final String ATTENDEE_SELECTION = Attendees.EVENT_ID + " = ? AND " + Attendees.ATTENDEE_EMAIL + " = ?";

    private final Context mSystemContext;

    private final Context mUserContext;

    private Callback mCallback;

    private boolean mRegistered;

    public CalendarTracker(Context systemContext, Context userContext) {
        mSystemContext = systemContext;
        mUserContext = userContext;
    }

    public void setCallback(Callback callback) {
        if (mCallback == callback)
            return;
        mCallback = callback;
        setRegistered(mCallback != null);
    }

    public void dump(String prefix, PrintWriter pw) {
        pw.print(prefix);
        pw.print("mCallback=");
        pw.println(mCallback);
        pw.print(prefix);
        pw.print("mRegistered=");
        pw.println(mRegistered);
        pw.print(prefix);
        pw.print("u=");
        pw.println(mUserContext.getUserId());
    }

    private ArraySet<Long> getPrimaryCalendars() {
        final long start = System.currentTimeMillis();
        final ArraySet<Long> rt = new ArraySet<>();
        final String primary = "\"primary\"";
        final String[] projection = { Calendars._ID, "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + primary };
        final String selection = primary + " = 1";
        Cursor cursor = null;
        try {
            cursor = mUserContext.getContentResolver().query(Calendars.CONTENT_URI, projection, selection, null, null);
            while (cursor != null && cursor.moveToNext()) {
                rt.add(cursor.getLong(0));
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        if (DEBUG)
            Log.d(TAG, "getPrimaryCalendars took " + (System.currentTimeMillis() - start));
        return rt;
    }

    public CheckEventResult checkEvent(EventInfo filter, long time) {
        final Uri.Builder uriBuilder = Instances.CONTENT_URI.buildUpon();
        ContentUris.appendId(uriBuilder, time);
        ContentUris.appendId(uriBuilder, time + EVENT_CHECK_LOOKAHEAD);
        final Uri uri = uriBuilder.build();
        final Cursor cursor = mUserContext.getContentResolver().query(uri, INSTANCE_PROJECTION, null, null, INSTANCE_ORDER_BY);
        final CheckEventResult result = new CheckEventResult();
        result.recheckAt = time + EVENT_CHECK_LOOKAHEAD;
        try {
            final ArraySet<Long> primaryCalendars = getPrimaryCalendars();
            while (cursor != null && cursor.moveToNext()) {
                final long begin = cursor.getLong(0);
                final long end = cursor.getLong(1);
                final String replacedle = cursor.getString(2);
                final boolean calendarVisible = cursor.getInt(3) == 1;
                final int eventId = cursor.getInt(4);
                final String name = cursor.getString(5);
                final String owner = cursor.getString(6);
                final long calendarId = cursor.getLong(7);
                final int availability = cursor.getInt(8);
                final boolean calendarPrimary = primaryCalendars.contains(calendarId);
                if (DEBUG)
                    Log.d(TAG, String.format("%s %s-%s v=%s a=%s eid=%s n=%s o=%s cid=%s p=%s", replacedle, new Date(begin), new Date(end), calendarVisible, availabilityToString(availability), eventId, name, owner, calendarId, calendarPrimary));
                final boolean meetsTime = time >= begin && time < end;
                final boolean meetsCalendar = calendarVisible && calendarPrimary && (filter.calendar == null || Objects.equals(filter.calendar, owner) || Objects.equals(filter.calendar, name));
                final boolean meetsAvailability = availability != Instances.AVAILABILITY_FREE;
                if (meetsCalendar && meetsAvailability) {
                    if (DEBUG)
                        Log.d(TAG, "  MEETS CALENDAR & AVAILABILITY");
                    final boolean meetsAttendee = meetsAttendee(filter, eventId, owner);
                    if (meetsAttendee) {
                        if (DEBUG)
                            Log.d(TAG, "    MEETS ATTENDEE");
                        if (meetsTime) {
                            if (DEBUG)
                                Log.d(TAG, "      MEETS TIME");
                            result.inEvent = true;
                        }
                        if (begin > time && begin < result.recheckAt) {
                            result.recheckAt = begin;
                        } else if (end > time && end < result.recheckAt) {
                            result.recheckAt = end;
                        }
                    }
                }
            }
        } catch (Exception e) {
            Slog.w(TAG, "error reading calendar", e);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return result;
    }

    private boolean meetsAttendee(EventInfo filter, int eventId, String email) {
        final long start = System.currentTimeMillis();
        String selection = ATTENDEE_SELECTION;
        String[] selectionArgs = { Integer.toString(eventId), email };
        if (DEBUG_ATTENDEES) {
            selection = null;
            selectionArgs = null;
        }
        final Cursor cursor = mUserContext.getContentResolver().query(Attendees.CONTENT_URI, ATTENDEE_PROJECTION, selection, selectionArgs, null);
        try {
            if (cursor == null || cursor.getCount() == 0) {
                if (DEBUG)
                    Log.d(TAG, "No attendees found");
                return true;
            }
            boolean rt = false;
            while (cursor != null && cursor.moveToNext()) {
                final long rowEventId = cursor.getLong(0);
                final String rowEmail = cursor.getString(1);
                final int status = cursor.getInt(2);
                final boolean meetsReply = meetsReply(filter.reply, status);
                if (DEBUG)
                    Log.d(TAG, (DEBUG_ATTENDEES ? String.format("rowEventId=%s, rowEmail=%s, ", rowEventId, rowEmail) : "") + String.format("status=%s, meetsReply=%s", attendeeStatusToString(status), meetsReply));
                final boolean eventMeets = rowEventId == eventId && Objects.equals(rowEmail, email) && meetsReply;
                rt |= eventMeets;
            }
            return rt;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (DEBUG)
                Log.d(TAG, "meetsAttendee took " + (System.currentTimeMillis() - start));
        }
    }

    private void setRegistered(boolean registered) {
        if (mRegistered == registered)
            return;
        final ContentResolver cr = mSystemContext.getContentResolver();
        final int userId = mUserContext.getUserId();
        if (mRegistered) {
            if (DEBUG)
                Log.d(TAG, "unregister content observer u=" + userId);
            cr.unregisterContentObserver(mObserver);
        }
        mRegistered = registered;
        if (DEBUG)
            Log.d(TAG, "mRegistered = " + registered + " u=" + userId);
        if (mRegistered) {
            if (DEBUG)
                Log.d(TAG, "register content observer u=" + userId);
            cr.registerContentObserver(Instances.CONTENT_URI, true, mObserver, userId);
            cr.registerContentObserver(Events.CONTENT_URI, true, mObserver, userId);
            cr.registerContentObserver(Calendars.CONTENT_URI, true, mObserver, userId);
        }
    }

    private static String attendeeStatusToString(int status) {
        switch(status) {
            case Attendees.ATTENDEE_STATUS_NONE:
                return "ATTENDEE_STATUS_NONE";
            case Attendees.ATTENDEE_STATUS_ACCEPTED:
                return "ATTENDEE_STATUS_ACCEPTED";
            case Attendees.ATTENDEE_STATUS_DECLINED:
                return "ATTENDEE_STATUS_DECLINED";
            case Attendees.ATTENDEE_STATUS_INVITED:
                return "ATTENDEE_STATUS_INVITED";
            case Attendees.ATTENDEE_STATUS_TENTATIVE:
                return "ATTENDEE_STATUS_TENTATIVE";
            default:
                return "ATTENDEE_STATUS_UNKNOWN_" + status;
        }
    }

    private static String availabilityToString(int availability) {
        switch(availability) {
            case Instances.AVAILABILITY_BUSY:
                return "AVAILABILITY_BUSY";
            case Instances.AVAILABILITY_FREE:
                return "AVAILABILITY_FREE";
            case Instances.AVAILABILITY_TENTATIVE:
                return "AVAILABILITY_TENTATIVE";
            default:
                return "AVAILABILITY_UNKNOWN_" + availability;
        }
    }

    private static boolean meetsReply(int reply, int attendeeStatus) {
        switch(reply) {
            case EventInfo.REPLY_YES:
                return attendeeStatus == Attendees.ATTENDEE_STATUS_ACCEPTED;
            case EventInfo.REPLY_YES_OR_MAYBE:
                return attendeeStatus == Attendees.ATTENDEE_STATUS_ACCEPTED || attendeeStatus == Attendees.ATTENDEE_STATUS_TENTATIVE;
            case EventInfo.REPLY_ANY_EXCEPT_NO:
                return attendeeStatus != Attendees.ATTENDEE_STATUS_DECLINED;
            default:
                return false;
        }
    }

    private final ContentObserver mObserver = new ContentObserver(null) {

        @Override
        public void onChange(boolean selfChange, Uri u) {
            if (DEBUG)
                Log.d(TAG, "onChange selfChange=" + selfChange + " uri=" + u + " u=" + mUserContext.getUserId());
            mCallback.onChanged();
        }

        @Override
        public void onChange(boolean selfChange) {
            if (DEBUG)
                Log.d(TAG, "onChange selfChange=" + selfChange);
        }
    };

    public static clreplaced CheckEventResult {

        public boolean inEvent;

        public long recheckAt;
    }

    public interface Callback {

        void onChanged();
    }
}

18 Source : ScreenShotHelper.java
with GNU General Public License v3.0
from farkam135

public clreplaced ScreenShotHelper {

    private static ScreenShotHelper instance = null;

    public static boolean sShouldRecalibrateWithNextScreenshot = false;

    private ContentObserver mediaObserver;

    private ContentResolver contentResolver;

    private String getRealPathFromUri(Uri contentUri) {
        Cursor cursor = null;
        try {
            String[] proj = { MediaStore.Images.Media.DATA };
            cursor = contentResolver.query(contentUri, proj, null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    private ScreenShotHelper(final Context context) {
        this.contentResolver = context.getContentResolver();
        mediaObserver = new ContentObserver(new Handler()) {

            @Override
            public void onChange(boolean selfChange, Uri uri) {
                super.onChange(selfChange, uri);
                if (!uri.toString().contains("images")) {
                    return;
                }
                final String pathChange = getRealPathFromUri(uri);
                if (!pathChange.contains("Screenshot")) {
                    return;
                }
                /* Ignore random events related to opening old screenshots by making
                 * sure the file was created within the past 10 seconds.
                 */
                long now = Calendar.getInstance().getTimeInMillis();
                long filetime = new File(pathChange).lastModified();
                if (now - filetime > 10000) {
                    return;
                }
                Bitmap bitmap = null;
                try {
                    bitmap = BitmapFactory.decodeFile(pathChange);
                } catch (Exception e) {
                    Timber.log(Log.ERROR, e);
                } finally {
                    if (bitmap != null) {
                        if (sShouldRecalibrateWithNextScreenshot) {
                            // Use the screenshot to recalibrate GoIV
                            OcrCalibrationResultActivity.startCalibration(context, bitmap, 0, 0);
                            sShouldRecalibrateWithNextScreenshot = false;
                            if (GoIVSettings.getInstance(context).shouldDeleteScreenshots()) {
                                deleteScreenShot(pathChange);
                            }
                        } else {
                            // Scan 'mon info
                            Intent newintent = Pokefly.createProcessBitmapIntent(bitmap, pathChange);
                            LocalBroadcastManager.getInstance(context).sendBroadcast(newintent);
                        }
                    }
                }
            }
        };
        contentResolver.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, mediaObserver);
    }

    public static ScreenShotHelper start(final Context context) {
        if (instance == null) {
            instance = new ScreenShotHelper(context);
        }
        return instance;
    }

    public void deleteScreenShot(String filePath) {
        contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Files.FileColumns.DATA + "=?", new String[] { filePath });
    }

    public void stop() {
        contentResolver.unregisterContentObserver(mediaObserver);
        contentResolver = null;
        mediaObserver = null;
        instance = null;
    }
}

18 Source : AndroidWordLevelSpellCheckerSession.java
with GNU General Public License v3.0
from dslul

public abstract clreplaced AndroidWordLevelSpellCheckerSession extends Session {

    private static final String TAG = AndroidWordLevelSpellCheckerSession.clreplaced.getSimpleName();

    public final static String[] EMPTY_STRING_ARRAY = new String[0];

    // Immutable, but not available in the constructor.
    private Locale mLocale;

    // Cache this for performance
    // One of SCRIPT_LATIN or SCRIPT_CYRILLIC for now.
    private int mScript;

    private final AndroidSpellCheckerService mService;

    protected final SuggestionsCache mSuggestionsCache = new SuggestionsCache();

    private final ContentObserver mObserver;

    private static final String quotesRegexp = "(\\u0022|\\u0027|\\u0060|\\u00B4|\\u2018|\\u2018|\\u201C|\\u201D)";

    private static final clreplaced SuggestionsParams {

        public final String[] mSuggestions;

        public final int mFlags;

        public SuggestionsParams(String[] suggestions, int flags) {
            mSuggestions = suggestions;
            mFlags = flags;
        }
    }

    protected static final clreplaced SuggestionsCache {

        private static final int MAX_CACHE_SIZE = 50;

        private final LruCache<String, SuggestionsParams> mUnigramSuggestionsInfoCache = new LruCache<>(MAX_CACHE_SIZE);

        private static String generateKey(final String query) {
            return query + "";
        }

        public SuggestionsParams getSuggestionsFromCache(final String query) {
            return mUnigramSuggestionsInfoCache.get(query);
        }

        public void putSuggestionsToCache(final String query, final String[] suggestions, final int flags) {
            if (suggestions == null || TextUtils.isEmpty(query)) {
                return;
            }
            mUnigramSuggestionsInfoCache.put(generateKey(query), new SuggestionsParams(suggestions, flags));
        }

        public void clearCache() {
            mUnigramSuggestionsInfoCache.evictAll();
        }
    }

    AndroidWordLevelSpellCheckerSession(final AndroidSpellCheckerService service) {
        mService = service;
        final ContentResolver cres = service.getContentResolver();
        mObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean self) {
                mSuggestionsCache.clearCache();
            }
        };
        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
    }

    @Override
    public void onCreate() {
        final String localeString = getLocale();
        mLocale = (null == localeString) ? null : LocaleUtils.constructLocaleFromString(localeString);
        mScript = ScriptUtils.getScriptFromSpellCheckerLocale(mLocale);
    }

    @Override
    public void onClose() {
        final ContentResolver cres = mService.getContentResolver();
        cres.unregisterContentObserver(mObserver);
    }

    private static final int CHECKABILITY_CHECKABLE = 0;

    private static final int CHECKABILITY_TOO_MANY_NON_LETTERS = 1;

    private static final int CHECKABILITY_CONTAINS_PERIOD = 2;

    private static final int CHECKABILITY_EMAIL_OR_URL = 3;

    private static final int CHECKABILITY_FIRST_LETTER_UNCHECKABLE = 4;

    private static final int CHECKABILITY_TOO_SHORT = 5;

    /**
     * Finds out whether a particular string should be filtered out of spell checking.
     *
     * This will loosely match URLs, numbers, symbols. To avoid always underlining words that
     * we know we will never recognize, this accepts a script identifier that should be one
     * of the SCRIPT_* constants defined above, to rule out quickly characters from very
     * different languages.
     *
     * @param text the string to evaluate.
     * @param script the identifier for the script this spell checker recognizes
     * @return one of the FILTER_OUT_* constants above.
     */
    private static int getCheckabilityInScript(final String text, final int script) {
        if (TextUtils.isEmpty(text) || text.length() <= 1)
            return CHECKABILITY_TOO_SHORT;
        // TODO: check if an equivalent processing can't be done more quickly with a
        // compiled regexp.
        // Filter by first letter
        final int firstCodePoint = text.codePointAt(0);
        // Filter out words that don't start with a letter or an apostrophe
        if (!ScriptUtils.isLetterPartOfScript(firstCodePoint, script) && '\'' != firstCodePoint)
            return CHECKABILITY_FIRST_LETTER_UNCHECKABLE;
        // Filter contents
        final int length = text.length();
        int letterCount = 0;
        for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
            final int codePoint = text.codePointAt(i);
            // Any word containing a COMMERCIAL_AT is probably an e-mail address
            // Any word containing a SLASH is probably either an ad-hoc combination of two
            // words or a URI - in either case we don't want to spell check that
            if (Constants.CODE_COMMERCIAL_AT == codePoint || Constants.CODE_SLASH == codePoint) {
                return CHECKABILITY_EMAIL_OR_URL;
            }
            // If the string contains a period, native returns strange suggestions (it seems
            // to return suggestions for everything up to the period only and to ignore the
            // rest), so we suppress lookup if there is a period.
            // TODO: investigate why native returns these suggestions and remove this code.
            if (Constants.CODE_PERIOD == codePoint) {
                return CHECKABILITY_CONTAINS_PERIOD;
            }
            if (ScriptUtils.isLetterPartOfScript(codePoint, script))
                ++letterCount;
        }
        // Guestimate heuristic: perform spell checking if at least 3/4 of the characters
        // in this word are letters
        return (letterCount * 4 < length * 3) ? CHECKABILITY_TOO_MANY_NON_LETTERS : CHECKABILITY_CHECKABLE;
    }

    /**
     * Helper method to test valid capitalizations of a word.
     *
     * If the "text" is lower-case, we test only the exact string.
     * If the "Text" is capitalized, we test the exact string "Text" and the lower-cased
     *  version of it "text".
     * If the "TEXT" is fully upper case, we test the exact string "TEXT", the lower-cased
     *  version of it "text" and the capitalized version of it "Text".
     */
    private boolean isInDictForAnyCapitalization(final String text, final int capitalizeType) {
        // If the word is in there as is, then it's in the dictionary. If not, we'll test lower
        // case versions, but only if the word is not already all-lower case or mixed case.
        if (mService.isValidWord(mLocale, text))
            return true;
        if (StringUtils.CAPITALIZE_NONE == capitalizeType)
            return false;
        // If we come here, we have a capitalized word (either First- or All-).
        // Downcase the word and look it up again. If the word is only capitalized, we
        // tested all possibilities, so if it's still negative we can return false.
        final String lowerCaseText = text.toLowerCase(mLocale);
        if (mService.isValidWord(mLocale, lowerCaseText))
            return true;
        if (StringUtils.CAPITALIZE_FIRST == capitalizeType)
            return false;
        // If the lower case version is not in the dictionary, it's still possible
        // that we have an all-caps version of a word that needs to be capitalized
        // according to the dictionary. E.g. "GERMANS" only exists in the dictionary as "Germans".
        return mService.isValidWord(mLocale, StringUtils.capitalizeFirstAndDowncaseRest(lowerCaseText, mLocale));
    }

    // Note : this must be reentrant
    /**
     * Gets a list of suggestions for a specific string. This returns a list of possible
     * corrections for the text preplaceded as an argument. It may split or group words, and
     * even perform grammatical replacedysis.
     */
    private SuggestionsInfo onGetSuggestionsInternal(final TextInfo textInfo, final int suggestionsLimit) {
        return onGetSuggestionsInternal(textInfo, null, suggestionsLimit);
    }

    protected SuggestionsInfo onGetSuggestionsInternal(final TextInfo textInfo, final NgramContext ngramContext, final int suggestionsLimit) {
        try {
            final String text = textInfo.getText().replaceAll(AndroidSpellCheckerService.APOSTROPHE, AndroidSpellCheckerService.SINGLE_QUOTE).replaceAll("^" + quotesRegexp, "").replaceAll(quotesRegexp + "$", "");
            if (!mService.hasMainDictionaryForLocale(mLocale)) {
                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
            }
            // Handle special patterns like email, URI, telephone number.
            final int checkability = getCheckabilityInScript(text, mScript);
            if (CHECKABILITY_CHECKABLE != checkability) {
                if (CHECKABILITY_CONTAINS_PERIOD == checkability) {
                    final String[] splitText = text.split(Constants.REGEXP_PERIOD);
                    boolean allWordsAreValid = true;
                    for (final String word : splitText) {
                        if (!mService.isValidWord(mLocale, word)) {
                            allWordsAreValid = false;
                            break;
                        }
                    }
                    if (allWordsAreValid) {
                        return new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS, new String[] { TextUtils.join(Constants.STRING_SPACE, splitText) });
                    }
                }
                return mService.isValidWord(mLocale, text) ? AndroidSpellCheckerService.getInDictEmptySuggestions() : AndroidSpellCheckerService.getNotInDictEmptySuggestions(CHECKABILITY_CONTAINS_PERIOD == checkability);
            }
            // Handle normal words.
            final int capitalizeType = StringUtils.getCapitalizationType(text);
            if (isInDictForAnyCapitalization(text, capitalizeType)) {
                if (DebugFlags.DEBUG_ENABLED) {
                    Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is a valid word");
                }
                return AndroidSpellCheckerService.getInDictEmptySuggestions();
            }
            if (DebugFlags.DEBUG_ENABLED) {
                Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is NOT a valid word");
            }
            final Keyboard keyboard = mService.getKeyboardForLocale(mLocale);
            if (null == keyboard) {
                Log.w(TAG, "onGetSuggestionsInternal() : No keyboard for locale: " + mLocale);
                // If there is no keyboard for this locale, don't do any spell-checking.
                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
            }
            final WordComposer composer = new WordComposer();
            final int[] codePoints = StringUtils.toCodePointArray(text);
            final int[] coordinates;
            coordinates = keyboard.getCoordinates(codePoints);
            composer.setComposingWord(codePoints, coordinates);
            // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
            final SuggestionResults suggestionResults = mService.getSuggestionResults(mLocale, composer.getComposedDataSnapshot(), ngramContext, keyboard);
            final Result result = getResult(capitalizeType, mLocale, suggestionsLimit, mService.getRecommendedThreshold(), text, suggestionResults);
            if (DebugFlags.DEBUG_ENABLED) {
                if (result.mSuggestions != null && result.mSuggestions.length > 0) {
                    final StringBuilder builder = new StringBuilder();
                    for (String suggestion : result.mSuggestions) {
                        builder.append(" [");
                        builder.append(suggestion);
                        builder.append("]");
                    }
                    Log.i(TAG, "onGetSuggestionsInternal() : Suggestions =" + builder);
                }
            }
            // Handle word not in dictionary.
            // This is called only once per unique word, so entering multiple
            // instances of the same word does not result in more than one call
            // to this method.
            // Also, upon changing the orientation of the device, this is called
            // again for every unique invalid word in the text box.
            StatsUtils.onInvalidWordIdentification(text);
            final int flags = SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | (result.mHasRecommendedSuggestions ? SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0);
            final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
            mSuggestionsCache.putSuggestionsToCache(text, result.mSuggestions, flags);
            return retval;
        } catch (RuntimeException e) {
            // Don't kill the keyboard if there is a bug in the spell checker
            Log.e(TAG, "Exception while spellchecking", e);
            return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
        }
    }

    private static final clreplaced Result {

        public final String[] mSuggestions;

        public final boolean mHasRecommendedSuggestions;

        public Result(final String[] gatheredSuggestions, final boolean hasRecommendedSuggestions) {
            mSuggestions = gatheredSuggestions;
            mHasRecommendedSuggestions = hasRecommendedSuggestions;
        }
    }

    private static Result getResult(final int capitalizeType, final Locale locale, final int suggestionsLimit, final float recommendedThreshold, final String originalText, final SuggestionResults suggestionResults) {
        if (suggestionResults.isEmpty() || suggestionsLimit <= 0) {
            return new Result(null, /* gatheredSuggestions */
            false);
        }
        final ArrayList<String> suggestions = new ArrayList<>();
        for (final SuggestedWordInfo suggestedWordInfo : suggestionResults) {
            final String suggestion;
            if (StringUtils.CAPITALIZE_ALL == capitalizeType) {
                suggestion = suggestedWordInfo.mWord.toUpperCase(locale);
            } else if (StringUtils.CAPITALIZE_FIRST == capitalizeType) {
                suggestion = StringUtils.capitalizeFirstCodePoint(suggestedWordInfo.mWord, locale);
            } else {
                suggestion = suggestedWordInfo.mWord;
            }
            suggestions.add(suggestion);
        }
        StringUtils.removeDupes(suggestions);
        // This returns a String[], while toArray() returns an Object[] which cannot be cast
        // into a String[].
        final List<String> gatheredSuggestionsList = suggestions.subList(0, Math.min(suggestions.size(), suggestionsLimit));
        final String[] gatheredSuggestions = gatheredSuggestionsList.toArray(new String[gatheredSuggestionsList.size()]);
        final int bestScore = suggestionResults.first().mScore;
        final String bestSuggestion = suggestions.get(0);
        final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(originalText, bestSuggestion, bestScore);
        final boolean hasRecommendedSuggestions = (normalizedScore > recommendedThreshold);
        return new Result(gatheredSuggestions, hasRecommendedSuggestions);
    }

    /*
     * The spell checker acts on its own behalf. That is needed, in particular, to be able to
     * access the dictionary files, which the provider restricts to the idenreplacedy of Latin IME.
     * Since it's called externally by the application, the spell checker is using the idenreplacedy
     * of the application by default unless we clearCallingIdenreplacedy.
     * That's what the following method does.
     */
    @Override
    public SuggestionsInfo onGetSuggestions(final TextInfo textInfo, final int suggestionsLimit) {
        long ident = Binder.clearCallingIdenreplacedy();
        try {
            return onGetSuggestionsInternal(textInfo, suggestionsLimit);
        } finally {
            Binder.restoreCallingIdenreplacedy(ident);
        }
    }
}

18 Source : MediaContentObserver.java
with GNU General Public License v3.0
from bcmapp

public clreplaced MediaContentObserver {

    private ContentObserver mInternalObserver;

    private ContentObserver mExternalObserver;

    private MediaContentChangeListener listener;

    private Context context;

    public MediaContentObserver(Context context, Handler handler) {
        this.context = context;
        mInternalObserver = new ContentObserver(handler) {

            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                if (listener != null) {
                    listener.onMediaContentChange(MediaStore.Images.Media.INTERNAL_CONTENT_URI);
                }
            }
        };
        mExternalObserver = new ContentObserver(handler) {

            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                if (listener != null) {
                    listener.onMediaContentChange(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                }
            }
        };
    }

    public void setChangeListener(MediaContentChangeListener listener) {
        this.listener = listener;
        if (context != null) {
            context.getContentResolver().registerContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true, mInternalObserver);
            context.getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, mExternalObserver);
        }
    }

    public void removeChangeListener() {
        this.listener = null;
        context.getContentResolver().unregisterContentObserver(mInternalObserver);
        context.getContentResolver().unregisterContentObserver(mExternalObserver);
        context = null;
    }

    interface MediaContentChangeListener {

        void onMediaContentChange(Uri uri);
    }
}

18 Source : InMemoryCursor.java
with Apache License 2.0
from androidx

@Override
public void registerContentObserver(ContentObserver observer) {
    mObserverRelay.registerContentObserver(observer);
}

18 Source : InMemoryCursor.java
with Apache License 2.0
from androidx

@Override
public void unregisterContentObserver(ContentObserver observer) {
    mObserverRelay.unregisterContentObserver(observer);
}

18 Source : MultiUriCursorWrapper.java
with GNU General Public License v3.0
from AndreAle94

@Override
public void unregisterContentObserver(ContentObserver observer) {
    // cursor will unregister all observers when it close
    if (!mClosed) {
        mContentObservable.unregisterObserver(observer);
    }
}

18 Source : SyncManager.java
with Apache License 2.0
from alperali

/**
 * This clreplaced manages message sync with the Telephony SmsProvider/MmsProvider.
 */
public clreplaced SyncManager {

    private static final String TAG = LogUtil.BUGLE_TAG;

    /**
     * Record of any user customization to conversation settings
     */
    public static clreplaced ConversationCustomization {

        private final boolean mArchived;

        private final boolean mMuted;

        private final boolean mNoVibrate;

        private final String mNotificationSoundUri;

        public ConversationCustomization(final boolean archived, final boolean muted, final boolean noVibrate, final String notificationSoundUri) {
            mArchived = archived;
            mMuted = muted;
            mNoVibrate = noVibrate;
            mNotificationSoundUri = notificationSoundUri;
        }

        public boolean isArchived() {
            return mArchived;
        }

        public boolean isMuted() {
            return mMuted;
        }

        public boolean noVibrate() {
            return mNoVibrate;
        }

        public String getNotificationSoundUri() {
            return mNotificationSoundUri;
        }
    }

    SyncManager() {
    }

    /**
     * Timestamp of in progress sync - used to keep track of whether sync is running
     */
    private long mSyncInProgressTimestamp = -1;

    /**
     * Timestamp of current sync batch upper bound - used to determine if message makes batch dirty
     */
    private long mCurrentUpperBoundTimestamp = -1;

    /**
     * Timestamp of messages inserted since sync batch started - used to determine if batch dirty
     */
    private long mMaxRecentChangeTimestamp = -1L;

    private final ThreadInfoCache mThreadInfoCache = new ThreadInfoCache();

    /**
     * User customization to conversations. If this is set, we need to recover them after
     * a full sync.
     */
    private LongSparseArray<ConversationCustomization> mCustomization = null;

    /**
     * Start an incremental sync (backed off a few seconds)
     */
    public static void sync() {
        SyncMessagesAction.sync();
    }

    /**
     * Start an incremental sync (with no backoff)
     */
    public static void immediateSync() {
        SyncMessagesAction.immediateSync();
    }

    /**
     * Start a full sync (for debugging)
     */
    public static void forceSync() {
        SyncMessagesAction.fullSync();
    }

    /**
     * Called from data model thread when starting a sync batch
     * @param upperBoundTimestamp upper bound timestamp for sync batch
     */
    public synchronized void startSyncBatch(final long upperBoundTimestamp) {
        replacedert.isTrue(mCurrentUpperBoundTimestamp < 0);
        mCurrentUpperBoundTimestamp = upperBoundTimestamp;
        mMaxRecentChangeTimestamp = -1L;
    }

    /**
     * Called from data model thread at end of batch to determine if any messages added in window
     * @param lowerBoundTimestamp lower bound timestamp for sync batch
     * @return true if message added within window from lower to upper bound timestamp of batch
     */
    public synchronized boolean isBatchDirty(final long lowerBoundTimestamp) {
        replacedert.isTrue(mCurrentUpperBoundTimestamp >= 0);
        final long max = mMaxRecentChangeTimestamp;
        final boolean dirty = (max >= 0 && max >= lowerBoundTimestamp);
        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
            LogUtil.d(TAG, "SyncManager: Sync batch of messages from " + lowerBoundTimestamp + " to " + mCurrentUpperBoundTimestamp + " is " + (dirty ? "DIRTY" : "clean") + "; max change timestamp = " + mMaxRecentChangeTimestamp);
        }
        mCurrentUpperBoundTimestamp = -1L;
        mMaxRecentChangeTimestamp = -1L;
        return dirty;
    }

    /**
     * Called from data model or background worker thread to indicate start of message add process
     * (add must complete on that thread before action transitions to new thread/stage)
     * @param timestamp timestamp of message being added
     */
    public synchronized void onNewMessageInserted(final long timestamp) {
        if (mCurrentUpperBoundTimestamp >= 0 && timestamp <= mCurrentUpperBoundTimestamp) {
            // Message insert in current sync window
            mMaxRecentChangeTimestamp = Math.max(mCurrentUpperBoundTimestamp, timestamp);
            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
                LogUtil.d(TAG, "SyncManager: New message @ " + timestamp + " before upper bound of " + "current sync batch " + mCurrentUpperBoundTimestamp);
            }
        } else if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
            LogUtil.d(TAG, "SyncManager: New message @ " + timestamp + " after upper bound of " + "current sync batch " + mCurrentUpperBoundTimestamp);
        }
    }

    /**
     * Synchronously checks whether sync is allowed and starts sync if allowed
     * @param full - true indicates a full (not incremental) sync operation
     * @param startTimestamp - starttimestamp for this sync (if allowed)
     * @return - true if sync should start
     */
    public synchronized boolean shouldSync(final boolean full, final long startTimestamp) {
        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
            LogUtil.v(TAG, "SyncManager: Checking shouldSync " + (full ? "full " : "") + "at " + startTimestamp);
        }
        if (full) {
            final long delayUntilFullSync = delayUntilFullSync(startTimestamp);
            if (delayUntilFullSync > 0) {
                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
                    LogUtil.d(TAG, "SyncManager: Full sync requested for " + startTimestamp + " delayed for " + delayUntilFullSync + " ms");
                }
                return false;
            }
        }
        if (isSyncing()) {
            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
                LogUtil.d(TAG, "SyncManager: Not allowed to " + (full ? "full " : "") + "sync yet; still running sync started at " + mSyncInProgressTimestamp);
            }
            return false;
        }
        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
            LogUtil.d(TAG, "SyncManager: Starting " + (full ? "full " : "") + "sync at " + startTimestamp);
        }
        mSyncInProgressTimestamp = startTimestamp;
        return true;
    }

    /**
     * Return delay (in ms) until allowed to run a full sync (0 meaning can run immediately)
     * @param startTimestamp Timestamp used to start the sync
     * @return 0 if allowed to run now, else delay in ms
     */
    public long delayUntilFullSync(final long startTimestamp) {
        final BugleGservices bugleGservices = BugleGservices.get();
        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
        final long lastFullSyncTime = prefs.getLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, -1L);
        final long smsFullSyncBackoffTimeMillis = bugleGservices.getLong(BugleGservicesKeys.SMS_FULL_SYNC_BACKOFF_TIME_MILLIS, BugleGservicesKeys.SMS_FULL_SYNC_BACKOFF_TIME_MILLIS_DEFAULT);
        final long noFullSyncBefore = (lastFullSyncTime < 0 ? startTimestamp : lastFullSyncTime + smsFullSyncBackoffTimeMillis);
        final long delayUntilFullSync = noFullSyncBefore - startTimestamp;
        if (delayUntilFullSync > 0) {
            return delayUntilFullSync;
        }
        return 0;
    }

    /**
     * Check if sync currently in progress (public for replacederts/logging).
     */
    public synchronized boolean isSyncing() {
        return (mSyncInProgressTimestamp >= 0);
    }

    /**
     * Check if sync batch should be in progress - compares upperBound with in memory value
     * @param upperBoundTimestamp - upperbound timestamp for sync batch
     * @return - true if timestamps match (otherwise batch is orphan from older process)
     */
    public synchronized boolean isSyncing(final long upperBoundTimestamp) {
        replacedert.isTrue(upperBoundTimestamp >= 0);
        return (upperBoundTimestamp == mCurrentUpperBoundTimestamp);
    }

    /**
     * Check if sync has completed for the first time.
     */
    public boolean getHasFirstSyncCompleted() {
        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
        return prefs.getLong(BuglePrefsKeys.LAST_SYNC_TIME, BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT) != BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT;
    }

    /**
     * Called once sync is complete
     */
    public synchronized void complete() {
        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
            LogUtil.d(TAG, "SyncManager: Sync started at " + mSyncInProgressTimestamp + " marked as complete");
        }
        mSyncInProgressTimestamp = -1L;
        // Conversation customization only used once
        mCustomization = null;
    }

    private final ContentObserver mMmsSmsObserver = new TelephonyMessagesObserver();

    private boolean mSyncOnChanges = false;

    private boolean mNotifyOnChanges = false;

    /**
     * Register content observer when necessary and kick off a catch up sync
     */
    public void updateSyncObserver(final Context context) {
        registerObserver(context);
        // Trigger an sms sync in case we missed and messages before registering this observer or
        // becoming the SMS provider.
        immediateSync();
    }

    private void registerObserver(final Context context) {
        if (!PhoneUtils.getDefault().isDefaultSmsApp()) {
            // Not default SMS app - need to actively monitor telephony but not notify
            mNotifyOnChanges = false;
            mSyncOnChanges = true;
        } else if (OsUtil.isSecondaryUser()) {
            // Secondary users default SMS app - need to actively monitor telephony and notify
            mNotifyOnChanges = true;
            mSyncOnChanges = true;
        } else {
            // Primary users default SMS app - don't monitor telephony (most changes from this app)
            mNotifyOnChanges = false;
            mSyncOnChanges = false;
            if (context.getPackageManager().hreplacedystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
                // This is default SMS app but on Auto platform, even default SMS app needs
                // to be notified of changes because Bluetooth makes changes to Sms database
                // (thru ContentProvider). Content Change notifications help the default SMS app
                // refresh display with changes, whenever Bluetooth changes data in SMS db.
                mNotifyOnChanges = true;
                mSyncOnChanges = false;
            }
        }
        if (mNotifyOnChanges || mSyncOnChanges) {
            context.getContentResolver().registerContentObserver(Telephony.MmsSms.CONTENT_URI, true, mMmsSmsObserver);
        } else {
            context.getContentResolver().unregisterContentObserver(mMmsSmsObserver);
        }
    }

    public synchronized void setCustomization(final LongSparseArray<ConversationCustomization> customization) {
        this.mCustomization = customization;
    }

    public synchronized ConversationCustomization getCustomizationForThread(final long threadId) {
        if (mCustomization != null) {
            return mCustomization.get(threadId);
        }
        return null;
    }

    public static void resetLastSyncTimestamps() {
        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
        prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, BuglePrefsKeys.LAST_FULL_SYNC_TIME_DEFAULT);
        prefs.putLong(BuglePrefsKeys.LAST_SYNC_TIME, BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT);
    }

    private clreplaced TelephonyMessagesObserver extends ContentObserver {

        public TelephonyMessagesObserver() {
            // Just run on default thread
            super(null);
        }

        // Implement the onChange(boolean) method to delegate the change notification to
        // the onChange(boolean, Uri) method to ensure correct operation on older versions
        // of the framework that did not have the onChange(boolean, Uri) method.
        @Override
        public void onChange(final boolean selfChange) {
            onChange(selfChange, null);
        }

        // Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument.
        @Override
        public void onChange(final boolean selfChange, final Uri uri) {
            // Handle change.
            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
                LogUtil.v(TAG, "SyncManager: Sms/Mms DB changed @" + System.currentTimeMillis() + " for " + (uri == null ? "<unk>" : uri.toString()) + " " + mSyncOnChanges + "/" + mNotifyOnChanges);
            }
            if (mSyncOnChanges) {
                // If sync is already running this will do nothing - but at end of each sync
                // action there is a check for recent messages that should catch new changes.
                SyncManager.immediateSync();
            }
            if (mNotifyOnChanges) {
            // TODO: Secondary users are not going to get notifications
            }
        }
    }

    public ThreadInfoCache getThreadInfoCache() {
        return mThreadInfoCache;
    }

    public static clreplaced ThreadInfoCache {

        // Cache of thread->conversationId map
        private final LongSparseArray<String> mThreadToConversationId = new LongSparseArray<String>();

        // Cache of thread->recipients map
        private final LongSparseArray<List<String>> mThreadToRecipients = new LongSparseArray<List<String>>();

        // Remember the conversation ids that need to be archived
        private final HashSet<String> mArchivedConversations = new HashSet<>();

        public synchronized void clear() {
            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
                LogUtil.d(TAG, "SyncManager: Cleared ThreadInfoCache");
            }
            mThreadToConversationId.clear();
            mThreadToRecipients.clear();
            mArchivedConversations.clear();
        }

        public synchronized boolean isArchived(final String conversationId) {
            return mArchivedConversations.contains(conversationId);
        }

        /**
         * Get or create a conversation based on the message's thread id
         *
         * @param threadId The message's thread
         * @param refSubId The subId used for normalizing phone numbers in the thread
         * @param customization The user setting customization to the conversation if any
         * @return The existing conversation id or new conversation id
         */
        public synchronized String getOrCreateConversation(final DatabaseWrapper db, final long threadId, int refSubId, final ConversationCustomization customization) {
            // This function has several components which need to be atomic.
            replacedert.isTrue(db.getDatabase().inTransaction());
            // If we already have this conversation ID in our local map, just return it
            String conversationId = mThreadToConversationId.get(threadId);
            if (conversationId != null) {
                return conversationId;
            }
            final List<String> recipients = getThreadRecipients(threadId);
            final ArrayList<ParticipantData> participants = BugleDatabaseOperations.getConversationParticipantsFromRecipients(recipients, refSubId);
            if (customization != null) {
                // There is user customization we need to recover
                conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId, customization.isArchived(), participants, customization.isMuted(), customization.noVibrate(), customization.getNotificationSoundUri());
                if (customization.isArchived()) {
                    mArchivedConversations.add(conversationId);
                }
            } else {
                conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId, false, /*archived*/
                participants, false, /*noNotification*/
                false, /*noVibrate*/
                null);
            }
            if (conversationId != null) {
                mThreadToConversationId.put(threadId, conversationId);
                return conversationId;
            }
            return null;
        }

        /**
         * Load the recipients of a thread from telephony provider. If we fail, use
         * a predefined unknown recipient. This should not return null.
         *
         * @param threadId
         */
        public synchronized List<String> getThreadRecipients(final long threadId) {
            List<String> recipients = mThreadToRecipients.get(threadId);
            if (recipients == null) {
                recipients = MmsUtils.getRecipientsByThread(threadId);
                if (recipients != null && recipients.size() > 0) {
                    mThreadToRecipients.put(threadId, recipients);
                }
            }
            if (recipients == null || recipients.isEmpty()) {
                LogUtil.w(TAG, "SyncManager : using unknown sender since thread " + threadId + " couldn't find any recipients.");
                // We want to try our best to load the messages,
                // so if recipient info is broken, try to fix it with unknown recipient
                recipients = Lists.newArrayList();
                recipients.add(ParticipantData.getUnknownSenderDestination());
            }
            return recipients;
        }
    }
}

17 Source : ReadSmsService.java
with Apache License 2.0
from xiong-it

/**
 * 短信验证码读取服务
 */
public clreplaced ReadSmsService extends Service {

    private static final String TAG = ReadSmsService.clreplaced.getSimpleName();

    // 接收到短信时的action
    private static final String SMS_RECEIVED_ACTION = Telephony.Sms.Intents.SMS_RECEIVED_ACTION;

    // API level>=23,可直接使用Telephony.Sms.Inbox.CONTENT_URI
    private static final String SMS_INBOX_URI = "content://sms/inbox";

    // API level>=23,可直接使用Telephony.Sms.CONTENT_URI
    private static final String SMS_URI = "content://sms";

    static final String[] PROJECTION = new String[] { Telephony.Sms._ID, Telephony.Sms.ADDRESS, Telephony.Sms.BODY, Telephony.Sms.DATE };

    public static final String EXTRAS_MESSAGER = "tech.michaelx.verifycode.ReadSmsService.EXTRAS_MESSAGER";

    public static final String EXTRAS_COFIG = "tech.michaelx.verifycode.ReadSmsService.EXTRAS_COFIG";

    public static final int RECEIVER_SMS_CODE_MSG = 0;

    public static final int OBSERVER_SMS_CODE_MSG = 1;

    private Messenger mMessenger;

    private CodeConfig mCodeConfig;

    /**
     * 读取未读短信,用以填写验证码
     */
    private ContentObserver mReadSmsObserver = new ContentObserver(new Handler()) {

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Cursor cursor = getContentResolver().query(Uri.parse(SMS_INBOX_URI), PROJECTION, Telephony.Sms.READ + "=?", new String[] { "0" }, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER);
            getSmsCodeFromObserver(cursor);
        }
    };

    /**
     * 短信广播接收者
     */
    private BroadcastReceiver mReadSmsCodeReceiver = new ReadSmsCodeReceiver();

    private clreplaced ReadSmsCodeReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {
                getSmsCodeFromReceiver(intent);
            }
        }
    }

    public ReadSmsService() {
        super();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            Bundle bundle = intent.getExtras();
            if (bundle == null) {
                Log.e("AutoInputAuthCode", "bundle = null");
            } else {
                register();
                mMessenger = bundle.getParcelable(EXTRAS_MESSAGER);
                mCodeConfig = bundle.getParcelable(EXTRAS_COFIG);
            }
        }
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unRegister();
    }

    /**
     * 包访问级别:提高性能
     * 从接收者中得到短信验证码
     *
     * @param intent
     */
    void getSmsCodeFromReceiver(Intent intent) {
        SmsMessage[] messages = null;
        if (Build.VERSION.SDK_INT >= 19) {
            messages = android.provider.Telephony.Sms.Intents.getMessagesFromIntent(intent);
            if (messages == null)
                return;
        } else {
            messages = getSmsUnder19(intent);
            if (messages == null)
                return;
        }
        if (messages.length > 0) {
            for (int i = 0; i < messages.length; i++) {
                SmsMessage sms = messages[i];
                String smsSender = sms.getOriginatingAddress();
                String smsBody = sms.getMessageBody();
                if (checkSmsSender(smsSender) && checkSmsBody(smsBody)) {
                    String smsCode = parseSmsBody(smsBody);
                    sendMsg2Register(OBSERVER_SMS_CODE_MSG, smsCode);
                    break;
                }
            }
        }
    }

    @Nullable
    private SmsMessage[] getSmsUnder19(Intent intent) {
        SmsMessage[] messages;
        Bundle bundle = intent.getExtras();
        // 相关链接:https://developer.android.com/reference/android/provider/Telephony.Sms.Intents.html#SMS_DELIVER_ACTION
        Object[] pdus = (Object[]) bundle.get("pdus");
        if ((pdus == null) || (pdus.length == 0)) {
            return null;
        }
        messages = new SmsMessage[pdus.length];
        for (int i = 0; i < pdus.length; i++) {
            messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
        }
        return messages;
    }

    /**
     * 包访问级别:提高性能
     * 从内容观察者得到短信验证码
     *
     * @param cursor
     */
    void getSmsCodeFromObserver(Cursor cursor) {
        if (cursor == null)
            return;
        while (cursor.moveToNext()) {
            String address = cursor.getString(cursor.getColumnIndex(Telephony.Sms.ADDRESS));
            String smsBody = cursor.getString(cursor.getColumnIndex(Telephony.Sms.BODY));
            if (checkSmsSender(address) && checkSmsBody(smsBody)) {
                String smsCode = parseSmsBody(smsBody);
                sendMsg2Register(RECEIVER_SMS_CODE_MSG, smsCode);
                break;
            }
        }
        closeCursor(cursor);
    }

    private void closeCursor(Cursor cursor) {
        if (cursor == null || cursor.isClosed())
            return;
        if (!cursor.isClosed()) {
            cursor.close();
        }
    }

    /**
     * @param smsBody
     * @return
     */
    private boolean checkSmsBody(String smsBody) {
        if (!TextUtils.isEmpty(mCodeConfig.getSmsBodyStart()) && !TextUtils.isEmpty(mCodeConfig.getSmsBodyContains())) {
            return smsBody.startsWith(mCodeConfig.getSmsBodyStart()) && smsBody.contains(mCodeConfig.getSmsBodyContains());
        } else if (!TextUtils.isEmpty(mCodeConfig.getSmsBodyStart())) {
            return smsBody.startsWith(mCodeConfig.getSmsBodyStart());
        } else if (!TextUtils.isEmpty(mCodeConfig.getSmsBodyContains())) {
            return smsBody.contains(mCodeConfig.getSmsBodyContains());
        } else {
            return true;
        }
    }

    /**
     * @param smsSender
     * @return
     */
    private boolean checkSmsSender(String smsSender) {
        if (mCodeConfig.getSmsFrom() != 0) {
            return smsSender.equals(String.valueOf(mCodeConfig.getSmsFrom()));
        }
        return smsSender.contains(String.valueOf(mCodeConfig.getSmsFromStart()));
    }

    /**
     * 注册广播接收者,内容观察者
     */
    private void register() {
        registerReceiver();
        registerObserver();
    }

    /**
     * 注册广播接收者
     */
    private void registerReceiver() {
        IntentFilter filter = new IntentFilter(SMS_RECEIVED_ACTION);
        filter.addAction(SMS_RECEIVED_ACTION);
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        registerReceiver(mReadSmsCodeReceiver, filter);
    }

    /**
     * 注册内容观察者
     */
    private void registerObserver() {
        getContentResolver().registerContentObserver(Uri.parse(SMS_URI), true, mReadSmsObserver);
    }

    /**
     * 注销广播接收者,内容观察者
     */
    private void unRegister() {
        unRegisterReceiver();
        unRegisterObserver();
    }

    /**
     * 注销广播接收者
     */
    private void unRegisterReceiver() {
        if (mReadSmsCodeReceiver == null)
            return;
        unregisterReceiver(mReadSmsCodeReceiver);
        mReadSmsCodeReceiver = null;
    }

    /**
     * 注销内容观察者
     */
    private void unRegisterObserver() {
        if (mReadSmsObserver == null)
            return;
        getContentResolver().unregisterContentObserver(mReadSmsObserver);
        mReadSmsObserver = null;
    }

    /**
     * 解析短信得到验证码
     *
     * @param smsBody
     * @return
     */
    private String parseSmsBody(String smsBody) {
        int len = mCodeConfig.getCodeLen();
        // 匹配规则为短信中的连续数字
        String regex = new String("(\\d{" + len + "})");
        String smsCode = "";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(smsBody);
        while (matcher.find()) {
            smsCode = matcher.group(0);
        }
        return smsCode;
    }

    /**
     * 发送消息到注册界面
     *
     * @param msgWhat
     * @param msgObj
     */
    private void sendMsg2Register(int msgWhat, String msgObj) {
        if (mMessenger != null) {
            Message msg = Message.obtain();
            msg.what = msgWhat;
            msg.obj = msgObj;
            try {
                mMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            } finally {
                stopSelf();
            }
        }
    }
}

17 Source : SettingsProviderTest.java
with Apache License 2.0
from RealMoMo

private void setSettingAndreplacedertSuccessfulChange(Runnable setCommand, final int type, final String name, final String value, final int userId) throws Exception {
    ContentResolver contentResolver = getContext().getContentResolver();
    final Uri settingUri = getBaseUriForType(type);
    final AtomicBoolean success = new AtomicBoolean();
    ContentObserver contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {

        public void onChange(boolean selfChange, Uri changeUri, int changeId) {
            Log.i(LOG_TAG, "onChange(" + selfChange + ", " + changeUri + ", " + changeId + ")");
            replacedertEquals("Wrong change Uri", changeUri, settingUri);
            replacedertEquals("Wrong user id", userId, changeId);
            String changeValue = getStringViaFrontEndApiSetting(type, name, userId);
            replacedertEquals("Wrong setting value", value, changeValue);
            success.set(true);
            synchronized (mLock) {
                mLock.notifyAll();
            }
        }
    };
    contentResolver.registerContentObserver(settingUri, false, contentObserver, userId);
    try {
        setCommand.run();
        final long startTimeMillis = SystemClock.uptimeMillis();
        synchronized (mLock) {
            if (success.get()) {
                return;
            }
            final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
            if (elapsedTimeMillis > WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) {
                fail("Could not change setting for " + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms");
            }
            final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS - elapsedTimeMillis;
            try {
                mLock.wait(remainingTimeMillis);
            } catch (InterruptedException ie) {
            /* ignore */
            }
        }
    } finally {
        contentResolver.unregisterContentObserver(contentObserver);
    }
}

17 Source : PluginProviderClient.java
with Apache License 2.0
from Qihoo360

/**
 * @deprecated
 */
public static void registerContentObserver(Context c, Uri uri, boolean notifyForDescendents, ContentObserver observer) {
    com.qihoo360.replugin.component.provider.PluginProviderClient.registerContentObserver(c, uri, notifyForDescendents, observer);
}

17 Source : PluginProviderClient.java
with Apache License 2.0
from Qihoo360

/**
 * @deprecated
 */
public static void notifyChange(Context c, Uri uri, ContentObserver observer) {
    com.qihoo360.replugin.component.provider.PluginProviderClient.notifyChange(c, uri, observer);
}

17 Source : PluginProviderClient.java
with Apache License 2.0
from Qihoo360

/**
 * @deprecated
 */
public static void notifyChange(Context c, Uri uri, ContentObserver observer, boolean b) {
    com.qihoo360.replugin.component.provider.PluginProviderClient.notifyChange(c, uri, observer, b);
}

17 Source : ApmProvider.java
with Apache License 2.0
from Qihoo360

private void notifyChange(Uri uri, ContentObserver observer) {
    try {
        getContext().getContentResolver().notifyChange(uri, observer);
    } catch (Exception e) {
        if (Env.DEBUG) {
            LogX.d(Env.TAG, "notifyChange ex : " + Log.getStackTraceString(e));
        }
    }
}

17 Source : HapticFeedbackController.java
with Apache License 2.0
from philliphsu

/**
 * A simple utility clreplaced to handle haptic feedback.
 */
public clreplaced HapticFeedbackController {

    private static final int VIBRATE_DELAY_MS = 125;

    private static final int VIBRATE_LENGTH_MS = 5;

    private static boolean checkGlobalSetting(Context context) {
        return Settings.System.getInt(context.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 1;
    }

    private final Context mContext;

    private final ContentObserver mContentObserver;

    private Vibrator mVibrator;

    private boolean mIsGloballyEnabled;

    private long mLastVibrate;

    public HapticFeedbackController(Context context) {
        mContext = context;
        mContentObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean selfChange) {
                mIsGloballyEnabled = checkGlobalSetting(mContext);
            }
        };
    }

    /**
     * Call to setup the controller.
     */
    public void start() {
        mVibrator = (Vibrator) mContext.getSystemService(Service.VIBRATOR_SERVICE);
        // Setup a listener for changes in haptic feedback settings
        mIsGloballyEnabled = checkGlobalSetting(mContext);
        Uri uri = Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED);
        mContext.getContentResolver().registerContentObserver(uri, false, mContentObserver);
    }

    /**
     * Call this when you don't need the controller anymore.
     */
    public void stop() {
        mVibrator = null;
        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
    }

    /**
     * Try to vibrate. To prevent this becoming a single continuous vibration, nothing will
     * happen if we have vibrated very recently.
     */
    public void tryVibrate() {
        if (mVibrator != null && mIsGloballyEnabled) {
            long now = SystemClock.uptimeMillis();
            // We want to try to vibrate each individual tick discretely.
            if (now - mLastVibrate >= VIBRATE_DELAY_MS) {
                mVibrator.vibrate(VIBRATE_LENGTH_MS);
                mLastVibrate = now;
            }
        }
    }
}

17 Source : ContentResolver.java
with Apache License 2.0
from oasisfeng

@RequiresApi(N)
public void notifyChange(Uri uri, ContentObserver observer, int flags) {
    throw new RuntimeException("Stub!");
}

17 Source : StickerPackPreviewViewModel.java
with GNU General Public License v3.0
from mollyim

final clreplaced StickerPackPreviewViewModel extends ViewModel {

    private final Application application;

    private final StickerPackPreviewRepository previewRepository;

    private final StickerManagementRepository managementRepository;

    private final MutableLiveData<Optional<StickerManifestResult>> stickerManifest;

    private final ContentObserver packObserver;

    private String packId;

    private String packKey;

    private StickerPackPreviewViewModel(@NonNull Application application, @NonNull StickerPackPreviewRepository previewRepository, @NonNull StickerManagementRepository managementRepository) {
        this.application = application;
        this.previewRepository = previewRepository;
        this.managementRepository = managementRepository;
        this.stickerManifest = new MutableLiveData<>();
        this.packObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean selfChange) {
                if (!TextUtils.isEmpty(packId) && !TextUtils.isEmpty(packKey)) {
                    previewRepository.getStickerManifest(packId, packKey, stickerManifest::postValue);
                }
            }
        };
        application.getContentResolver().registerContentObserver(DatabaseContentProviders.StickerPack.CONTENT_URI, true, packObserver);
    }

    LiveData<Optional<StickerManifestResult>> getStickerManifest(@NonNull String packId, @NonNull String packKey) {
        this.packId = packId;
        this.packKey = packKey;
        previewRepository.getStickerManifest(packId, packKey, stickerManifest::postValue);
        return stickerManifest;
    }

    void onInstallClicked() {
        managementRepository.installStickerPack(packId, packKey, true);
    }

    void onRemoveClicked() {
        managementRepository.uninstallStickerPack(packId, packKey);
    }

    @Override
    protected void onCleared() {
        application.getContentResolver().unregisterContentObserver(packObserver);
    }

    static clreplaced Factory extends ViewModelProvider.NewInstanceFactory {

        private final Application application;

        private final StickerPackPreviewRepository previewRepository;

        private final StickerManagementRepository managementRepository;

        Factory(@NonNull Application application, @NonNull StickerPackPreviewRepository previewRepository, @NonNull StickerManagementRepository managementRepository) {
            this.application = application;
            this.previewRepository = previewRepository;
            this.managementRepository = managementRepository;
        }

        @Override
        @NonNull
        public <T extends ViewModel> T create(@NonNull Clreplaced<T> modelClreplaced) {
            // noinspection ConstantConditions
            return modelClreplaced.cast(new StickerPackPreviewViewModel(application, previewRepository, managementRepository));
        }
    }
}

17 Source : StickerManagementViewModel.java
with GNU General Public License v3.0
from mollyim

final clreplaced StickerManagementViewModel extends ViewModel {

    private final Application application;

    private final StickerManagementRepository repository;

    private final MutableLiveData<PackResult> packs;

    private final ContentObserver observer;

    private StickerManagementViewModel(@NonNull Application application, @NonNull StickerManagementRepository repository) {
        this.application = application;
        this.repository = repository;
        this.packs = new MutableLiveData<>();
        this.observer = new ContentObserver(null) {

            @Override
            public void onChange(boolean selfChange) {
                repository.deleteOrphanedStickerPacks();
                repository.getStickerPacks(packs::postValue);
            }
        };
        application.getContentResolver().registerContentObserver(DatabaseContentProviders.StickerPack.CONTENT_URI, true, observer);
    }

    void init() {
        repository.deleteOrphanedStickerPacks();
        repository.fetchUnretrievedReferencePacks();
    }

    void onVisible() {
        repository.deleteOrphanedStickerPacks();
    }

    @NonNull
    LiveData<PackResult> getStickerPacks() {
        repository.getStickerPacks(packs::postValue);
        return packs;
    }

    void onStickerPackUninstallClicked(@NonNull String packId, @NonNull String packKey) {
        repository.uninstallStickerPack(packId, packKey);
    }

    void onStickerPackInstallClicked(@NonNull String packId, @NonNull String packKey) {
        repository.installStickerPack(packId, packKey, false);
    }

    void onOrderChanged(List<StickerPackRecord> packsInOrder) {
        repository.setPackOrder(packsInOrder);
    }

    @Override
    protected void onCleared() {
        application.getContentResolver().unregisterContentObserver(observer);
    }

    static clreplaced Factory extends ViewModelProvider.NewInstanceFactory {

        private final Application application;

        private final StickerManagementRepository repository;

        Factory(@NonNull Application application, @NonNull StickerManagementRepository repository) {
            this.application = application;
            this.repository = repository;
        }

        @Override
        @NonNull
        public <T extends ViewModel> T create(@NonNull Clreplaced<T> modelClreplaced) {
            // noinspection ConstantConditions
            return modelClreplaced.cast(new StickerManagementViewModel(application, repository));
        }
    }
}

17 Source : ViewOnceMessageViewModel.java
with GNU General Public License v3.0
from mollyim

clreplaced ViewOnceMessageViewModel extends ViewModel {

    private static final String TAG = Log.tag(ViewOnceMessageViewModel.clreplaced);

    private final Application application;

    private final ViewOnceMessageRepository repository;

    private final MutableLiveData<Optional<MmsMessageRecord>> message;

    private final ContentObserver observer;

    private ViewOnceMessageViewModel(@NonNull Application application, long messageId, @NonNull ViewOnceMessageRepository repository) {
        this.application = application;
        this.repository = repository;
        this.message = new MutableLiveData<>();
        this.observer = new ContentObserver(null) {

            @Override
            public void onChange(boolean selfChange) {
                repository.getMessage(messageId, optionalMessage -> onMessageRetrieved(optionalMessage));
            }
        };
        repository.getMessage(messageId, message -> {
            if (message.isPresent()) {
                Uri uri = DatabaseContentProviders.Conversation.getUriForThread(message.get().getThreadId());
                application.getContentResolver().registerContentObserver(uri, true, observer);
            }
            onMessageRetrieved(message);
        });
    }

    @NonNull
    LiveData<Optional<MmsMessageRecord>> getMessage() {
        return message;
    }

    @Override
    protected void onCleared() {
        application.getContentResolver().unregisterContentObserver(observer);
    }

    private void onMessageRetrieved(@NonNull Optional<MmsMessageRecord> optionalMessage) {
        Util.runOnMain(() -> {
            MmsMessageRecord current = message.getValue() != null ? message.getValue().orNull() : null;
            MmsMessageRecord proposed = optionalMessage.orNull();
            if (current != null && proposed != null && current.getId() == proposed.getId()) {
                Log.d(TAG, "Same ID -- skipping update");
            } else {
                message.setValue(optionalMessage);
            }
        });
    }

    static clreplaced Factory extends ViewModelProvider.NewInstanceFactory {

        private final Application application;

        private final long messageId;

        private final ViewOnceMessageRepository repository;

        Factory(@NonNull Application application, long messageId, @NonNull ViewOnceMessageRepository repository) {
            this.application = application;
            this.messageId = messageId;
            this.repository = repository;
        }

        @Override
        @NonNull
        public <T extends ViewModel> T create(@NonNull Clreplaced<T> modelClreplaced) {
            // noinspection ConstantConditions
            return modelClreplaced.cast(new ViewOnceMessageViewModel(application, messageId, repository));
        }
    }
}

17 Source : MessageRecordLiveData.java
with GNU General Public License v3.0
from mollyim

final clreplaced MessageRecordLiveData extends LiveData<MessageRecord> {

    private final Context context;

    private final String type;

    private final Long messageId;

    private final ContentObserver obs;

    @Nullable
    private Cursor cursor;

    MessageRecordLiveData(Context context, String type, Long messageId) {
        this.context = context;
        this.type = type;
        this.messageId = messageId;
        obs = new ContentObserver(null) {

            @Override
            public void onChange(boolean selfChange) {
                SignalExecutors.BOUNDED.execute(() -> resetCursor());
            }
        };
    }

    @Override
    protected void onActive() {
        retrieveMessageRecord();
    }

    @Override
    protected void onInactive() {
        SignalExecutors.BOUNDED.execute(this::destroyCursor);
    }

    private void retrieveMessageRecord() {
        SignalExecutors.BOUNDED.execute(this::retrieveMessageRecordActual);
    }

    @WorkerThread
    private synchronized void destroyCursor() {
        if (cursor != null) {
            cursor.unregisterContentObserver(obs);
            cursor.close();
            cursor = null;
        }
    }

    @WorkerThread
    private synchronized void resetCursor() {
        destroyCursor();
        retrieveMessageRecord();
    }

    @WorkerThread
    private synchronized void retrieveMessageRecordActual() {
        if (cursor != null) {
            return;
        }
        switch(type) {
            case MmsSmsDatabase.SMS_TRANSPORT:
                handleSms();
                break;
            case MmsSmsDatabase.MMS_TRANSPORT:
                handleMms();
                break;
            default:
                throw new replacedertionError("no valid message type specified");
        }
    }

    @WorkerThread
    private synchronized void handleSms() {
        final MessageDatabase db = DatabaseFactory.getSmsDatabase(context);
        final Cursor cursor = db.getVerboseMessageCursor(messageId);
        final MessageRecord record = SmsDatabase.readerFor(cursor).getNext();
        postValue(record);
        cursor.registerContentObserver(obs);
        this.cursor = cursor;
    }

    @WorkerThread
    private synchronized void handleMms() {
        final MessageDatabase db = DatabaseFactory.getMmsDatabase(context);
        final Cursor cursor = db.getVerboseMessageCursor(messageId);
        final MessageRecord record = MmsDatabase.readerFor(cursor).getNext();
        postValue(record);
        cursor.registerContentObserver(obs);
        this.cursor = cursor;
    }
}

17 Source : CursorList.java
with GNU General Public License v3.0
from mollyim

@Override
public void unregisterContentObserver(@NonNull ContentObserver observer) {
    cursor.unregisterContentObserver(observer);
}

17 Source : CursorList.java
with GNU General Public License v3.0
from mollyim

@Override
public void registerContentObserver(@NonNull ContentObserver observer) {
    cursor.registerContentObserver(observer);
}

17 Source : HapticFeedbackController.java
with Apache License 2.0
from mohsenjahani

/**
 * A simple utility clreplaced to handle haptic feedback.
 */
public clreplaced HapticFeedbackController {

    private static final int VIBRATE_DELAY_MS = 125;

    private static final int VIBRATE_LENGTH_MS = 50;

    private static boolean checkGlobalSetting(Context context) {
        return Settings.System.getInt(context.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 1;
    }

    private final Context mContext;

    private final ContentObserver mContentObserver;

    private Vibrator mVibrator;

    private boolean mIsGloballyEnabled;

    private long mLastVibrate;

    public HapticFeedbackController(Context context) {
        mContext = context;
        mContentObserver = new ContentObserver(null) {

            @Override
            public void onChange(boolean selfChange) {
                mIsGloballyEnabled = checkGlobalSetting(mContext);
            }
        };
    }

    /**
     * Call to setup the controller.
     */
    public void start() {
        if (hasVibratePermission(mContext)) {
            mVibrator = (Vibrator) mContext.getSystemService(Service.VIBRATOR_SERVICE);
        }
        // Setup a listener for changes in haptic feedback settings
        mIsGloballyEnabled = checkGlobalSetting(mContext);
        Uri uri = Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED);
        mContext.getContentResolver().registerContentObserver(uri, false, mContentObserver);
    }

    /**
     * Method to verify that vibrate permission has been granted.
     *
     * Allows users of the library to disabled vibrate support if desired.
     * @return true if Vibrate permission has been granted
     */
    private boolean hasVibratePermission(Context context) {
        PackageManager pm = context.getPackageManager();
        int hasPerm = pm.checkPermission(android.Manifest.permission.VIBRATE, context.getPackageName());
        return hasPerm == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * Call this when you don't need the controller anymore.
     */
    public void stop() {
        mVibrator = null;
        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
    }

    /**
     * Try to vibrate. To prevent this becoming a single continuous vibration, nothing will
     * happen if we have vibrated very recently.
     */
    public void tryVibrate() {
        if (mVibrator != null && mIsGloballyEnabled) {
            long now = SystemClock.uptimeMillis();
            // We want to try to vibrate each individual tick discretely.
            if (now - mLastVibrate >= VIBRATE_DELAY_MS) {
                mVibrator.vibrate(VIBRATE_LENGTH_MS);
                mLastVibrate = now;
            }
        }
    }
}

See More Examples