Feb 25

Infamous: Second Son release date revealed

Infamous: Second Son release date revealed

Infamous: Second SonThe release date of the Sony PlayStation 4 (PS4) exclusive, action-adventure video game developed by Sucker Punch ‘Infamous: Second Son’ has been revealed.  According to various sources and Polygon, the game is all set to launch in February 2014.  Along with the Infamous: Second son release date the company has also confirmed a few more features the gamers can expect of it.

The game that was announced at the PS4 unveiling event will take place in Seattle post seven years of the events that took place in the 2nd installment.  Players will also get to see a new protagonist in the form of Delsin Rowe who is a 24 year old with special abilities.

Just like the previous one, the upcoming game will also include an open world as well as a third person view.  A good news for players who have played the previous version is that, You will no longer need to press the L1 button to aim and fire as this version allows it in free motion along with a permanent reticle on screen.  New features such as these make the release date seem longer for those who have been following this superhit video game since the first title.  The game for now seems to be announced as PS4 exclusive, it will be interesting to see if a PlayStation 3 (PS3) version eventually comes out.

What are your thoughts of the Infamous: Second Son Release Date?

Gaming,Cricket,WWE and lots more

Feb 24

WWE Main Event 11/12/2013 – Results, Review and Analysis

WWE Main Event 11/12/2013 – Results, Review and Analysis

World Wrestling Entertainment’s Wednesday Night Pro Wrestling show kicked off with wrestlers such as Curtis Axel, Dolph Ziggler, Natalya, Alicia Fox, Xavier woods, R-Truth, Tons of Funk in action.  To know about what happened during the course of the show, read on for the complete results.

Note: Spoilers below.

Curtis Axel defeated Dolph Ziggler.

Natayla defeated Alicia Fox Via Submission

Xavier Woods and R-Truth defeated Tons of Funk.

What are your thoughts about the WWE Main Event 11/12/2013 Results?

Gaming,Cricket,WWE and lots more

Feb 24

All Google Play Developers Can Now Reply to User Reviews

Posted by Ellie Powers, Google Play team

There are a lot of great things a developer can do to promote their app, but the best way for your app to take off is when a really happy user tells their friend about your app, who tells their friend, who tells someone else — you get the picture.

That’s why it’s always been a priority for us to strengthen that conversation between developers and their users. Google Play is now connected with Google+, and by associating reviews with an identity, the quality of reviews has increased tremendously (in addition to letting users find reviews they trust).

We’re happy to announce today that all developers on Google Play can now reply to user reviews. You can reply to user reviews in the Google Play Developer Console, and your replies are shown publicly below the corresponding user review on Google Play. Users receive an email notification when you reply and can either reply to you directly by email, or update their review if they choose to do so — though keep in mind that users are not obligated to update their reviews. You can also update your reply at any time.

Developers who have been using this feature have told us that the following best practices are most effective in improving their apps and building strong relationships with their users:

  • Check reviews frequently, and involve people from all parts of your organization
  • Identify and prioritize bugs based on user impact
  • Let users know when their problems are resolved
  • Reply constructively to both negative and positive reviews
  • Refer users to documentation or other support channels
  • Get ideas about new improvements or features
  • Thank the users who are your biggest advocates

style="border:1px solid #ddd;border-radius: 6px;margin-top:1em;" src="http://4.bp.blogspot.com/-W7nmPciNlG0/UXgyKF6R8cI/AAAAAAAACGU/YNPDn9d2TZY/s1600/reply-reviews.png" />

Before replying to user reviews, it is important to review the posting guidelines to be sure that you are using this feature in compliance with Google Play’s policies at all times. The reply to each user’s review will be public, so prospective users will see if you provide consistently high quality customer support. Read the posting guidelines, and start connecting with users today.

Conversations are meant to be two-sided, and facilitating discussion between developers and users will ultimately yield better apps, to the benefit of everyone.

Join the discussion on

+Android Developers


Android Developers Blog

Feb 23

Keeping up to Date with the the Support Library

Posted by Agustin Fonts, Product Manager, Android Support Library


