Phone to Chrome support

This commit is contained in:
burke.davey
2010-08-31 22:48:46 +00:00
parent 328e237e3e
commit 5f0b4693f2
8 changed files with 373 additions and 185 deletions

View File

@@ -12,8 +12,9 @@
<!-- Permissions for internet access and account access --> <!-- Permissions for internet access and account access -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- App must have this permission to use the library --> <!-- App must have this permission to use the library -->
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.USE_CREDENTIALS" />
@@ -31,14 +32,21 @@
<activity android:name=".HelpActivity" <activity android:name=".HelpActivity"
android:screenOrientation="portrait"> android:screenOrientation="portrait">
</activity> </activity>
<!-- In order to use the c2dm library, an <activity android:name=".ShareLinkActivity">
application must declare a class with the name C2DMReceiver, in its <intent-filter>
own package, extending com.google.android.c2dm.C2DMBaseReceiver <action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<!-- In order to use the c2dm library, an
application must declare a class with the name C2DMReceiver, in its
own package, extending com.google.android.c2dm.C2DMBaseReceiver
It must also include this section in the manifest, replacing It must also include this section in the manifest, replacing
"com.google.android.apps.chrometophone" with its package name. "com.google.android.apps.chrometophone" with its package name. -->
-->
<service android:name=".C2DMReceiver" /> <service android:name=".C2DMReceiver" />
<!-- Only google service can send data messages for the app. If permission is not set - <!-- Only google service can send data messages for the app. If permission is not set -

View File

@@ -77,6 +77,18 @@
<!-- Notification shown when text from the desktop is copied to Android's clipboard (user can now paste the text) [CHAR LIMIT=NONE] --> <!-- Notification shown when text from the desktop is copied to Android's clipboard (user can now paste the text) [CHAR LIMIT=NONE] -->
<string name="copied_desktop_clipboard">Copied desktop clipboard</string> <string name="copied_desktop_clipboard">Copied desktop clipboard</string>
<!-- Brief notification that appears when user sends link from phone to desktop [CHAR LIMIT=NONE] -->
<string name="sending_link_toast">Sending link...</string>
<!-- Brief notification that appears when user has sent link from phone to desktop [CHAR LIMIT=NONE] -->
<string name="link_sent_toast">Link sent</string>
<!-- Brief notification that appears when link cannot be sent from phone to desktop [CHAR LIMIT=NONE] -->
<string name="link_not_sent_toast">Link not sent</string>
<!-- Brief notification that appears when link cannot be sent from phone to desktop (because of auth issue) [CHAR LIMIT=NONE] -->
<string name="link_not_sent_auth_toast">Link not sent - authentication required</string>
<!-- Introduction text at start of setup flow. Preserve occurrences of &lt;br>, &lt;a href="{tos_link}">, &lt;a href="{pp_link}">, and &lt;a/> [CHAR LIMIT=NONE] --> <!-- Introduction text at start of setup flow. Preserve occurrences of &lt;br>, &lt;a href="{tos_link}">, &lt;a href="{pp_link}">, and &lt;a/> [CHAR LIMIT=NONE] -->
<string name="intro_text"> <string name="intro_text">
Chrome to Phone lets you easily share links, maps, and currently selected phone numbers and text Chrome to Phone lets you easily share links, maps, and currently selected phone numbers and text

View File

