Thursday, 21 June 2012

Helping you build beautiful, powerful, successful apps

[This post is by Billy Rutledge, Director of Developer Relations for Android. — Tim Bray]

Just in time for Google I/O next week, the Android Developers site is stepping into a new look that is streamlined, simplified, and refocused. A developer’s tasks fall into three baskets: Designing, developing, and distributing. We're trying to make developer.android.com's organization reflect this reality, shepherding you through the app development life cycle, from start to finish.

Design

Earlier this year, we launched Android Design, an online style guide which lays out the principles, building blocks, and patterns for excellence in Android user interfaces. It seems to be working; every day, we see more and more beautiful apps arriving in Google Play. At I/O, we’ll continue to talk design, kicking off with Android Design for Success, led by Matias Duarte.

Develop

An Android app should be fast, powerful and useful. With Android Training, one of the many parts of the Develop section that we continue to build out, we lay out best practices in a variety of framework topics to help you achieve those goals. If you’re at I/O and you’re interested in Android tools, be sure to start off your show with What’s new in Android Developers’ Tools.

Distribute

The most important piece of the piece of the puzzle is about getting your app in front of millions and millions of Android users on Google Play. That’s why we added a section on distributing your app — a peek into the world of publishing and promoting your app. Chris Yerga on the Play team will be kicking off our how-to sessions on distributing your with Android apps in Google Play.

This is just a small sample of the Android sessions at Google I/O, many of which will be live-streamed so you can follow along even if you can’t make it out to San Francisco. In the meantime, we hope you find the new Android Developer site much more useful as you build great apps.



Join the discussion on

+Android Developers



Sunday, 3 June 2012

Using DialogFragments

[This post is by David Chandler, Android Developer Advocate — Tim Bray]

Honeycomb introduced Fragments to support reusing portions of UI and logic across multiple activities in an app. In parallel, the showDialog / dismissDialog methods in Activity are being deprecated in favor of DialogFragments.



In this post, I’ll show how to use DialogFragments with the v4 support library (for backward compatibility on pre-Honeycomb devices) to show a simple edit dialog and return a result to the calling Activity using an interface.
For design guidelines around Dialogs, see the Android Design site.

The Layout

Here’s the layout for the dialog in a file named fragment_edit_name.xml.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/edit_name"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:orientation="vertical" >

<TextView
android:id="@+id/lbl_your_name" android:text="Your name"
android:layout_width="wrap_content" android:layout_height="wrap_content" />

<EditText
android:id="@+id/txt_your_name"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:inputType=”text”
android:imeOptions="actionDone" />
</LinearLayout>

Note the use of two optional attributes. In conjunction with android:inputType=”text”, android:imeOptions=”actionDone” configures the soft keyboard to show a Done key in place of the Enter key.

The Dialog Code

The dialog extends DialogFragment, and since we want backward compatibility, we’ll import it from the v4 support library. (To add the support library to an Eclipse project, right-click on the project and choose Android Tools | Add Support Library...).

import android.support.v4.app.DialogFragment;
// ...

public class EditNameDialog extends DialogFragment {

private EditText mEditText;

public EditNameDialog() {
// Empty constructor required for DialogFragment
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container);
mEditText = (EditText) view.findViewById(R.id.txt_your_name);
getDialog().setTitle("Hello");

return view;
}
}

The dialog extends DialogFragment and includes the required empty constructor. Fragments implement the onCreateView() method to actually load the view using the provided LayoutInflater.

Showing the Dialog

Now we need some code in our Activity to show the dialog. Here is a simple example that immediately shows the EditNameDialog to enter the user’s name. On completion, it shows a Toast with the entered text.

import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
// ...

public class FragmentDialogDemo extends FragmentActivity implements EditNameDialogListener {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showEditDialog();
}

private void showEditDialog() {
FragmentManager fm = getSupportFragmentManager();
EditNameDialog editNameDialog = new EditNameDialog();
editNameDialog.show(fm, "fragment_edit_name");
}