It’s important to keep current when you’re dealing with technology. That’s why we’re constantly working to improve the quality of our software, particularly libraries that are linked into your apps, such as the Support Library.  The Support Library is a suite of libraries that provides backward compatibility along with additional features across many Android releases.



We have just released version 25.2 of the Support Library.  If you’re making use of the android.support.v7.media.MediaRouter class in revision 25.1.1 or 25.1.0, we strongly recommend that you update due to a known issue.  If you haven’t updated recently, you’ve missed out on some great bug fixes such as these:



25.2:
  • Corrected a severe mediarouter issue in which using an A2DP Bluetooth device and media routing APIs could cause the device to become unresponsive, requiring a reboot
  • Showing a slide presentation with screen mirroring no longer causes the device to disconnect from Wi-Fi
  • Media button now properly handles media apps that did not register themselves with setMediaButtonReceiver()
  • TextInputLayout correctly overlays hint and text if text is set by XML (AOSP issue 230171)
  • Corrected a memory leak in MediaControllerCompat (AOSP issue 231441)
  • RecyclerView no longer crashes when recycling view holders (AOSP issue 225762)

Reporting (and fixing) a Bug

The Support Library is developed by the Android Framework and Developer Relations teams, and, just like the Android platform, you can file bugs using the AOSP issue tracker, or submit fixes to our Git repository. Your feedback is critical in helping us to make the Support Library the most productive environment to use for developing Android applications.


Android Developers Blog

Feb 23

How Google Cloud Messaging handles Doze in Android 6.0 Marshmallow

Posted by, Laurence Moroney, Developer Advocate

Android 6.0 Marshmallow introduces a new power saving feature called ‘Doze’. A device enters Doze when the user leaves it unplugged and stationary for a period of time and with the screen off. When this happens, the system defers application activity to save power. It will periodically and briefly resume normal operations, called an idle maintenance window, in order to perform app syncing and other pending operations.

If your app uses Google Cloud Messaging (GCM), you will need to take into account the following behaviors for users whose devices are in Doze.

GCM has two priority types for messages, called high priority and normal priority. When using high priority, GCM attempts to deliver messages immediately, waking a device in Doze, as needed. With Android Marshmallow, nothing changes here.

However, when using normal priority (the default priority), there are a number of different behaviors when the device is in Doze, including:

  • The most important change is that messages will be batched for devices in Doze. When the device enters its idle maintenance window, the batch of messages will be received.
  • We discard messages whose time_to_live expires while the device is in Doze (including TTL=0).

Despite this, it is recommended that, unless absolutely necessary, you keep your notifications as normal priority ones, as this will minimize battery impact. They will still sync during doze mode as described above, and of course once the device exits Doze.

High priority messages should only be used by applications that need to generate an immediate notification to the end user such as a chat app notification or an incoming phone call.

To learn more about Google Cloud Messaging message priorities, visit the Google Developers site.


Android Developers Blog

Feb 23

Publish your app with confidence from the Google Play Developer Console

Posted by Kobi Glick, Product Manager, Google Play

Publishing a new app, or app update, is an important and exciting milestone for
every developer. In order to make the process smoother and more trackable, we’re
announcing the launch of a new way to publish apps on Google Play with some new
features. The changes will give you the ability to manage your app releases with
more confidence via a new manage releases page in the Google Play Developer Console.


Manage your app updates with clarity and control

The new manage releases page is where you upload alpha, beta, and production
releases of your app. From here, you can see important information and the
status of all your releases across tracks.
The new manage releases page.
Easier access to existing and new publishing
features
Publishing an app or update is a big step, and one that every developer wants to
have confidence in taking. To help, we’ve added two new features.

First, we’ve added a validation step that highlights potential issues before you
publish. The new “review and rollout” page will appear before you confirm the
roll out of a new app and flag if there are validation errors or warnings. This
new flow will make the app release process easier, especially for apps using
multi-APK. It also provides new information; for example, in cases where you
added new permissions to your app, the system will highlight it.

Second, it’s now simpler to perform and track staged roll-outs during the
publishing flow. With staged rollouts, you can release your update to a growing
% of users, giving you a chance to catch and address any issues before affecting
your whole audience.