@@ -0,0 +1,155 @@
/*
* Copyright 2010 Google Inc.
*
* 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.google.android.apps.chrometophone;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.List;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* AppEngine client. Handles auth.
*/
public class AppEngineClient {
private static final String TAG = "AppEngineClient";
static final String BASE_URL = "https://chrometophone.appspot.com";
private static final String AUTH_URL = BASE_URL + "/_ah/login";
private static final String AUTH_TOKEN_TYPE = "ah";
private final Context mContext;
private final String mAccountName;
public AppEngineClient(Context context, String accountName) {
this.mContext = context;
this.mAccountName = accountName;
}
public HttpResponse makeRequest(String urlPath, List<NameValuePair> params) throws Exception {
HttpResponse res = makeRequestNoRetry(urlPath, params, false);
if (res.getStatusLine().getStatusCode() == 500) {
res = makeRequestNoRetry(urlPath, params, true);
}
return res;
}
private HttpResponse makeRequestNoRetry(String urlPath, List<NameValuePair> params, boolean newToken)
throws Exception {
// Get auth token for account
Account account = new Account(mAccountName, "com.google");
String authToken = getAuthToken(mContext, account);
if (authToken == null) throw new PendingAuthException(mAccountName);
if (newToken) { // invalidate the cached token
AccountManager accountManager = AccountManager.get(mContext);
accountManager.invalidateAuthToken(account.type, authToken);
authToken = getAuthToken(mContext, account);
}
// Get ACSID cookie
DefaultHttpClient client = new DefaultHttpClient();
String continueURL = BASE_URL;
URI uri = new URI(AUTH_URL + "?continue=" +
URLEncoder.encode(continueURL, "UTF-8") +
"&auth=" + authToken);
HttpGet method = new HttpGet(uri);
final HttpParams getParams = new BasicHttpParams();
HttpClientParams.setRedirecting(getParams, false); // continue is not used
method.setParams(getParams);
HttpResponse res = client.execute(method);
Header[] headers = res.getHeaders("Set-Cookie");
if (res.getStatusLine().getStatusCode() != 302 ||
headers.length == 0) {
return res;
}
String ascidCookie = null;
for (Header header: headers) {
if (header.getValue().indexOf("ACSID=") >=0) {
// let's parse it
String value = header.getValue();
String[] pairs = value.split(";");
ascidCookie = pairs[0];
}
}
// Make POST request
uri = new URI(BASE_URL + urlPath);
HttpPost post = new HttpPost(uri);
UrlEncodedFormEntity entity =
new UrlEncodedFormEntity(params, "UTF-8");
post.setEntity(entity);
post.setHeader("Cookie", ascidCookie);
post.setHeader("X-Same-Domain", "1"); // XSRF
res = client.execute(post);
return res;
}
private String getAuthToken(Context context, Account account) {
String authToken = null;
AccountManager accountManager = AccountManager.get(context);
try {
AccountManagerFuture<Bundle> future =
accountManager.getAuthToken (account, AUTH_TOKEN_TYPE, false, null, null);
Bundle bundle = future.getResult();
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
// User will be asked for "App Engine" permission.
if (authToken == null) {
// No auth token - will need to ask permission from user.
Intent intent = new Intent(MainActivity.AUTH_PERMISSION_ACTION);
intent.putExtra("AccountManagerBundle", bundle);
context.sendBroadcast(intent);
}
} catch (OperationCanceledException e) {
Log.w(TAG, e.getMessage());
} catch (AuthenticatorException e) {
Log.w(TAG, e.getMessage());
} catch (IOException e) {
Log.w(TAG, e.getMessage());
}
return authToken;
}
public class PendingAuthException extends Exception {
private static final long serialVersionUID = 1L;
public PendingAuthException(String message) {
super(message);
}
}
}

View File