@Override
public void onFinishEditDialog(String inputText) {
Toast.makeText(this, "Hi, " + inputText, Toast.LENGTH_SHORT).show();
}
}

There are a few things to notice here. First, because we’re using the support library for backward compatibility with the Fragment API, our Activity extends FragmentActivity from the support library. Because we’re using the support library, we call getSupportFragmentManager() instead of getFragmentManager().

After loading the initial view, the activity immediately shows the EditNameDialog by calling its show() method. This allows the DialogFragment to ensure that what is happening with the Dialog and Fragment states remains consistent. By default, the back button will dismiss the dialog without any additional code.

Using the Dialog

Next, let’s enhance EditNameDialog so it can return a result string to the Activity.

import android.support.v4.app.DialogFragment;
// ...
public class EditNameDialog extends DialogFragment implements OnEditorActionListener {

public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}

private EditText mEditText;

public EditNameDialog() {
// Empty constructor required for DialogFragment
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container);
mEditText = (EditText) view.findViewById(R.id.txt_your_name);
getDialog().setTitle("Hello");

// Show soft keyboard automatically
mEditText.requestFocus();
getDialog().getWindow().setSoftInputMode(
LayoutParams.SOFT_INPUT_STATE_VISIBLE);
mEditText.setOnEditorActionListener(this);

return view;
}

@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (EditorInfo.IME_ACTION_DONE == actionId) {
// Return input text to activity
EditNameDialogListener activity = (EditNameDialogListener) getActivity();
activity.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();
return true;
}
return false;
}
}

For user convenience, we programmatically focus on the EditText with mEditText.requestFocus(). Alternatively, we could have used the <requestFocus/> tag in the layout XML to do this; however, in some cases it’s preferable to request focus programmatically. For example, an OnFocusChangeListener added in the Fragment’s onCreateView() method won’t get called if you request focus in the layout XML.

If the user focuses on an EditText, the soft keyboard will automatically appear. In order to force this to happen with our programmatic focus, we call getDialog().getWindow().setSoftInputMode(). Note that many Window operations you might have done previously in a Dialog can still be done in a DialogFragment, but you have to call getDialog().getWindow() instead of just getWindow(). The resulting dialog is shown on both a handset and tablet (not to scale):

The onEditorAction() method handles the callback when the user presses the Done key. It gets invoked because we’ve set an OnEditorActionListener on the EditText. It calls back to the Activity to send the entered text. To do this, EditNameDialog declares an interface EditNameDialogListener that is implemented by the Activity. This enables the dialog to be reused by many Activities. To invoke the callback method onFinishEditDialog(), it obtains a reference to the Activity which launched the dialog by calling getActivity(), which all Fragments provide, and then casts it to the interface type. In MVC architecture, this is a common pattern for allowing a view to communicate with a controller.

We can dismiss the dialog one of two ways. Here we are calling dismiss() within the Dialog class itself. It could also be called from the Activity like the show() method.

Hopefully this sheds some more light on Fragments as they relate to Dialogs. You can find the sample code in this blog post on Google Code.

References for learning more about Fragments:

Thursday, 24 May 2012

In-app Subscriptions in Google Play



[This post is by Ibrahim Elbouchikhi, Product Manager on the Google Play team. —Dirk Dougherty]



We launched In-app Billing on Google Play a year ago to give developers more ways to sell and engage users over the lifetime of their apps. Since the launch, In-app Billing has been extremely successful in helping developers monetize their apps through try-and-buy, virtual goods, upgrades, and other popular business models. Today, 23 of the 24 top-grossing apps in Google Play use In-app Billing, and the total revenue generated from in-app purchases exceeds revenue from traditional app purchases.



We’re now taking In-app Billing further by adding another important business model — subscriptions. Starting today, developers can use In-app Billing to sell monthly or annual subscriptions from inside of their apps. All subscriptions are auto-renewing, for every app and game and every type of subscription product. Developers just set the price and billing interval and Google Play manages the purchase transactions for them, just as it does for other in-app products and app purchases.