If you want to review the history of your releases, it is now possible to track
them granularly and download previous APKs.

Finally we’ve added a new artifacts library under manage releases where you can
find all the files that help you manage a release.

Start using the new manage releases page today
You can access the new manage releases page in the Developer Console. Visit the
Google
Play Developer Help Center for more information. With these changes, we’re
helping you to publish, track and manage your app with confidence on Google
Play.
How useful did you find this blogpost?
                                                                              


Android Developers Blog

Feb 23

New Tools to Take Your Games to the Next Level

In this mobile world, games aren’t just for the hardcore MMOG fan anymore, they’re for everyone; in fact, three out of four people with an Android phone or tablet play games. If you’re a game developer, Google has a host of tools available for you to help take your game to the next level, including Google Play game services, which let’s you leverage Google’s strength in mobile and cloud services so you can focus on building compelling game experiences for your users. Today, we’re adding more tools to your gaming toolbox, like the open sourcing of a 2D physics library, as well as new features to the Google Play game services offering, like a plug-in for Unity.

LiquidFun, a rigid-body physics library with fluid simulation

First, we are announcing the open-source release of LiquidFun, a new C++ 2D physics library that makes it easier for developers to add realistic physics to their games.

Based on Box2D, LiquidFun features particle-based fluid simulation. Game developers can use it for new game mechanics and add realistic physics to game play. Designers can use the library to create beautiful fluid interactive experiences.

The video clip below shows a circular body falling into a viscous fluid using LiquidFun.

The LiquidFun library is written in C++, so any platform that has a C++ compiler can benefit from it. To help with this, we have provided a method to build the LiquidFun library, example applications, and unit tests for Android, Linux, OSX and Windows.

We’re looking forward to seeing what you’ll do with LiquidFun and we want to hear from you about how we can make this even better! Download the latest release from our LiquidFun project page on GitHub and join our discussion list!

Google Play Games plug-in for Unity

If you are a game developer using Unity, the cross-platform game engine from Unity Technologies, you can now more easily integrate game services using a new Google Play Games plug-in for Unity. This initial version of the plug-in supports sign-in, achievements, leaderboards and cloud save on Android and iOS. You can download the plug-in from the Play Games project page on GitHub, along with documentation and sample code.

New categories for games in Google Play

New game categories are coming to the Play Store in February 2014, such as Simulation, Role Playing, and Educational! Developers can now use the Google Play Developer Console to choose a new category for their apps if the Application Type is “Games”. The New Category field in the Store Listing will set the future category for your game. This will not change the category of your game on Google Play until the new categories go live in February 2014.

Join the discussion on

+Android Developers


Android Developers Blog

Feb 22

Conference Data Sync and GCM in the Google I/O App

By Bruno Oliveira, tech lead of the 2014 Google I/O mobile app

Keeping data in sync with the cloud is an important part of many applications, and the Google I/O App is no exception. To do this, we leverage the standard Android mechanism for this purpose: a Sync Adapter. Using a Sync Adapter has many benefits over using a more rudimentary mechanism such as setting up recurring alarms, because the system automatically handles the scheduling of Sync Adapters to optimize battery life.

We store the data in a local SQLite database. However, rather than having the whole application access that database directly, the application employs another standard Android mechanism to control and organize access to that data. This structure is, naturally, a Content Provider. Only the content provider’s implementation has direct access to the SQLite database. All other parts of the app can only access data through the Content Resolver. This allows for a very flexible decoupling between the representation of the data in the database and the more abstract view of that data that is used throughout the app.

The I/O app maintains with two main kinds of data: conference data (sessions, speakers, rooms, etc) and user data (the user’s personalized schedule). Conference data is kept up to date with a one-way sync from a set of JSON files stored in Google Cloud Storage, whereas user data goes through a two-way sync with a file stored in the user’s Google Drive AppData folder.

Downloading Conference Data Efficiently

For a conference like Google I/O, conference data can be somewhat large. It consists of information about all the sessions, rooms, speakers, map locations, social hashtags, video library items and others. Downloading the whole data set repeatedly would be wasteful both in terms of battery and bandwidth, so we adopt a strategy to minimize the amount of data we download and process.

