blob: a0a95a24118c283f14be46f4ebe8b972fabbf1fd [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.documentsui.inspector;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.LocaleList;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextSelection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Checks if a TextView has a latitude and longitude. If so shows the default maps app to open
* those coordinates.
*
* Example - textView.setTextClassifier(new GpsCoordinatesTextClassifier(context, intent));
*/
final class GpsCoordinatesTextClassifier implements TextClassifier {
// Checks for latitude and longitude points, latitude ranges -90.0 to 90.0 and longitude
// ranges -180.0 to 180.0 Valid entries can be of the format "0,0", "0, 0" and "0.0, 0.0"
// in the mentioned range.
private static final String geoPattern
= "-?(90(\\.0*)?|[1-8]?[0-9](\\.[0-9]*)?), *-?(180("
+ "\\.0*)?|([1][0-7][0-9]|[0-9]?[0-9])(\\.[0-9]*)?)";
private static final Pattern sGeoPattern = Pattern.compile(geoPattern);
private final TextClassifier mSystemClassifier;
private final PackageManager mPackageManager;
public GpsCoordinatesTextClassifier(PackageManager pm, TextClassifier classifier) {
assert pm != null;
assert classifier != null;
mPackageManager = pm;
mSystemClassifier = classifier;
}
public static GpsCoordinatesTextClassifier create(Context context) {
return new GpsCoordinatesTextClassifier(
context.getPackageManager(),
context.getSystemService(TextClassificationManager.class).getTextClassifier());
}
// TODO: add support for local specific formatting
@Override
public TextClassification classifyText(
CharSequence text, int start, int end, LocaleList localeList) {
CharSequence sequence = text.subSequence(start, end);
if (isGeoSequence(sequence)) {
Intent intent = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(String.format("geo:0,0?q=%s", sequence)));
final ResolveInfo info = mPackageManager.resolveActivity(intent, 0);
if (info != null) {
return new TextClassification.Builder()
.setText(sequence.toString())
.setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
.setIcon(info.loadIcon(mPackageManager))
.setLabel(info.loadLabel(mPackageManager).toString())
.setIntent(intent)
.build();
}
}
// return default if text was not latitude, longitude or we couldn't find an application
// to handle the geo intent.
return mSystemClassifier.classifyText(text, start, end, localeList);
}
@Override
public TextSelection suggestSelection(
CharSequence context, int start, int end, LocaleList localeList) {
// Show map action menu popup when entire TextView is selected.
final int[] boundaries = {0, context.length()};
if (boundaries != null) {
return new TextSelection.Builder(boundaries[0], boundaries[1])
.setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
.build();
}
return mSystemClassifier.suggestSelection(context, start, end, localeList);
}
private static boolean isGeoSequence(CharSequence text) {
return sGeoPattern.matcher(text).matches();
}
}