For users, Google Play provides a familiar and convenient purchase experience, highlighting subscription details such as price and billing interval before continuing with purchases. After the transaction, Google Play manages recurring billing and keeps users informed of new charges, sending them an email with each renewal. At any time, users can visit My Apps in the Play Store app to view their subscriptions and cancel any subscription as needed.





While making it easy for developers to offer a great purchasing experience, our subscriptions are also designed for flexibility. Developers can use them to monetize premium dynamic content such as journals and magazines, but they can also use them to sell access to bundled products, game levels, music and video content, value-added services, or any other digital content.



Building on Google Play’s strength as a truly cloud-connected experience, developers can offer users the ability to carry their subscriptions across multiple properties, services, or campaigns. To make this easier, we’re introducing an HTTP-based publisher API through which enterprise-scale backend servers can validate or cancel subscriptions. Using this API, for example, developers can extend access from their Android apps to their web properties, based on subscriptions that are purchased on Google Play.



In the coming days, several developers will be launching apps with Google Play subscriptions and we expect many more to follow. Glu Mobile is launching updated versions of its top Android titles, including Frontline Commando, offering subscriptions through custom VIP currency packages. "We're using Google Play subscriptions to offer consumers a compelling value and a single currency which they can use across Glu’s most popular titles” says Niccolo de Masi, CEO of Glu. “We're excited to bring these capabilities to our Android users and we believe that Google Play subscriptions will fuel further growth in our business."



If you’re a developer, you can get started with subscriptions right away by reading the In-app Billing documentation and downloading the updated sample app. If you are already using in-app billing, you’ll find that adding support for subscriptions is straightforward and involves only minor changes to your code.



You can publish your updated apps and subscription products as soon as you are ready. We’ve already rolled out client support to most Android devices worldwide, so any user with Google Play 3.5 or higher installed can buy subscriptions starting today.



We’re looking forward to seeing how you use subscriptions in your apps!



Join the discussion on

+Android Developers



Friday, 13 April 2012

Android C2DM — Client Login key expiration

[This post is by Francesco Nerieri, engineering team lead for C2DM — Tim Bray]

In the upcoming weeks, some of the older Client Login authentication keys will expire. If you generated the token you’re currently using to authenticate with the C2DM servers before October 2011, it will stop working.

If the response from the C2DM servers contains an Update-Client-Auth header, you’ll need to replace the current token with the one included in the header.

  // Check for updated token header
String updatedAuthToken = conn.getHeaderField(UPDATE_CLIENT_AUTH);
if (updatedAuthToken != null && !authToken.equals(updatedAuthToken)) {
log.info("Got updated auth token from datamessaging servers: " +
updatedAuthToken);
serverConfig.updateToken(updatedAuthToken);
}

We suggest that you start using the Update-Client-Auth response header to update tokens regularly, as keys will expire periodically from now on. For example, have a look at the Chrome to Phone service hosted on code.google.com; this code takes care of authenticating via Client Login and then sending a message:

Alternatively, you can manually generate a new Client Login token now and replace the one currently in use. ClientLogin can be used with any application that can make an HTTPS POST request. The POST request should be structured as a form post with the default encoding application/x-www-form-urlencoded, like this:

POST /accounts/ClientLogin HTTP/1.0
Content-type: application/x-www-form-urlencoded

accountType=GOOGLE&Email=johndoe@gmail.com&Passwd=north23AZ&service=ac2dm

If the POST succeeds, the response contains the authorization token, labeled "Auth", which is your new token. You could even do this from the command line:

curl -d \
"accountType=HOSTED_OR_GOOGLE&Email=johndoe@gmail.com&Passwd=north23AZ&service=ac2dm" \
https://www.google.com/accounts/ClientLogin | \
grep Auth

If your request fails or if you are prompted for captchas, please read ClientLogin for Installed Applications. And of course, if you updated your code to use the Update-Client-Auth header after the keys had expired, then you will first need to manually generate a new token.

Have fun with C2DM!

Followers