This strategy is separating the data into several different JSON files, and having them be referenced by a central master JSON file called the manifest file. The URL of the manifest file is the only URL that is hard-coded into the app (it is defined by the MANIFEST_URL constant in Config.java). Note that the I/O app uses Google Cloud Storage to store and serve these files, but any robust hosting service accessible via HTTP can be used for the same purpose.

The first part of the sync process is checking if the manifest file was changed since the app last downloaded it, and processing it only if it’s newer. This logic is implemented by the fetchConfenceDataIfNewer method in RemoteConferenceDataFetcher.

public class RemoteConferenceDataFetcher {
    // (...)
    public String[] fetchConferenceDataIfNewer(String refTimestamp) throws IOException {
        BasicHttpClient httpClient = new BasicHttpClient();
        httpClient.setRequestLogger(mQuietLogger);
        // (...)

        // Only download if data is newer than refTimestamp
        if (!TextUtils.isEmpty(refTimestamp) && TimeUtils
            .isValidFormatForIfModifiedSinceHeader(refTimestamp)) {
                httpClient.addHeader("If-Modified-Since", refTimestamp);
            }
        }

        HttpResponse response = httpClient.get(mManifestUrl, null);
        int status = response.getStatus();
        if (status == HttpURLConnection.HTTP_OK) {
            // Data modified since we last checked -- process it!
        } else if (status == HttpURLConnection.HTTP_NOT_MODIFIED) {
            // data on the server is not newer than our data - no work to do!
            return null;
        } else {
            // (handle error)
        }
    }
    // (...)
}

Notice that we submit the HTTP If-Modified-Since header with our request, so that if the manifest hasn’t changed since we last checked it, we will get an HTTP response code of HTTP_NOT_MODIFIED rather than HTTP_OK, we will react by skipping the download and parsing process. This means that unless the manifest has changed since we last saw it, the sync process is very economical: it consists only of a single HTTP request and a short response.

The manifest file’s format is straightforward: it consists of references to other JSON files that contain the relevant pieces of the conference data:

{
  "format": "iosched-json-v1",
  "data_files": [
    "past_io_videolibrary_v5.json",
    "experts_v11.json",
    "hashtags_v8.json",
    "blocks_v10.json",
    "map_v11.json",
    "keynote_v10.json",
    "partners_v2.json",
    "session_data_v2.681.json"
  ]
}

The sync process then proceeds to process each of the listed data files in order. This part is also implemented to be as economical as possible: if we detect that we already have a cached version of a specific data file, we skip it entirely and use our local cache instead. This task is done by the processManifest method.

Then, each JSON file is parsed and the entities present in each one are accumulated in memory. At the end of this process, the data is written to the Content Provider.

Issuing Content Provider Operations Efficiently

The conference data sync needs to be efficient not only in the amount of data it downloads, but also in the amount of operations it performs on the database. This must be done as economically as possible, so this step is also optimized: instead of overwriting the whole database with the new data, the Sync Adapter attempts to preserve the existing entities and only update the ones that have changed. In our tests, this optimization step reduced the total sync time from 16 seconds to around 2 seconds on our test devices.

In order to accomplish this important third layer of optimization, the application needs to know, given an entity in memory and its version in the Content Provider, whether or not we need to issue content provider operations to update that entity. Comparing the entity in memory to the entity in the database field by field is one option, but is cumbersome and slow, since it would require us to read every field. Instead, we add a field to each entity called the import hashcode. The import hashcode is a weak hash value generated from its data. For example, here is how the import hashcode for a speaker is computed:

public class Speaker {
    public String id;
    public String publicPlusId;
    public String bio;
    public String name;
    public String company;
    public String plusoneUrl;
    public String thumbnailUrl;

