• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.documentsui.inspector;
17 
18 import android.content.Context;
19 import android.content.Intent;
20 import android.content.pm.PackageManager;
21 import android.content.pm.ResolveInfo;
22 import android.net.Uri;
23 import android.os.LocaleList;
24 import android.view.textclassifier.TextClassification;
25 import android.view.textclassifier.TextClassificationManager;
26 import android.view.textclassifier.TextClassifier;
27 import android.view.textclassifier.TextSelection;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30 
31 /**
32  * Checks if a TextView has a latitude and longitude. If so shows the default maps app to open
33  * those coordinates.
34  *
35  * Example - textView.setTextClassifier(new GpsCoordinatesTextClassifier(context, intent));
36  */
37 final class GpsCoordinatesTextClassifier implements TextClassifier {
38 
39     // Checks for latitude and longitude points, latitude ranges -90.0 to 90.0 and longitude
40     // ranges -180.0 to 180.0 Valid entries can be of the format "0,0", "0, 0" and "0.0, 0.0"
41     // in the mentioned range.
42     private static final String geoPattern
43         = "-?(90(\\.0*)?|[1-8]?[0-9](\\.[0-9]*)?), *-?(180("
44         + "\\.0*)?|([1][0-7][0-9]|[0-9]?[0-9])(\\.[0-9]*)?)";
45     private static final Pattern sGeoPattern = Pattern.compile(geoPattern);
46 
47     private final TextClassifier mSystemClassifier;
48     private final PackageManager mPackageManager;
49 
GpsCoordinatesTextClassifier(PackageManager pm, TextClassifier classifier)50     public GpsCoordinatesTextClassifier(PackageManager pm, TextClassifier classifier) {
51         assert pm != null;
52         assert classifier != null;
53         mPackageManager = pm;
54         mSystemClassifier = classifier;
55     }
56 
create(Context context)57     public static GpsCoordinatesTextClassifier create(Context context) {
58         return new GpsCoordinatesTextClassifier(
59                 context.getPackageManager(),
60                 context.getSystemService(TextClassificationManager.class).getTextClassifier());
61     }
62 
63     // TODO: add support for local specific formatting
64     @Override
classifyText( CharSequence text, int start, int end, LocaleList localeList)65     public TextClassification classifyText(
66             CharSequence text, int start, int end, LocaleList localeList) {
67 
68         CharSequence sequence = text.subSequence(start, end);
69         if (isGeoSequence(sequence)) {
70 
71             Intent intent = new Intent(Intent.ACTION_VIEW)
72                 .setData(Uri.parse(String.format("geo:0,0?q=%s", sequence)));
73 
74             final ResolveInfo info = mPackageManager.resolveActivity(intent, 0);
75             if (info != null) {
76 
77                 return new TextClassification.Builder()
78                         .setText(sequence.toString())
79                         .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
80                         .setIcon(info.loadIcon(mPackageManager))
81                         .setLabel(info.loadLabel(mPackageManager).toString())
82                         .setIntent(intent)
83                         .build();
84             }
85         }
86 
87         // return default if text was not latitude, longitude or we couldn't find an application
88         // to handle the geo intent.
89         return mSystemClassifier.classifyText(text, start, end, localeList);
90     }
91 
92     @Override
suggestSelection( CharSequence context, int start, int end, LocaleList localeList)93     public TextSelection suggestSelection(
94         CharSequence context, int start, int end, LocaleList localeList) {
95 
96         // Show map action menu popup when entire TextView is selected.
97         final int[] boundaries = {0, context.length()};
98 
99         if (boundaries != null) {
100             return new TextSelection.Builder(boundaries[0], boundaries[1])
101                 .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
102                 .build();
103         }
104         return mSystemClassifier.suggestSelection(context, start, end, localeList);
105     }
106 
isGeoSequence(CharSequence text)107     private static boolean isGeoSequence(CharSequence text) {
108         return sGeoPattern.matcher(text).matches();
109     }
110 }
111