@@ -15,7 +15,6 @@
*/ */
package com.google.android.apps.chrometophone; package com.google.android.apps.chrometophone;
import java.io.IOException; import java.io.IOException;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
@@ -76,7 +75,7 @@ public class C2DMReceiver extends C2DMBaseReceiver {
// turn this on for a small percentage of requests or for users // turn this on for a small percentage of requests or for users
// who report issues. // who report issues.
DefaultHttpClient client = new DefaultHttpClient(); DefaultHttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(DeviceRegistrar.BASE_URL + "/debug?id=" HttpGet get = new HttpGet(AppEngineClient.BASE_URL + "/debug?id="
+ extras.get("collapse_key")); + extras.get("collapse_key"));
// No auth - the purpose is only to generate a log/confirm delivery // No auth - the purpose is only to generate a log/confirm delivery
// (to avoid overhead of getting the token) // (to avoid overhead of getting the token)

View File

@@ -15,38 +15,20 @@
*/ */
package com.google.android.apps.chrometophone; package com.google.android.apps.chrometophone;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.http.Header;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log; import android.util.Log;
/** /**
* Register with the chrometophone appengine server. * Register/unregister with the Chrome to Phone App Engine server.
* Will pass the registration id and user, authenticating with app engine.
*/ */
public class DeviceRegistrar { public class DeviceRegistrar {
public static final String STATUS_EXTRA = "Status"; public static final String STATUS_EXTRA = "Status";
@@ -57,14 +39,9 @@ public class DeviceRegistrar {
private static final String TAG = "DeviceRegistrar"; private static final String TAG = "DeviceRegistrar";
static final String SENDER_ID = "stp.chrome@gmail.com"; static final String SENDER_ID = "stp.chrome@gmail.com";
static final String BASE_URL = "https://chrometophone.appspot.com";
// Appengine authentication private static final String REGISTER_PATH = "/register";
private static final String AUTH_URL = BASE_URL + "/_ah/login"; private static final String UNREGISTER_PATH = "/unregister";
private static final String AUTH_TOKEN_TYPE = "ah";
private static final String REGISTER_URL = BASE_URL + "/register";
private static final String UNREGISTER_URL = BASE_URL + "/unregister";
public static void registerWithServer(final Context context, public static void registerWithServer(final Context context,
final String deviceRegistrationID) { final String deviceRegistrationID) {
@@ -72,7 +49,7 @@ public class DeviceRegistrar {
public void run() { public void run() {
Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI"); Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI");
try { try {
HttpResponse res = makeRequest(context, deviceRegistrationID, REGISTER_URL); HttpResponse res = makeRequest(context, deviceRegistrationID, REGISTER_PATH);
if (res.getStatusLine().getStatusCode() == 200) { if (res.getStatusLine().getStatusCode() == 200) {
SharedPreferences settings = Prefs.get(context); SharedPreferences settings = Prefs.get(context);
SharedPreferences.Editor editor = settings.edit(); SharedPreferences.Editor editor = settings.edit();
@@ -87,7 +64,7 @@ public class DeviceRegistrar {
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS); updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
} }
context.sendBroadcast(updateUIIntent); context.sendBroadcast(updateUIIntent);
} catch (PendingAuthException e) { } catch (AppEngineClient.PendingAuthException pae) {
// Ignore - we'll reregister later // Ignore - we'll reregister later
} catch (Exception e) { } catch (Exception e) {
Log.w(TAG, "Registration error " + e.getMessage()); Log.w(TAG, "Registration error " + e.getMessage());
@@ -100,132 +77,41 @@ public class DeviceRegistrar {
public static void unregisterWithServer(final Context context, public static void unregisterWithServer(final Context context,
final String deviceRegistrationID) { final String deviceRegistrationID) {
Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI"); new Thread(new Runnable() {
try { public void run() {
HttpResponse res = makeRequest(context, deviceRegistrationID, UNREGISTER_URL); Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI");
if (res.getStatusLine().getStatusCode() == 200) { try {
SharedPreferences settings = Prefs.get(context); HttpResponse res = makeRequest(context, deviceRegistrationID, UNREGISTER_PATH);
SharedPreferences.Editor editor = settings.edit(); if (res.getStatusLine().getStatusCode() == 200) {
editor.remove("deviceRegistrationID"); SharedPreferences settings = Prefs.get(context);
editor.commit(); SharedPreferences.Editor editor = settings.edit();
updateUIIntent.putExtra(STATUS_EXTRA, UNREGISTERED_STATUS); editor.remove("deviceRegistrationID");
} else { editor.commit();
Log.w(TAG, "Unregistration error " + updateUIIntent.putExtra(STATUS_EXTRA, UNREGISTERED_STATUS);
String.valueOf(res.getStatusLine().getStatusCode())); } else {
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS); Log.w(TAG, "Unregistration error " +
} String.valueOf(res.getStatusLine().getStatusCode()));
} catch (Exception e) { updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS); }
Log.w(TAG, "Unegistration error " + e.getMessage()); } catch (Exception e) {
} updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
Log.w(TAG, "Unegistration error " + e.getMessage());
}
// Update dialog activity // Update dialog activity
context.sendBroadcast(updateUIIntent); context.sendBroadcast(updateUIIntent);
}
}).start();
} }
private static HttpResponse makeRequest(Context context, String deviceRegistrationID, private static HttpResponse makeRequest(Context context, String deviceRegistrationID,
String url) throws Exception { String urlPath) throws Exception {
HttpResponse res = makeRequestNoRetry(context, deviceRegistrationID, url,
false);
if (res.getStatusLine().getStatusCode() == 500) {
res = makeRequestNoRetry(context, deviceRegistrationID, url,
true);
}
return res;
}
private static HttpResponse makeRequestNoRetry(Context context, String deviceRegistrationID,
String url, boolean newToken) throws Exception {
// Get chosen user account
SharedPreferences settings = Prefs.get(context); SharedPreferences settings = Prefs.get(context);
String accountName = settings.getString("accountName", null); String accountName = settings.getString("accountName", null);
if (accountName == null) throw new Exception("No account"); List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("devregid", deviceRegistrationID));
// Get auth token for account AppEngineClient client = new AppEngineClient(context, accountName);
Account account = new Account(accountName, "com.google"); return client.makeRequest(urlPath, params);
String authToken = getAuthToken(context, account);
if (authToken == null) {
throw new PendingAuthException(accountName);
}
if (newToken) {
// Invalidate the cached token
AccountManager accountManager = AccountManager.get(context);
accountManager.invalidateAuthToken(account.type, authToken);
authToken = getAuthToken(context, account);
}
// Register device with server
DefaultHttpClient client = new DefaultHttpClient();
String continueURL = BASE_URL;
URI uri = new URI(AUTH_URL + "?continue=" +
URLEncoder.encode(continueURL, "UTF-8") +
"&auth=" + authToken);
HttpGet method = new HttpGet(uri);
// No redirect following - continue is not used
final HttpParams params = new BasicHttpParams();
HttpClientParams.setRedirecting(params, false);
method.setParams(params);
HttpResponse res = client.execute(method);
Header[] headers = res.getHeaders("Set-Cookie");
if (res.getStatusLine().getStatusCode() != 302 ||
headers.length == 0) {
return res;
}
String ascidCookie = null;
for (Header header: headers) {
if (header.getValue().indexOf("ACSID=") >=0) {
// let's parse it
String value = header.getValue();
String[] pairs = value.split(";");
ascidCookie = pairs[0];
}
}
uri = new URI(url);
HttpPost post = new HttpPost(uri);
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("devregid", deviceRegistrationID));
UrlEncodedFormEntity entity =
new UrlEncodedFormEntity(formparams, "UTF-8");
post.setEntity(entity);
post.setHeader("Cookie", ascidCookie);
post.setHeader("X-Same-Domain", "1"); // XSRF
res = client.execute(post);
return res;
}
private static String getAuthToken(Context context, Account account) {
String authToken = null;
AccountManager accountManager = AccountManager.get(context);
try {
AccountManagerFuture<Bundle> future =
accountManager.getAuthToken (account, AUTH_TOKEN_TYPE, false, null, null);
Bundle bundle = future.getResult();
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
// User will be asked for "App Engine" permission.
if (authToken == null) {
// No auth token - will need to ask permission from user.
Intent intent = new Intent(MainActivity.AUTH_PERMISSION_ACTION);
intent.putExtra("AccountManagerBundle", bundle);
context.sendBroadcast(intent);
}
} catch (OperationCanceledException e) {
Log.w(TAG, e.getMessage());
} catch (AuthenticatorException e) {
Log.w(TAG, e.getMessage());
} catch (IOException e) {
Log.w(TAG, e.getMessage());
}
return authToken;
}
static class PendingAuthException extends Exception {
private static final long serialVersionUID = 1L;
public PendingAuthException(String message) {
super(message);
}
} }
} }

View File

@@ -23,37 +23,38 @@ public class HelpActivity extends Activity {
} }
public static String getTOSLink() { public static String getTOSLink() {
String link = "http://m.google.com/toscountry"; // default return constructLink(Locale.getDefault(), "/tospage", "/toscountry");
String locale = Locale.getDefault().toString();
if (locale.equals(Locale.US.toString())) {
link = "http://m.google.com/tospage";
} else if (locale.equals(Locale.UK.toString())) {
link = "http://m.google.co.uk/tospage";
} else if (locale.equals(Locale.CANADA.toString())) {
link = "http://m.google.ca/tospage";
} else if (locale.equals(Locale.CANADA_FRENCH.toString())) {
link = "http://m.google.ca/tospage?hl=fr";
} else if (locale.equals(Locale.FRANCE.toString())) {
link = "http://m.google.fr/tospage";
}
return link;
} }
public static String getPPLink() { public static String getPPLink() {
String link = "http://m.google.com/privacy"; // default return constructLink(Locale.getDefault(), "/privacy", "/privacy");
}
String locale = Locale.getDefault().toString(); private static String constructLink(Locale locale, String path, String defaultPath) {
if (locale.toString().equals(Locale.US.toString())) { String link = "http://m.google.com" + defaultPath;
link = "http://m.google.com/privacy"; String localeString = locale.toString();
} else if (locale.toString().equals(Locale.UK.toString())) { if (localeString.equals(Locale.CANADA.toString())) {
link = "http://m.google.co.uk/privacy"; link = "http://m.google.ca" + path;
} else if (locale.toString().equals(Locale.CANADA.toString())) { } else if (localeString.equals(Locale.CANADA_FRENCH.toString())) {
link = "http://m.google.ca/privacy"; link = "http://m.google.ca" + path + "?hl=fr";
} else if (locale.toString().equals(Locale.CANADA_FRENCH.toString())) { } else if (localeString.equals(Locale.CHINA.toString())) {
link = "http://m.google.ca/privacy?hl=fr"; link = "http://m.google.cn" + path;
} else if (locale.toString().equals(Locale.FRANCE.toString())) { } else if (localeString.equals(Locale.FRANCE.toString())) {
link = "http://m.google.fr/privacy"; link = "http://m.google.fr" + path;
} else if (localeString.equals(Locale.GERMAN.toString())) {
link = "http://m.google.de" + path;
} else if (localeString.equals(Locale.ITALY.toString())) {
link = "http://m.google.it" + path;
} else if (localeString.equals(Locale.JAPAN.toString())) {
link = "http://m.google.co.jp" + path;
} else if (localeString.equals(Locale.KOREA.toString())) {
link = "http://m.google.co.kr" + path;
} else if (localeString.equals(Locale.TAIWAN.toString())) {
link = "http://m.google.tw" + path;
} else if (localeString.equals(Locale.UK.toString())) {
link = "http://m.google.co.uk" + path;
} else if (localeString.equals(Locale.US.toString())) {
link = "http://m.google.com" + path;
} }
return link; return link;
} }

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2010 Google Inc.
*
* 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.google.android.apps.chrometophone;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;
public class ShareLink implements Handler.Callback {
private static final String TOAST = "toast";
private static final String BROWSER_CHANNEL_PATH = "/browserchannel";
private static ShareLink mInstance;
private final Handler mHandler;
private final Context mContext;
private ShareLink(Context context) {
mContext = context;
mHandler = new Handler(this);
}
public static synchronized ShareLink getInstance(Context context) {
if (mInstance == null) {
mInstance = new ShareLink(context);
}
return mInstance;
}
public void send(final String link) {
new Thread(new Runnable() {
public void run() {
sendToast(mContext.getString(R.string.sending_link_toast));
try {
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("data", link));
SharedPreferences settings = Prefs.get(mContext);
final String accountName = settings.getString("accountName", null);
AppEngineClient client = new AppEngineClient(mContext, accountName);
HttpResponse res = client.makeRequest(BROWSER_CHANNEL_PATH, params);
if (res.getStatusLine().getStatusCode() == 200) {
sendToast(mContext.getString(R.string.link_sent_toast));
} else {
sendToast(mContext.getString(R.string.link_not_sent_toast));
}
} catch (AppEngineClient.PendingAuthException e) {
sendToast(mContext.getString(R.string.link_not_sent_auth_toast));
} catch (Exception e) {
sendToast(mContext.getString(R.string.link_not_sent_toast));
}
}
}).start();
}
private void sendToast(String toastMessage) {
Message msg = new Message();
Bundle data = new Bundle();
data.putString(TOAST, toastMessage);
msg.setData(data);
mHandler.sendMessage(msg);
}
public boolean handleMessage(Message msg) {
Toast.makeText(mContext, msg.getData().getString(TOAST), Toast.LENGTH_LONG).show();
return true;
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2010 Google Inc.
*
* 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.google.android.apps.chrometophone;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
/**
* Invoked when user selects "Share page" in the browser. Sends link
* to AppEngine server.
*/
public class ShareLinkActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Intent.ACTION_SEND.equals(getIntent().getAction())) {
String link = getIntent().getExtras().getString(Intent.EXTRA_TEXT);
ShareLink.getInstance(this).send(link);
}
finish();
}
}