    public String getImportHashcode() {
        StringBuilder sb = new StringBuilder();
        sb.append("id").append(id == null ? "" : id)
                .append("publicPlusId")
                .append(publicPlusId == null ? "" : publicPlusId)
                .append("bio")
                .append(bio == null ? "" : bio)
                .append("name")
                .append(name == null ? "" : name)
                .append("company")
                .append(company== null ? "" : company)
                .append("plusoneUrl")
                .append(plusoneUrl == null ? "" : plusoneUrl)
                .append("thumbnailUrl")
                .append(thumbnailUrl == null ? "" : thumbnailUrl);
        String result = sb.toString();
        return String.format(Locale.US, "%08x%08x",
            result.hashCode(), result.length());
    }
}

Every time an entity is updated in the database, its import hashcode is saved with it as a database column. Later, when we have a candidate for an updated version of that entity, all we need to do is compute the import hashcode of the candidate and compare it to the import hashcode of the entity in the database. If they differ, then we issue Content Provider operations to update the entity in the database. If they are the same, we skip that entity. This incremental update logic can be seen, for example, in the makeContentProviderOperations method of the SpeakersHandler class:

public class SpeakersHandler extends JSONHandler {
    private HashMap mSpeakers = new HashMap();

    // (...)
    @Override
    public void makeContentProviderOperations(ArrayList list) {
        // (...)
        int updatedSpeakers = 0;
        for (Speaker speaker : mSpeakers.values()) {
            String hashCode = speaker.getImportHashcode();
            speakersToKeep.add(speaker.id);

            if (!isIncrementalUpdate || !speakerHashcodes.containsKey(speaker.id) ||
                    !speakerHashcodes.get(speaker.id).equals(hashCode)) {
                // speaker is new/updated, so issue content provider operations
                ++updatedSpeakers;
                boolean isNew = !isIncrementalUpdate ||
                    !speakerHashcodes.containsKey(speaker.id);
                buildSpeaker(isNew, speaker, list);
            }
        }

        // delete obsolete speakers
        int deletedSpeakers = 0;
        if (isIncrementalUpdate) {
            for (String speakerId : speakerHashcodes.keySet()) {
                if (!speakersToKeep.contains(speakerId)) {
                    buildDeleteOperation(speakerId, list);
                    ++deletedSpeakers;
                }
            }
        }
    }
}

The buildSpeaker and buildDeleteOperation methods (omitted here for brevity) simply build the Content Provider operations necessary to, respectively, insert/update a speaker or delete a speaker from the Content Provider. Notice that this approach means we only issue Content Provider operations to update a speaker if the import hashcode has changed. We also deal with obsolete speakers, that is, speakers that were in the database but were not referenced by the incoming data, and we issue delete operations for those speakers.

Making Sync Robust

The sync adapter in the I/O app is responsible for several tasks, amongst which are the remote conference data sync, the user schedule sync and also the user feedback sync. Failures can happen in any of them because of network conditions and other factors. However, a failure in one of the tasks should not impact the execution of the other tasks. This is why we structure the sync process as a series of independent tasks, each protected by a try/catch block, as can be seen in the performSync method of the SyncHelper class:

// remote sync consists of these operations, which we try one by one (and
// tolerate individual failures on each)
final int OP_REMOTE_SYNC = 0;
final int OP_USER_SCHEDULE_SYNC = 1;
final int OP_USER_FEEDBACK_SYNC = 2;

int[] opsToPerform = userDataOnly ?
        new int[] { OP_USER_SCHEDULE_SYNC } :
        new int[] { OP_REMOTE_SYNC, OP_USER_SCHEDULE_SYNC, OP_USER_FEEDBACK_SYNC};

for (int op : opsToPerform) {
    try {
        switch (op) {
            case OP_REMOTE_SYNC:
                dataChanged |= doRemoteSync();
                break;
            case OP_USER_SCHEDULE_SYNC:
                dataChanged |= doUserScheduleSync(account.name);
                break;
            case OP_USER_FEEDBACK_SYNC:
                doUserFeedbackSync();
                break;
        }
    } catch (AuthException ex) {
        // (... handle auth error...)
    } catch (Throwable throwable) {
        // (... handle other error...)

        // Let system know an exception happened:
        if (syncResult != null && syncResult.stats != null) {
            ++syncResult.stats.numIoExceptions;
        }
    }
}

