am 43341ba0: Merge "Ask the client to make itself known when it\'s not"
* commit '43341ba04298f9548e3ee6f37403eaf333dfa3bc': Ask the client to make itself known when it's notmain
commit
e40d563365
|
@ -95,6 +95,12 @@
|
|||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".DictionaryPackInstallBroadcastReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.inputmethod.dictionarypack.UNKNOWN_CLIENT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<provider android:name="com.android.inputmethod.dictionarypack.DictionaryProvider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false"
|
||||
|
|
|
@ -24,17 +24,35 @@ package com.android.inputmethod.dictionarypack;
|
|||
* is needed in particular to cleanly compile regression tests.
|
||||
*/
|
||||
public class DictionaryPackConstants {
|
||||
/**
|
||||
* The root domain for the dictionary pack, upon which authorities and actions will append
|
||||
* their own distinctive strings.
|
||||
*/
|
||||
private static final String DICTIONARY_DOMAIN = "com.android.inputmethod.dictionarypack";
|
||||
|
||||
/**
|
||||
* Authority for the ContentProvider protocol.
|
||||
*/
|
||||
// TODO: find some way to factorize this string with the one in the resources
|
||||
public static final String AUTHORITY = "com.android.inputmethod.dictionarypack.aosp";
|
||||
public static final String AUTHORITY = DICTIONARY_DOMAIN + ".aosp";
|
||||
|
||||
/**
|
||||
* The action of the intent for publishing that new dictionary data is available.
|
||||
*/
|
||||
// TODO: make this different across different packages. A suggested course of action is
|
||||
// to use the package name inside this string.
|
||||
public static final String NEW_DICTIONARY_INTENT_ACTION =
|
||||
"com.android.inputmethod.dictionarypack.newdict";
|
||||
// NOTE: The appended string should be uppercase like all other actions, but it's not for
|
||||
// historical reasons.
|
||||
public static final String NEW_DICTIONARY_INTENT_ACTION = DICTIONARY_DOMAIN + ".newdict";
|
||||
|
||||
/**
|
||||
* The action of the intent sent by the dictionary pack to ask for a client to make
|
||||
* itself known. This is used when the settings activity is brought up for a client the
|
||||
* dictionary pack does not know about.
|
||||
*/
|
||||
public static final String UNKNOWN_DICTIONARY_PROVIDER_CLIENT = DICTIONARY_DOMAIN
|
||||
+ ".UNKNOWN_CLIENT";
|
||||
// In the above intents, the name of the string extra that contains the name of the client
|
||||
// we want information about.
|
||||
public static final String DICTIONARY_PROVIDER_CLIENT_EXTRA = "client";
|
||||
}
|
||||
|
|
|
@ -509,6 +509,11 @@ public final class DictionaryProvider extends ContentProvider {
|
|||
} catch (final BadFormatException e) {
|
||||
Log.w(TAG, "Not enough information to insert this dictionary " + values, e);
|
||||
}
|
||||
// We just received new information about the list of dictionary for this client.
|
||||
// For all intents and purposes, this is new metadata, so we should publish it
|
||||
// so that any listeners (like the Settings interface for example) can update
|
||||
// themselves.
|
||||
UpdateHandler.publishUpdateMetadataCompleted(getContext(), true);
|
||||
break;
|
||||
case DICTIONARY_V1_WHOLE_LIST:
|
||||
case DICTIONARY_V1_DICT_INFO:
|
||||
|
|
|
@ -110,6 +110,15 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
|||
super.onResume();
|
||||
mChangedSettings = false;
|
||||
UpdateHandler.registerUpdateEventListener(this);
|
||||
final Activity activity = getActivity();
|
||||
if (!MetadataDbHelper.isClientKnown(activity, mClientId)) {
|
||||
Log.i(TAG, "Unknown dictionary pack client: " + mClientId + ". Requesting info.");
|
||||
final Intent unknownClientBroadcast =
|
||||
new Intent(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT);
|
||||
unknownClientBroadcast.putExtra(
|
||||
DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA, mClientId);
|
||||
activity.sendBroadcast(unknownClientBroadcast);
|
||||
}
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
getActivity().registerReceiver(mConnectivityChangedReceiver, filter);
|
||||
|
@ -363,8 +372,13 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
|||
getActivity(), android.R.anim.fade_out));
|
||||
preferenceView.startAnimation(AnimationUtils.loadAnimation(
|
||||
getActivity(), android.R.anim.fade_in));
|
||||
// The menu is created by the framework asynchronously after the activity,
|
||||
// which means it's possible to have the activity running but the menu not
|
||||
// created yet - hence the necessity for a null check here.
|
||||
if (null != mUpdateNowMenu) {
|
||||
mUpdateNowMenu.setTitle(R.string.check_for_updates_now);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,9 @@
|
|||
|
||||
package com.android.inputmethod.dictionarypack;
|
||||
|
||||
import com.android.inputmethod.latin.LatinIME;
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
public final class EventHandler extends BroadcastReceiver {
|
||||
private static final String TAG = EventHandler.class.getName();
|
||||
|
|
|
@ -444,7 +444,19 @@ public final class UpdateHandler {
|
|||
manager.remove(fileId);
|
||||
}
|
||||
|
||||
private static void publishUpdateMetadataCompleted(final Context context,
|
||||
/**
|
||||
* Sends a broadcast informing listeners that the dictionaries were updated.
|
||||
*
|
||||
* This will call all local listeners through the UpdateEventListener#downloadedMetadata
|
||||
* callback (for example, the dictionary provider interface uses this to stop the Loading
|
||||
* animation) and send a broadcast about the metadata having been updated. For a client of
|
||||
* the dictionary pack like Latin IME, this means it should re-query the dictionary pack
|
||||
* for any relevant new data.
|
||||
*
|
||||
* @param context the context, to send the broadcast.
|
||||
* @param downloadSuccessful whether the download of the metadata was successful or not.
|
||||
*/
|
||||
public static void publishUpdateMetadataCompleted(final Context context,
|
||||
final boolean downloadSuccessful) {
|
||||
// We need to warn all listeners of what happened. But some listeners may want to
|
||||
// remove themselves or re-register something in response. Hence we should take a
|
||||
|
|
|
@ -450,4 +450,25 @@ public final class BinaryDictionaryFileDumper {
|
|||
info.toContentValues());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a client record with the dictionary content provider.
|
||||
*
|
||||
* This merely acquires the content provider and calls
|
||||
* #reinitializeClientRecordInDictionaryContentProvider.
|
||||
*
|
||||
* @param context the context for resources and providers.
|
||||
* @param clientId the client ID to use.
|
||||
*/
|
||||
public static void initializeClientRecordHelper(final Context context,
|
||||
final String clientId) {
|
||||
try {
|
||||
final ContentProviderClient client = context.getContentResolver().
|
||||
acquireContentProviderClient(getProviderUriBuilder("").build());
|
||||
if (null == client) return;
|
||||
reinitializeClientRecordInDictionaryContentProvider(context, client, clientId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Cannot contact the dictionary content provider", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,14 +25,35 @@ import android.content.pm.PackageInfo;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Takes action to reload the necessary data when a dictionary pack was added/removed.
|
||||
* Receives broadcasts pertaining to dictionary management and takes the appropriate action.
|
||||
*
|
||||
* This object receives three types of broadcasts.
|
||||
* - Package installed/added. When a dictionary provider application is added or removed, we
|
||||
* need to query the dictionaries.
|
||||
* - New dictionary broadcast. The dictionary provider broadcasts new dictionary availability. When
|
||||
* this happens, we need to re-query the dictionaries.
|
||||
* - Unknown client. If the dictionary provider is in urgent need of data about some client that
|
||||
* it does not know, it sends this broadcast. When we receive this, we need to tell the dictionary
|
||||
* provider about ourselves. This happens when the settings for the dictionary pack are accessed,
|
||||
* but Latin IME never got a chance to register itself.
|
||||
*/
|
||||
public final class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = DictionaryPackInstallBroadcastReceiver.class.getSimpleName();
|
||||
|
||||
final LatinIME mService;
|
||||
|
||||
public DictionaryPackInstallBroadcastReceiver() {
|
||||
// This empty constructor is necessary for the system to instantiate this receiver.
|
||||
// This happens when the dictionary pack says it can't find a record for our client,
|
||||
// which happens when the dictionary pack settings are called before the keyboard
|
||||
// was ever started once.
|
||||
Log.i(TAG, "Latin IME dictionary broadcast receiver instantiated from the framework.");
|
||||
mService = null;
|
||||
}
|
||||
|
||||
public DictionaryPackInstallBroadcastReceiver(final LatinIME service) {
|
||||
mService = service;
|
||||
}
|
||||
|
@ -44,6 +65,11 @@ public final class DictionaryPackInstallBroadcastReceiver extends BroadcastRecei
|
|||
|
||||
// We need to reread the dictionary if a new dictionary package is installed.
|
||||
if (action.equals(Intent.ACTION_PACKAGE_ADDED)) {
|
||||
if (null == mService) {
|
||||
Log.e(TAG, "Called with intent " + action + " but we don't know the service: this "
|
||||
+ "should never happen");
|
||||
return;
|
||||
}
|
||||
final Uri packageUri = intent.getData();
|
||||
if (null == packageUri) return; // No package name : we can't do anything
|
||||
final String packageName = packageUri.getSchemeSpecificPart();
|
||||
|
@ -71,6 +97,11 @@ public final class DictionaryPackInstallBroadcastReceiver extends BroadcastRecei
|
|||
return;
|
||||
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
|
||||
&& !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
|
||||
if (null == mService) {
|
||||
Log.e(TAG, "Called with intent " + action + " but we don't know the service: this "
|
||||
+ "should never happen");
|
||||
return;
|
||||
}
|
||||
// When the dictionary package is removed, we need to reread dictionary (to use the
|
||||
// next-priority one, or stop using a dictionary at all if this was the only one,
|
||||
// since this is the user request).
|
||||
|
@ -82,7 +113,28 @@ public final class DictionaryPackInstallBroadcastReceiver extends BroadcastRecei
|
|||
// read dictionary from?
|
||||
mService.resetSuggestMainDict();
|
||||
} else if (action.equals(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)) {
|
||||
if (null == mService) {
|
||||
Log.e(TAG, "Called with intent " + action + " but we don't know the service: this "
|
||||
+ "should never happen");
|
||||
return;
|
||||
}
|
||||
mService.resetSuggestMainDict();
|
||||
} else if (action.equals(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT)) {
|
||||
if (null != mService) {
|
||||
// Careful! This is returning if the service is NOT null. This is because we
|
||||
// should come here instantiated by the framework in reaction to a broadcast of
|
||||
// the above action, so we should gave gone through the no-args constructor.
|
||||
Log.e(TAG, "Called with intent " + action + " but we have a reference to the "
|
||||
+ "service: this should never happen");
|
||||
return;
|
||||
}
|
||||
// The dictionary provider does not know about some client. We check that it's really
|
||||
// us that it needs to know about, and if it's the case, we register with the provider.
|
||||
final String wantedClientId =
|
||||
intent.getStringExtra(DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA);
|
||||
final String myClientId = context.getString(R.string.dictionary_pack_client_id);
|
||||
if (!wantedClientId.equals(myClientId)) return; // Not for us
|
||||
BinaryDictionaryFileDumper.initializeClientRecordHelper(context, myClientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue