Defer view intents for the browser until user present.

Fix target SDK so menu button appears always.
Add URL matching for YT; include https in regex.
This commit is contained in:
burke.davey
2012-06-15 04:22:33 +00:00
parent 8dba8e92f4
commit c105df2eab
6 changed files with 67 additions and 17 deletions

View File

@@ -4,5 +4,5 @@
<classpathentry kind="src" path="gen"/> <classpathentry kind="src" path="gen"/>
<classpathentry kind="src" path="c2dm"/> <classpathentry kind="src" path="c2dm"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin/classes"/>
</classpath> </classpath>

View File

@@ -2,8 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.apps.chrometophone" package="com.google.android.apps.chrometophone"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="12" android:versionCode="13"
android:versionName="2.3.0"> android:versionName="2.3.1">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="10" />
<!-- Only this application can receive the messages and registration result --> <!-- Only this application can receive the messages and registration result -->
<permission android:name="com.google.android.apps.chrometophone.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <permission android:name="com.google.android.apps.chrometophone.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.google.android.apps.chrometophone.permission.C2D_MESSAGE" /> <uses-permission android:name="com.google.android.apps.chrometophone.permission.C2D_MESSAGE" />
@@ -71,6 +73,11 @@
<category android:name="com.google.android.apps.chrometophone" /> <category android:name="com.google.android.apps.chrometophone" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".UserPresentReceiver" android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
</application> </application>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11" />
</manifest> </manifest>

View File