When one particular part of the sync process fails, we let the system know about it by increasing syncResult.stats.numIoExceptions. This will cause the system to retry the sync at a later time, using exponential backoff.

When Should We Sync? Enter GCM.

It’s very important for users to be able to get updates about conference data in a timely manner, especially during (and in the few days leading up to) Google I/O. A naïve way to solve this problem is simply making the app poll the server repeatedly for updates. Naturally, this causes problems with bandwidth and battery consumption.

To solve this problem in a more elegant way, we use GCM (Google Cloud Messaging). Whenever there is an update to the data on the server side, the server sends a GCM message to all registered devices. Upon receipt of this GCM message, the device performs a sync to download the new conference data. The GCMIntentService class handles the incoming GCM messages:

public class GCMIntentService extends GCMBaseIntentService {
    private static final String TAG = makeLogTag("GCM");

    private static final Map MESSAGE_RECEIVERS;
    static {
        // Known messages and their GCM message receivers
        Map  receivers = new HashMap();
        receivers.put("test", new TestCommand());
        receivers.put("announcement", new AnnouncementCommand());
        receivers.put("sync_schedule", new SyncCommand());
        receivers.put("sync_user", new SyncUserCommand());
        receivers.put("notification", new NotificationCommand());
        MESSAGE_RECEIVERS = Collections.unmodifiableMap(receivers);
    }

    // (...)

    @Override
    protected void onMessage(Context context, Intent intent) {
        String action = intent.getStringExtra("action");
        String extraData = intent.getStringExtra("extraData");
        LOGD(TAG, "Got GCM message, action=" + action + ", extraData=" + extraData);

        if (action == null) {
            LOGE(TAG, "Message received without command action");
            return;
        }

        action = action.toLowerCase();
        GCMCommand command = MESSAGE_RECEIVERS.get(action);
        if (command == null) {
            LOGE(TAG, "Unknown command received: " + action);
        } else {
            command.execute(this, action, extraData);
        }

    }
    // (...)
}

Notice that the onMessage method delivers the message to the appropriate handler depending on the GCM message’s “action” field. If the action field is “sync_schedule”, the application delivers the message to an instance of the SyncCommand class, which causes a sync to happen. Incidentally, notice that the implementation of the SyncCommand class allows the GCM message to specify a jitter parameter, which causes it to trigger a sync not immediately but at a random time in the future within the jitter interval. This spreads out the syncs evenly over a period of time rather than forcing all clients to sync simultaneously, and thus prevents a sudden peak in requests on the server side.

Syncing User Data

The I/O app allows the user to build their own personalized schedule by choosing which sessions they are interested in attending. This data must be shared across the user’s Android devices, and also between the I/O website and Android. This means this data has to be stored in the cloud, in the user’s Google account. We chose to use the Google Drive AppData folder for this task.

User data is synced to Google Drive by the doUserScheduleSync method of the SyncHelper class. If you dive into the source code, you will notice that this method essentially accesses the Google Drive AppData folder through the Google Drive HTTP API, then reconciles the set of sessions in the data with the set of sessions starred by the user on the device, and issues the necessary modifications to the cloud if there are locally updated sessions.

This means that if the user selects one session on their Android device and then selects another session on the I/O website, the result should be that both the Android device and the I/O website will show that both sessions are in the user’s schedule.

Also, whenever the user adds or removes a session on the I/O website, the data on all their Android devices should be updated, and vice versa. To accomplish that, the I/O website sends our GCM server a notification every time the user makes a change to their schedule; the GCM server, in turn, sends a GCM message to all the devices owned by that user in order to cause them to sync their user data. The same mechanism works across the user’s devices as well: when one device updates the data, it issues a GCM message to all other devices.

Conclusion

Serving fresh data is a key component of many Android apps. This article showed how the I/O app deals with the challenges of keeping the data up-to-date while minimizing network traffic and database changes, and also keeping this data in sync across different platforms and devices through the use of Google Cloud Storage, Google Drive and Google Cloud Messaging.


Android Developers Blog

Feb 22

Build flexible layouts with FlexboxLayout

Posted by Takeshi Hagikura, Developer Programs Engineer


At Google I/O last year we announced ConstraintLayout,
which enables you to build complex layouts while maintaining a flat view
hierarchy. It is also fully supported in Android Studio’s Visual
Layout Editor.

At the same time, we open sourced FlexboxLayout to bring the
same functionalities of the CSS
Flexible Layout module to Android. Here are some cases where
FlexboxLayout is particularly effective.

FlexboxLayout can be interpreted as an advanced LinearLayout
because both layouts align their child views sequentially. The significant
difference between LinearLayout and FlexboxLayout is that
FlexboxLayout has a feature for wrapping.

That means if you add the flexWrap=”wrap” attribute,
FlexboxLayout puts a view to a new line if there is not enough
space left in the current line as shown in the picture below.

One layout for various screen sizes

With that characteristic in mind, let’s take a case where you want to put views
sequentially but have them move to new lines if the available space changes (due
to a device factor, orientation changes or the window resizing in the
multi-window mode).

Nexus5X portrait
Nexus5X landscape
Pixel C with multi window mode enabled, divider line on the left.

Pixel C with multi window mode enabled, divider line on the middle.

Pixel C with multi window mode enabled, divider line on the right.

You would need to define multiple DP-bucket layouts (such as layout-600dp,
layout-720dp, layout-1020dp) to handle various screen sizes with traditional
layouts such as LinearLayout or RelativeLayout. But
the dialog above is built with a single FlexboxLayout.

The technique used in the example is setting the flexWrap="wrap" as
explained above,

<com .google.android.flexbox.flexboxlayout
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     app:flexwrap="wrap">

then you can get the following layout where child views are aligned to a new
line instead of overflowing its parent.


Another technique I’d like to highlight is setting the
layout_flexGrow attribute to an individual child. This helps
improve the look of the final layout when free space is left over. The
layout_flexGrow attribute works similar to the
layout_weight attribute in LinearLayout. That means
FlexboxLayout will distribute the remaining space according to the
layout_flexGrow value set to each child in the same line.

In the example below, it assumes each child has the layout_flexGrow
attribute set to 1, so free space will be evenly distributed to
each of them.

 <android .support.design.widget.TextInputLayout
     android:layout_width="100dp"
     android:layout_height="wrap_content"
     app:layout_flexgrow="1">


You can check out the complete layout
xml file in the GitHub repository.

RecyclerView integration 

Another advantage of FlexboxLayout is that it can be integrated
with RecyclerView.
With the latest release of the alpha
version the new FlexboxLayoutManager extends
RecyclerView.LayoutManager, now you can make use of the Flexbox
functionalities in a scrollable container in much more memory-efficient way.

Note that you can still achieve a scrollable Flexbox container with
FlexboxLayout wrapped with ScrollView. But, you will
be likely to experience jankiness or even an OutOfMemoryError if the number of
items contained in the layout is large, as FlexboxLayout doesn’t
take view recycling into account for the views that go off the screen as the
user scrolls.

(If you would like to learn more about the RecyclerView in details, you can
check out the videos from the Android UI toolkit team such as 1, 2)

A real world example where the RecyclerView integration is useful
is for apps like the Google Photos app or News apps, both expect large number of
items while needing to handle various width of items.

One example is found in the demo
application in the FlexboxLayout repository. As you can see in
the repository, each image shown in RecyclerView has a different
width. But by setting the flexWrap setting to wrap,

FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
layoutManager.setFlexWrap(FlexWrap.WRAP);

and setting the flexGrow (as you can see, you can configure the
attributes through FlexboxLayoutManager and
FlexboxLayoutManager.LayoutParams for child attributes instead of
configuring it from xml) attribute to a positive value for each child,

void bindTo(Drawable drawable) {
  mImageView.setImageDrawable(drawable);
  ViewGroup.LayoutParams lp = mImageView.getLayoutParams();
  if (lp instanceof FlexboxLayoutManager.LayoutParams) {
    FlexboxLayoutManager.LayoutParams flexboxLp =
        (FlexboxLayoutManager.LayoutParams) mImageView.getLayoutParams();
    flexboxLp.setFlexGrow(1.0f);
  }
}