@@ -21,7 +21,6 @@ import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -86,12 +85,8 @@ public class C2DMReceiver extends C2DMBaseReceiver {
// Notify and optionally start activity // Notify and optionally start activity
if (settings.getBoolean("launchBrowserOrMaps", true) && launchIntent != null) { if (settings.getBoolean("launchBrowserOrMaps", true) && launchIntent != null) {
try { LauncherUtils.playNotificationSound(context);
context.startActivity(launchIntent); LauncherUtils.sendIntentToApp(context, launchIntent);
LauncherUtils.playNotificationSound(context);
} catch (ActivityNotFoundException e) {
return;
}
} else { } else {
LauncherUtils.generateNotification(context, url, title, launchIntent); LauncherUtils.generateNotification(context, url, title, launchIntent);
} }

View File

@@ -1,8 +1,14 @@
package com.google.android.apps.chrometophone; package com.google.android.apps.chrometophone;
import java.util.LinkedHashSet;
import java.util.Set;
import android.app.KeyguardManager;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -11,6 +17,7 @@ import android.media.AudioManager;
import android.media.Ringtone; import android.media.Ringtone;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.os.PowerManager;
import android.text.ClipboardManager; import android.text.ClipboardManager;
/** /**
@@ -19,6 +26,7 @@ import android.text.ClipboardManager;
public class LauncherUtils { public class LauncherUtils {
private static final String GMM_PACKAGE_NAME = "com.google.android.apps.maps"; private static final String GMM_PACKAGE_NAME = "com.google.android.apps.maps";
private static final String GMM_CLASS_NAME = "com.google.android.maps.MapsActivity"; private static final String GMM_CLASS_NAME = "com.google.android.maps.MapsActivity";
private static final String YT_PACKAGE_NAME = "com.google.android.youtube";
public static Intent getLaunchIntent(Context context, String title, String url, String sel) { public static Intent getLaunchIntent(Context context, String title, String url, String sel) {
Intent intent = null; Intent intent = null;
@@ -32,6 +40,8 @@ public class LauncherUtils {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isMapsURL(url)) { if (isMapsURL(url)) {
intent.setClassName(GMM_PACKAGE_NAME, GMM_CLASS_NAME); intent.setClassName(GMM_PACKAGE_NAME, GMM_CLASS_NAME);
} else if (isYouTubeURL(url)) {
intent.setPackage(YT_PACKAGE_NAME);
} }
// Fall back if we can't resolve intent (i.e. app missing) // Fall back if we can't resolve intent (i.e. app missing)
@@ -110,11 +120,49 @@ public class LauncherUtils {
} }
public static boolean isMapsURL(String url) { public static boolean isMapsURL(String url) {
return url.matches("http://maps\\.google\\.[a-z]{2,3}(\\.[a-z]{2})?[/?].*") || return url.matches("http[s]://maps\\.google\\.[a-z]{2,3}(\\.[a-z]{2})?[/?].*") ||
url.matches("http://www\\.google\\.[a-z]{2,3}(\\.[a-z]{2})?/maps.*"); url.matches("http[s]://www\\.google\\.[a-z]{2,3}(\\.[a-z]{2})?/maps.*");
} }
public static boolean isYouTubeURL(String url) { public static boolean isYouTubeURL(String url) {
return url.matches("http://www\\.youtube\\.[a-z]{2,3}(\\.[a-z]{2})?/.*"); return url.matches("http[s]://www\\.youtube\\.[a-z]{2,3}(\\.[a-z]{2})?/.*");
}
public static void sendIntentToApp(Context context, Intent intent) {
// Defer browser URLs until screen else the browser might drop the intent for security
// reasons. This is a little racey but in practice works fine.
if (isScreenOffOrLocked(context) &&
intent.getAction().equals(Intent.ACTION_VIEW) &&
(intent.getPackage() == null)) {
// Stuff away the intent URL
SharedPreferences prefs = Prefs.get(context);
SharedPreferences.Editor editor = prefs.edit();
Set<String> queuedUrls =
prefs.getStringSet("queuedUrls", new LinkedHashSet<String>());
queuedUrls.add(intent.getDataString());
editor.putStringSet("queuedUrls", queuedUrls);
editor.commit();
// Enable broadcast receiver for user present - it will pick up the stored intent URL
PackageManager pm = context.getPackageManager();
ComponentName componentName = new ComponentName(context, UserPresentReceiver.class);
pm.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
} else { // user present, so send immediately
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) { }
}
}
private static boolean isScreenOffOrLocked(Context context) {
KeyguardManager keyguardManager =
(KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
PowerManager powerManager =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
boolean off = !powerManager.isScreenOn();
off |= keyguardManager.inKeyguardRestrictedInputMode();
return off;
} }
} }

View File

@@ -3,6 +3,6 @@
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="c2dm"/> <classpathentry kind="src" path="c2dm"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER"/> <classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER/appengine-java-sdk-1.5.2"/>
<classpathentry kind="output" path="war/WEB-INF/classes"/> <classpathentry kind="output" path="war/WEB-INF/classes"/>
</classpath> </classpath>

View File

@@ -1,4 +1,4 @@
#Tue May 10 23:32:51 BST 2011 #Sun Aug 21 01:00:53 BST 2011
eclipse.preferences.version=1 eclipse.preferences.version=1
filesCopiedToWebInfLib=appengine-api-1.0-sdk-1.5.0.jar|appengine-api-labs-1.5.0.jar|appengine-jsr107cache-1.5.0.jar|jsr107cache-1.1.jar|datanucleus-appengine-1.0.8.final.jar|datanucleus-core-1.1.5.jar|datanucleus-jpa-1.1.5.jar|geronimo-jpa_3.0_spec-1.1.1.jar|geronimo-jta_1.1_spec-1.1.1.jar|jdo2-api-2.3-eb.jar filesCopiedToWebInfLib=appengine-api-1.0-sdk-1.5.2.jar|appengine-api-labs-1.5.2.jar|appengine-jsr107cache-1.5.2.jar|jsr107cache-1.1.jar|datanucleus-appengine-1.0.9.final.jar|datanucleus-core-1.1.5.jar|datanucleus-jpa-1.1.5.jar|geronimo-jpa_3.0_spec-1.1.1.jar|geronimo-jta_1.1_spec-1.1.1.jar|jdo2-api-2.3-eb.jar
ormEnhancementInclusions=src/**|c2dm/** ormEnhancementInclusions=src/**|c2dm/**