you can see every image fits within the layout nicely regardless of the screen
orientation.

If you would like to see complete FlexboxLayout example, you can check:

  • Playground
    demo app – using FlexboxLayout and
    FlexboxLayoutManager.
  • Cat
    gallery demo app – using FlexboxLayoutManager


What’s next?

Check out the full documentation for other
attributes to build flexible layouts tailored for your needs. We’re very open to
hear your feedback, if you find any issues or feature requests, please file an
issue on the GitHub
repository.


Android Developers Blog

Feb 22

Android Studio 1.4

Posted by, Jamal Eason, Product Manager, Android

Today we are releasing the 1.4 update to the Android Studio stable release channel. Most of the work and enhancements for Android Studio 1.4 are under the hood. However we have a handful of new features that we hope you enjoy and integrate into your workflow.

New Features in Android Studio 1.4



Design Tools

  • Vector Assets

    Starting with API 21, you can use Vector Drawables for image assets. For most apps, using VectorDrawables decreases the amount of density dependent drawables you need to maintain, and will also give you sharp image assets regardless of the screen device densities your app supports.

    With Android Studio 1.4, we are making the process of importing SVG images or Material icons much easier. If you update your gradle android plugin to 1.4.0-beta3 (or higher) in the project structure dialogue or your project build.gradle file ( ‘com.android.tools.build:gradle:1.4.0-beta3′
    ), you can now use the new Vector Asset Studio by right-clicking the res/drawable folder in your project and selecting New → Vector Asset from the content menu.

    We are also excited to offer backwards compatibility for your vector assets in Android Studio 1.4. Once you have a vectorDrawable image in your res/drawable, Android Studio will automatically generate raster PNG images for API level 20 and below during build time. This means you only need to update and maintain your vector asset for your app project and Android Studio can take care of image conversion process. Note, it is still best practice to create density dependent launcher icons in your res/mipmap folder. Learn more by watching the DevByte video on the new Vector Asset Studio tool.


  • Theme Editor

    We understand that managing your app theme and style can be a bit complex. With Android Studio 1.4, we are releasing a preview of the Theme Editor to help with this task. This first version of the Theme Editor is focused on editing and updating the material theme colors (colors.xml) in your app project. In future releases, we will cover more attributes of your app theme and styles files. To access the editor, navigate from top level menu Tools → Android → Theme Editor.

  • Project Templates

    We know many of you use the New Project Wizard app templates to start a new app project or to quickly add an activity to an existing app. To help with the visual design of your apps, we updated the app templates to include the Android Design Support Library alongside the AppCompat Support library.

    From the template wizard you can start projects with a basic blank template with a floating action button or start from a range of user interface components such as the navigation drawer, or AppBar with scrolling view. We also re-introduced the empty app template for those who want minimum code generation when adding an activity to your project.

    With Android Studio 1.4, you can also validate your apps on the new Nexus 5X and Nexus 6P screen sizes.

Performance Monitors

  • GPU Rendering Monitor

    Now it is possible to quickly inspect the GPU rendering performance of your app. To enable GPU monitoring, make sure you turn on monitoring for your Android hardware device or emulator under Setting → Developer Options → Profile GPU rendering → In adb shell dumpsys gfxinfo . To learn more about the GPU rendering results, check out the developer documentation.

  • Network Monitor

    With Android Studio 1.4, you can also monitor the network usage of your app. With the monitor you can track the transmit and receive rates of your app over time.

Developer Services

  • Firebase

    It is now even easier to add a Firebase mobile backend to your Android app. Firebase includes data storage, user authentication, static hosting, and more. To access the feature, navigate from the top level menu and select File → Project Structure → Cloud. Learn more about Firebase in this tutorial.

Whats Next

For current developers on Android Studio, you can check for updates from the navigation menu (Help → Check for Update [Windows/Linux] , Android Studio → Check for Updates [OS X]) . For new users, you can learn more about Android Studio on the product overview page or download the stable version from the Android Studio download site.

We welcome feedback on how we can help you. Connect with the Android developer tools team on Google+.


Android Developers Blog