%a
<atomic>
<type_traits>
APP_STL := c++_shared
-DANDROID_STL=c++_shared
externalNativeBuild { cmake { arguments "-DANDROID_STL=c++_shared" } }
--stl=libc++
_FILE_OFFSET_BITS=64
off_t
lseek
lseek64
off64_t
APP_UNIFIED_HEADERS := true
$ ndk-build APP_UNIFIED_HEADERS=true
android { ... defaultConfig { ... externalNativeBuild { ndkBuild { ... arguments "APP_UNIFIED_HEADERS=true" } } } }
android { ... defaultConfig { ... externalNativeBuild { cmake { ... arguments "-DANDROID_UNIFIED_HEADERS=ON" } } } }
Posted by Matteo Vallone, Google Play Games Business Development
To build awareness of the awesome innovation and art that indie game developers are bringing to users on Google Play, we have invested heavily over the past year in programs like Indie Corner, as well as events like the Google Play Indie Games Festivals in North America and Korea.
As part of that sustained effort, we also want to celebrate the passion and innovation of indie game developers with the introduction of the first-ever Google Play Indie Games Contest in Europe. The contest will recognize the best indie talent in several countries and offer prizes that will help you get your game noticed by industry experts and gamers worldwide.
Prizes for the finalists and winners:
Entering the contest:
If you're based in Czech Republic, Denmark, Finland, France (coming soon), Germany, Iceland, Israel, Netherlands, Norway, Poland (coming soon), Romania, Spain, Sweden, Turkey, or UK (excl. Northern Ireland), have 15 or less full time employees, and published a new game on Google Play after 1 January 2016, you may now be eligible to enter the contest. If you're planning on publishing a new game soon, you can also enter by submitting a private beta. Check out all the details in the terms and conditions. Submissions close on 31 December 2016.
The process:
Up to 20 finalists will get to showcase their games at an open event at the Saatchi Gallery in London on the 16th February 2017. At the event, the top 10 will be selected by the event attendees and the Google Play team. The top 10 will then get the opportunity to pitch to a jury of industry experts, from which the final winner and runners up will be selected.
Even if someone is NOT entering the contest:
Even if you're not eligible to enter the contest, you can still register to attend the final showcase event in London on 16 February 2017, check out some great indie games, and have fun with various industry experts and indie developers. We will also be hosting a workshop for all indie games developers from across EMEA in the new Google office in Kings Cross the next day, so this will be a packed week.
Get started:
Enter the Indie Games Contest now and visit the contest site to find out more about the contest, the event, and the workshop.
In addition to supporting the experimental Gradle plugin, Android Studio 2.2 enables you to build C/C++ components of Android projects using CMake and ndk-build.
The Android Studio team plans to continue to support the experimental Gradle plugin. This will eventually replace the current Gradle plugin, providing additional tightly-integrated benefits to C/C++ developers such as smarter dependency management. So if you're interested in someday having the smartest possible interface between your IDE and your build system, you shouldn't ignore the experimental plugin.
CMake and ndk-build are useful alternatives to Gradle in several cases:
For new projects, we recommend using CMake or experimental Gradle. For new Android projects with limited C++, we recommend trying the experimental Gradle plugin. For projects with substantial amounts of C++, or where you want the maximally stable build configuration, we recommend using a CMake build. Android Studio intends CMake to be a permanently supported solution.
While we think that there are substantial advantages to having a single build system able to handle all parts of an Android application, stabilizing the experimental plugin is not an option for us because it relies on Gradle APIs that are still a work in progress. Until the Gradle APIs are stabilized, the experimental plugin will keep changing, particularly in its Domain Specific Language, and will be strictly tied to a very specific version of Gradle itself.
Note that the the old, undocumented ndkCompile integration is deprecated. If you are using it, you need to move away from it as we'll remove it completely in the near future. We recommend migrating to gradle+cmake via our migration guide.
Migrating from Eclipse to Android Studio
We no longer support the Eclipse ADT. To get started migrating, download and install Android Studio. For most projects, migration is as simple as importing your existing Eclipse ADT projects in Android Studio with the File → New→ Import Project menu option. For more details on the migration process, check out the migration guide.
Feedback and Open Source Contributions
We're dedicated to making Android Studio the best possible integrated development environment for building Android apps, so if there are missing features or other challenges preventing you from using Android Studio, we want to hear about it [please take our survey]. You can also file bugs or feature requests directly with the team, and let us know via our Twitter or Google+ accounts.
Android Studio is an open source project, available to all at no cost. Check out our Open Source project page if you're interested in contributing or learning more.
Posted by Dmitry Malykhanov, Developer Advocate
Related to other improvements to the Android platform, the dynamic linker in Android M and N has stricter requirements for writing clean, cross-platform compatible native code in order to load. It is necessary that an application’s native code follows the rules and recommendations in order to ensure a smooth transition to recent Android releases.
Below we outline in detail each individual change related to native code loading, the consequences and steps you can take to avoid issues.
Required tools: there is an <arch>-linux-android-readelf binary (e.g. arm-linux-androideabi-readelf or i686-linux-android-readelf) for each architecture in the NDK (under toolchains/), but you can use readelf for any architecture, as we will be doing basic inspection only. On Linux you need to have the “binutils” package installed for readelf, and “pax-utils” for scanelf.
Native libraries must use only public API, and must not link against non-NDK platform libraries. Starting with API 24 this rule is enforced and applications are no longer able to load non-NDK platform libraries. The rule is enforced by the dynamic linker, so non-public libraries are not accessible regardless of the way code tries to load them: System.loadLibrary(...), DT_NEEDED entries, and direct calls to dlopen(...) will fail in exactly the same way.
Users should have a consistent app experience across updates, and developers shouldn’t have to make emergency app updates to handle platform changes. For that reason, we recommend against using private C/C++ symbols. Private symbols aren’t tested as part of the Compatibility Test Suite (CTS) that all Android devices must pass. They may not exist, or they may behave differently. This makes apps that use them more likely to fail on specific devices, or on future releases --- as many developers found when Android 6.0 Marshmallow switched from OpenSSL to BoringSSL.
In order to reduce the user impact of this transition, we’ve identified a set of libraries that see significant use from Google Play’s most-installed apps, and that are feasible for us to support in the short term (including libandroid_runtime.so, libcutils.so, libcrypto.so, and libssl.so). In order to give you more time to transition, we will temporarily support these libraries; so if you see a warning that means your code will not work in a future release -- please fix it now!
$ readelf --dynamic libBroken.so | grep NEEDED 0x00000001 (NEEDED) Shared library: [libnativehelper.so] 0x00000001 (NEEDED) Shared library: [libutils.so] 0x00000001 (NEEDED) Shared library: [libstagefright_foundation.so] 0x00000001 (NEEDED) Shared library: [libmedia_jni.so] 0x00000001 (NEEDED) Shared library: [liblog.so] 0x00000001 (NEEDED) Shared library: [libdl.so] 0x00000001 (NEEDED) Shared library: [libz.so] 0x00000001 (NEEDED) Shared library: [libstdc++.so] 0x00000001 (NEEDED) Shared library: [libm.so] 0x00000001 (NEEDED) Shared library: [libc.so]
Potential problems: starting from API 24 the dynamic linker will not load private libraries, preventing the application from loading.
Resolution: rewrite your native code to rely only on public API. As a short term workaround, platform libraries without complex dependencies (libcutils.so) can be copied to the project. As a long term solution the relevant code must be copied to the project tree. SSL/Media/JNI internal/binder APIs should not be accessed from the native code. When necessary, native code should call appropriate public Java API methods.
A complete list of public libraries is available within the NDK, under platforms/android-API/usr/lib.
platforms/android-API/usr/lib
Note: SSL/crypto is a special case, applications must NOT use platform libcrypto and libssl libraries directly, even on older platforms. All applications should use GMS Security Provider to ensure they are protected from known vulnerabilities.
Each ELF file has additional information contained in the section headers. These headers must be present now, because the dynamic linker uses them for sanity checking. Some developers try to strip them in an attempt to obfuscate the binary and prevent reverse engineering. (This doesn’t really help because it is possible to reconstruct the stripped information using widely-available tools.)
$ readelf --header libBroken.so | grep 'section headers' Start of section headers: 0 (bytes into file) Size of section headers: 0 (bytes) Number of section headers: 0 $
Resolution: remove the extra steps from your build that strip section headers.
Starting with API 23, shared objects must not contain text relocations. That is, the code must be loaded as is and must not be modified. Such an approach reduces load time and improves security.
The usual reason for text relocations is non-position independent hand-written assembler. This is not common. Use the scanelf tool as described in our documentation for further diagnostics:
$ scanelf -qT libTextRel.so libTextRel.so: (memory/data?) [0x15E0E2] in (optimized out: previous simd_broken_op1) [0x15E0E0] libTextRel.so: (memory/data?) [0x15E3B2] in (optimized out: previous simd_broken_op2) [0x15E3B0] [skipped the rest]
If you have no scanelf tool available, it is possible to do a basic check with readelf instead, look for either a TEXTREL entry or the TEXTREL flag. Either alone is sufficient. (The value corresponding to the TEXTREL entry is irrelevant and typically 0 --- simply the presence of the TEXTREL entry declares that the .so contains text relocations). This example has both indicators present:
$ readelf --dynamic libTextRel.so | grep TEXTREL 0x00000016 (TEXTREL) 0x0 0x0000001e (FLAGS) SYMBOLIC TEXTREL BIND_NOW $
Note: it is technically possible to have a shared object with the TEXTREL entry/flag but without any actual text relocations. This doesn’t happen with the NDK, but if you’re generating ELF files yourself make sure you’re not generating ELF files that claim to have text relocations, because the Android dynamic linker trusts the entry/flag.
Potential problems: Relocations enforce code pages being writable, and wastefully increase the number of dirty pages in memory. The dynamic linker has issued warnings about text relocations since Android K (API 19), but on API 23 and above it refuses to load code with text relocations.
Resolution: rewrite assembler to be position independent to ensure no text relocations are necessary. Check the Gentoo documentation for cookbook recipes.
While library dependencies (DT_NEEDED entries in the ELF headers) can be absolute paths, that doesn’t make sense on Android because you have no control over where your library will be installed by the system. A DT_NEEDED entry should be the same as the needed library’s SONAME, leaving the business of finding the library at runtime to the dynamic linker.
Before API 23, Android’s dynamic linker ignored the full path, and used only the basename (the part after the last ‘/’) when looking up the required libraries. Since API 23 the runtime linker will honor the DT_NEEDED exactly and so it won’t be able to load the library if it is not present in that exact location on the device.
Even worse, some build systems have bugs that cause them to insert DT_NEEDED entries that point to a file on the build host, something that cannot be found on the device.
$ readelf --dynamic libSample.so | grep NEEDED 0x00000001 (NEEDED) Shared library: [libm.so] 0x00000001 (NEEDED) Shared library: [libc.so] 0x00000001 (NEEDED) Shared library: [libdl.so] 0x00000001 (NEEDED) Shared library: [C:\Users\build\Android\ci\jni\libBroken.so] $
Potential problems: before API 23 the DT_NEEDED entry’s basename was used, but starting from API 23 the Android runtime will try to load the library using the path specified, and that path won’t exist on the device. There are broken third-party toolchains/build systems that use a path on a build host instead of the SONAME.
Resolution: make sure all required libraries are referenced by SONAME only. It is better to let the runtime linker to find and load those libraries as the location may change from device to device.
Each ELF shared object (“native library”) must have a SONAME (Shared Object Name) attribute. The NDK toolchain adds this attribute by default, so its absence indicates either a misconfigured alternative toolchain or a misconfiguration in your build system. A missing SONAME may lead to runtime issues such as the wrong library being loaded: the filename is used instead when this attribute is missing.
$ readelf --dynamic libWithSoName.so | grep SONAME 0x0000000e (SONAME) Library soname: [libWithSoName.so] $
Potential problems: namespace conflicts may lead to the wrong library being loaded at runtime, which leads to crashes when required symbols are not found, or you try to use an ABI-incompatible library that isn’t the library you were expecting.
Resolution: the current NDK generates the correct SONAME by default. Ensure you’re using the current NDK and that you haven’t configured your build system to generate incorrect SONAME entries (using the -soname linker option).
-soname
Please remember, clean, cross-platform code built with a current NDK should have no issues on Android N. We encourage you to revise your native code build so that it produces correct binaries.
Posted by Dimitry Ivanov & Elliott Hughes, Software Engineers
As documented in the Android N behavioral changes, to protect Android users and apps from unforeseen crashes, Android N will restrict which libraries your C/C++ code can link against at runtime. As a result, if your app uses any private symbols from platform libraries, you will need to update it to either use the public NDK APIs or to include its own copy of those libraries. Some libraries are public: the NDK exposes libandroid, libc, libcamera2ndk, libdl, libGLES, libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES, libstdc++, libvulkan, and libz as part of the NDK API. Other libraries are private, and Android N only allows access to them for platform HALs, system daemons, and the like. If you aren’t sure whether your app uses private libraries, you can immediately check it for warnings on the N Developer Preview.
We’re making this change because it’s painful for users when their apps stop working after a platform update. Whether they blame the app developer or the platform, everybody loses. Users should have a consistent app experience across updates, and developers shouldn’t have to make emergency app updates to handle platform changes. For that reason, we recommend against using private C/C++ symbols. Private symbols aren’t tested as part of the Compatibility Test Suite (CTS) that all Android devices must pass. They may not exist, or they may behave differently. This makes apps that use them more likely to fail on specific devices, or on future releases — as many developers found when Android 6.0 Marshmallow switched from OpenSSL to BoringSSL.
You may be surprised that there’s no STL in the list of NDK libraries. The three STL implementations included in the NDK — the LLVM libc++, the GNU STL, and libstlport — are intended to be bundled with your app, either by statically linking into your library, or by inclusion as a separate shared library. In the past, some developers have assumed that they didn’t need to package the library because the OS itself had a copy. This assumption is incorrect: a particular STL implementation may disappear (as was the case with stlport, which was removed in Marshmallow), may never have been available (as is the case with the GNU STL), or it may change in ABI incompatible ways (as is the case with the LLVM libc++).
In order to reduce the user impact of this transition, we’ve identified a set of libraries that see significant use from Google Play’s most-installed apps, and that are feasible for us to support in the short term (including libandroid_runtime.so, libcutils.so, libcrypto.so, and libssl.so). For legacy code in N, we will temporarily support these libraries in order to give you more time to transition. Note that we don't intend to continue this support in any future Android platform release, so if you see a warning that means your code will not work in a future release — please fix it now!
Table 1. What to expect if your app is linking against private native libraries.
Please test your app during the N Previews.
targetSdkVersion
Test your apps on the Developer Preview — if you see a toast like this one, your app is accessing private native APIs. Please fix your code soon!
Here’s some example logcat output from an app that hasn’t bumped its target SDK version (and so the restriction isn’t fully enforced because this is only the developer preview):
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so" ("/system/lib/libandroid_runtime.so") needed or dlopened by "/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120
This is telling you that your library “libapplib.so” refers to the library “libandroid_runtime.so”, which is a private library.
When Android N ships, or if you set your target SDK version to N now, you’ll see something like this if you try to use System.loadLibrary from Java:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace" at java.lang.Runtime.loadLibrary0(Runtime.java:977) at java.lang.System.loadLibrary(System.java:1602)
If you’re using dlopen(3) from C/C++ you’ll get a NULL return and dlerror(3) will return the same “dlopen failed...” string as shown above.
For more information about how to check if your app is using private symbols, see the FAQ on developer.android.com.
Posted by Shannon Woods, Technical Program Manager
Today we're pleased to bring you a preview of Android development tools for Vulkan™. Vulkan is a new 3D rendering API which we’ve helped to develop as a member of Khronos, geared at providing explicit, low-overhead GPU (Graphics Processor Unit) control to developers. Vulkan’s reduction of CPU overhead allows some synthetic benchmarks to see as much as 10 times the draw call throughput on a single core as compared to OpenGL ES. Combined with a threading-friendly API design which allows multiple cores to be used in parallel with high efficiency, this offers a significant boost in performance for draw-call heavy applications.
Vulkan support is available now via the Android N Preview on devices which support it, including Nexus 5X and Nexus 6P. (Of course, you will still be able to use OpenGL ES as well!)
To help developers start coding quickly, we’ve put together a set of samples and guides that illustrate how to use Vulkan effectively.
You can see Vulkan in action running on an Android device with Robert Hodgin’s Fish Tornado demo, ported by Google’s Art, Copy, and Code team:
There are many similarities between OpenGL ES and Vulkan, but Vulkan offers new features for developers who need to make every millisecond count.
As noted above, Vulkan’s lack of implicit validation requires developers to make use of tools outside the API in order to validate their code. Vulkan’s layer mechanism allows validation code and other developer tools to inspect every API call during development, without incurring any overhead in the shipping version. Our guides show you how to build the validation layers for use with the Android NDK, giving you the tools necessary to build bug-free Vulkan code from start to finish.
The Vulkan ecosystem is a broad one, and the resources to get you started don’t end here. There is a wealth of material to explore, including:
Posted by Shanee Nishry
Previously, we showed how you can use vertex layout qualifiers to increase the performance and determinism of your OpenGL application. In this post, we’ll show another useful technique that will help you produce increased performance and cleaner code when drawing objects.
Before drawing onto the screen, you need to bind your vertex data (e.g. positions, normals, UVs) to the corresponding vertex shader attributes. To do that, you need to bind the vertex buffer, enable the generic vertex attribute, and use glVertexAttribPointer to describe the layout of the buffer.
Therefore, a draw call might look like this:
const GLuint ATTRIBUTE_LOCATION_POSITIONS = 0; const GLuint ATTRIBUTE_LOCATION_TEXTUREUV = 1; const GLuint ATTRIBUTE_LOCATION_NORMALS = 2; // Bind shader program, uniforms and textures // ... // Bind the vertex buffer glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer_object ); // Set the vertex attributes glEnableVertexAttribArray( ATTRIBUTE_LOCATION_POSITIONS ); glVertexAttribPointer( ATTRIBUTE_LOCATION_POSITIONS, 3, GL_FLOAT, GL_FALSE, 32, 0 ); glEnableVertexAttribArray( ATTRIBUTE_LOCATION_TEXTUREUV ); glVertexAttribPointer( ATTRIBUTE_LOCATION_TEXTUREUV, 2, GL_FLOAT, GL_FALSE, 32, 12 ); glEnableVertexAttribArray( ATTRIBUTE_LOCATION_NORMALS ); glVertexAttribPointer( ATTRIBUTE_LOCATION_NORMALS, 3, GL_FLOAT, GL_FALSE, 32, 20 ); // Draw elements glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_SHORT, 0 );
There are several reasons why we might not like this code very much. The first is that we need to cache the layout of the vertex buffer to enable and disable the right attributes before drawing. This means we are either hard-coding or saving some amount of data for a nearly meaningless task.
The second reason is performance. Having to tell the drivers which attributes to individually activate is suboptimal. It would be best if we could precompile this information and deliver it all at once.
Lastly, and purely for aesthetics, our draw call is cluttered by long boilerplate code. It would be nice to get rid of it.
So how can we improve on the above code?
If you are using OpenGL ES 3 or higher, you should use Vertex Array Objects (or "VAOs") to store your vertex attribute state.
Using a VAO allows the drivers to compile the vertex description format for repeated use. In addition, this frees you from having to cache the vertex format needed for glVertexAttribPointer, and it also results in less per-draw boilerplate code.
The first thing you need to do is create your VAO. This is created once per mesh, alongside the vertex buffer object and is done like this:
const GLuint ATTRIBUTE_LOCATION_POSITIONS = 0; const GLuint ATTRIBUTE_LOCATION_TEXTUREUV = 1; const GLuint ATTRIBUTE_LOCATION_NORMALS = 2; // Bind the vertex buffer object glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer_object ); // Create a VAO GLuint vao; glGenVertexArrays( 1, &vao; ); glBindVertexArray( vao ); // Set the vertex attributes as usual glEnableVertexAttribArray( ATTRIBUTE_LOCATION_POSITIONS ); glVertexAttribPointer( ATTRIBUTE_LOCATION_POSITIONS, 3, GL_FLOAT, GL_FALSE, 32, 0 ); glEnableVertexAttribArray( ATTRIBUTE_LOCATION_TEXTUREUV ); glVertexAttribPointer( ATTRIBUTE_LOCATION_TEXTUREUV, 2, GL_FLOAT, GL_FALSE, 32, 12 ); glEnableVertexAttribArray( ATTRIBUTE_LOCATION_NORMALS ); glVertexAttribPointer( ATTRIBUTE_LOCATION_NORMALS, 3, GL_FLOAT, GL_FALSE, 32, 20 ); // Unbind the VAO to avoid accidentally overwriting the state // Skip this if you are confident your code will not do so glBindVertexArray( 0 );
You have probably noticed that this is very similar to our previous code section except that we now have the addition of:
// Create a vertex array object GLuint vao; glGenVertexArrays( 1, &vao; ); glBindVertexArray( vao );
These lines create and bind the VAO. All glEnableVertexAttribArray and glVertexAttribPointer calls after that are recorded in the currently bound VAO, and that greatly simplifies our per-draw procedure as all you need to do is use the newly created VAO.
The next time you want to draw using this mesh all you need to do is bind the VAO using glBindVertexArray.
// Bind shader program, uniforms and textures // ... // Bind Vertex Array Object glBindVertexArray( vao ); // Draw elements glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_SHORT, 0 );
You no longer need to go through all the vertex attributes. This makes your code cleaner, makes per-frame calls shorter and more efficient, and allows the drivers to optimize the binding stage to increase performance.
Want to learn more how to improve your game performance? Check out our Game Performance article series. If you are building on Android you might also be interested in the Android Performance Patterns.
Posted by Ian Lake, Developer Advocate
The Android Support Library is a collection of libraries available on a wide array of API levels that help you focus on the unique parts of your app, providing pre-built components, new functionality, and compatibility shims.
With the latest release of the Android Support Library (23.1), you will see improvements across the Support V4, Media Router, RecyclerView, AppCompat, Design, Percent, Custom Tabs, Leanback, and Palette libraries. Let’s take a closer look.
The Support V4 library focuses on making supporting a wide variety of API levels straightforward with compatibility shims and backporting specific functionality.
NestedScrollView is a ScrollView that supports nested scrolling back to API 4. You’ll now be able to set a OnScrollChangeListener to receive callbacks when the scroll X or Y positions change.
ScrollView
There are a lot of pieces that make up a fully functioning media playback app, with much of it centered around MediaSessionCompat. A media button receiver, a key part to handling playback controls from hardware or bluetooth controls, is now formalized in the new MediaButtonReceiver class. This class makes it possible to forward received playback controls to a Service which is managing your MediaSessionCompat, reusing the Callback methods already required for API 21+, centralizing support on all API levels and all media control events in one place. A simplified constructor for MediaSessionCompat is also available, automatically finding a media button receiver in your manifest for use with MediaSessionCompat.
MediaSessionCompat
MediaSessionCompat.
The Media Router Support Library is the key component for connecting and sending your media playback to remote devices, such as video and audio devices with Google Cast support. It also provides the mechanism, via MediaRouteProvider, to enable any application to create and manage a remote media playback device connection.
In this release, MediaRouteChooserDialog (the dialog that controls selecting a valid remote device) and MediaRouteControllerDialog (the dialog to control ongoing remote playback) have both received a brand new design and additional functionality as well. You’ll find the chooser dialog sorts devices by frequency of use and includes a device type icon for easy identification of different devices while the controller dialog now shows current playback information (including album art).
To feel like a natural part of your app, the content color for both dialogs is now based on the colorPrimary of your alert dialog theme:
colorPrimary
<!-- Your app theme set on your Activity --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/primary</item> <item name="colorPrimaryDark">@color/primaryDark</item> <item name="alertDialogTheme">@style/AppTheme.Dialog</item> </style>
<!-- Theme for the dialog itself --> <style name="AppTheme.Dialog" parent="Theme.AppCompat.Light.Dialog.Alert"> <item name="colorPrimary">@color/primary</item> <item name="colorPrimaryDark">@color/primaryDark</item> </style>
RecyclerView is an extremely powerful and flexible way to show a list, grid, or any view of a large set of data. One advantage over ListView or GridView is the built in support for animations as items are added, removed, or repositioned.
ListView
GridView
This release significantly changes the animation system for the better. By using the new ItemAnimator’s canReuseUpdatedViewHolder() method, you’ll be able to choose to reuse the existing ViewHolder, enabling item content animation support. The new ItemHolderInfo and associated APIs give the ItemAnimator the flexibility to collect any data it wants at the correct point in the layout lifecycle, passing that information into the animate callbacks.
Note that this new API is not backward compatible. If you previously implemented an ItemAnimator, you can instead extend SimpleItemAnimator, which provides the old API by wrapping the new API. You’ll also notice that some methods have been entirely removed from ItemAnimator. For example, if you were calling recyclerView.getItemAnimator().setSupportsChangeAnimations(false), this code won’t compile anymore. You can replace it with:
ItemAnimator
recyclerView.getItemAnimator().setSupportsChangeAnimations(false),
ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof SimpleItemAnimator) { ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); }
One component of the AppCompat Support Library has been in providing a consistent set of widgets across all API levels, including the ability to tint those widgets to match your branding and accent colors.
This release adds tint aware versions of SeekBar (for tinting the thumb) as well as ImageButton and ImageView (providing backgroundTint support) which will automatically be used when you use the platform versions in your layouts. You’ll also find that SwitchCompat has been updated to match the styling found in Android 6.0 Marshmallow.
backgroundTint
The Design Support Library includes a number of components to help implement the latest in the Google design specifications.
TextInputLayout expands its existing functionality of floating hint text and error indicators with new support for character counting.
AppBarLayout supports a number of scroll flags which affect how children views react to scrolling (e.g. scrolling off the screen). New to this release is SCROLL_FLAG_SNAP, ensuring that when scrolling ends, the view is not left partially visible. Instead, it will be scrolled to its nearest edge, making fully visible or scrolled completely off the screen. You’ll also find that AppBarLayout now allows users to start scrolling from within the AppBarLayout rather than only from within your scrollable view - this behavior can be controlled by adding a DragCallback.
NavigationView provides a convenient way to build a navigation drawer, including the ability to creating menu items using a menu XML file. We’ve expanded the functionality possible with the ability to set custom views for items via app:actionLayout or using MenuItemCompat.setActionView().
app:actionLayout
The Percent Support Library provides percentage based dimensions and margins and, new to this release, the ability to set a custom aspect ratio via app:aspectRatio. By setting only a single width or height and using aspectRatio, the PercentFrameLayout or PercentRelativeLayout will automatically adjust the other dimension so that the layout uses a set aspect ratio.
app:aspectRatio.
The Custom Tabs Support Library allows your app to utilize the full features of compatible browsers including using pre-existing cookies while still maintaining a fast load time (via prefetching) and a custom look and actions.
In this release, we’re adding a few additional customizations such as hiding the url bar when the page is scrolled down with the new enableUrlBarHiding() method. You’ll also be able to update the action button in an already launched custom tab via your CustomTabsSession with setActionButton() - perfect for providing a visual indication of a state change.
Navigation events via CustomTabsCallback#onNavigationEvent() have also been expanded to include the new TAB_SHOWN and TAB_HIDDEN events, giving your app more information on how the user interacts with your web content.
The Leanback library makes it easy to build user interfaces on TV devices. This release adds GuidedStepSupportFragment for a support version of GuidedStepFragment as well as improving animations and transitions and allowing GuidedStepFragment to be placed on top of existing content.
You’ll also be able to annotate different types of search completions in SearchFragment and staggered slide transition support for VerticalGridFragment.
Palette, used to extract colors from images, now supports extracting from a specific region of a Bitmap with the new setRegion() method.
There’s no better time to get started with the Android Support Library. You can get started developing today by updating the Android Support Repository from the Android SDK Manager.
For an in depth look at every API change in this release, check out the full API diff.
To learn more about the Android Support Library and the APIs available to you through it, visit the Support Library section on the Android Developer site.
Posted by Ben Frenkel, Product Manager Google Play Games
Launched last March, Player Analytics is already becoming an important tool for many game developers, helping them to manage their games businesses and optimize in-game player behavior. Today we’re expanding Player Analytics with two new analytics reports that give you better visibility into time-based player activity and custom game events. We’re also introducing a new Player Stats API to let you tune your game experience for specific segments of players across the game lifecycle. Along with those, we’re rolling out a new version of our C++/iOS SDKs and Unity plug-in and giving you better tools to manage repeating Quests.
We are launching two new reports later this week in the Play Games developer console: the Player Time Series Explorer and the Events Viewer. We’ve also made improvements to our player retention report.
Ever wondered what your players are doing in the first few minutes of gameplay? What happens just before players spend or churn? The time-series explorer lets you understand what happens in these critical moments for your players.
For example, you carefully built out the first set of experiences in your game, but are surprised by how many players never get through even the first set of challenges. With the Player Time Series Explorer, you can now see which challenges are impeding player progress most, and make targeted improvements to decrease the rate of churn. Learn more.
Customize settings to explore player time series
Select from a list of preset questions
Find out what happens before your players spend for the first time
Select “What happens before first spend” to see what happens just before your players spend for the first time. Time series are aligned by first spend event so you can easily explore what happened just before and after first purchase.
Find out what happens before your players churn
Select “What happens before churn” to see what happens before your players stop playing. In the example below, all the churn events are right aligned to make it easier to compare player time series.
You can see more details for all event types by holding your cursor over the event’s shape. In this example, you can see that “Player 03” spent $4.99 after earning six achievements. Hovering over the achievement shapes will show you which specific achievements were earned.
Now you can create your own reports based on your custom Play Games’ events. You can select multiple events to display and bookmark the report for easy access. Learn more.
Here’s an example showing how a developer can compare the rates at which Players are entering contests, winning, and almost winning. This report would identify opportunities to improve the balance of its contest modes. You can then bookmark the settings so you can easily track improvements.
We added a 28-day-by-28-day retention grid to help you compare retention rates across a larger number of new user cohorts.
Stats and reports give you insights into your what your players are doing, but wouldn’t it be nice to take action on those insights in your game? That’s what the Player Stats API is all about. The Player Stats API lets you tailor player experiences to specific segments of players across the game lifecycle. Player segments are based on player progression, spend, and engagement.
Here are some examples of what you can do with Player Stats API:
The Player Stats API is launching in the next few weeks.
iOS support for Play game services just got a lot better. This update includes improved CocoaPods support, which will make it easier to configure Play game services in Xcode. This also means you’ll have a much easier time building for iOS using the Unity plug-in as well.
The latest build of the C++/iOS SDKs is now built on the new Google Sign-In framework, which adds support for authentication via multiple Google apps, including Gmail and YouTube. More importantly, if a player does not have any applicable Google apps installed, the Sign-In framework will bring up a webview within the app for authentication. Opening up a webview inside the app, instead of switching to a separate browser instance, makes for a much better user experience, and addresses a top developer request. For more on the new Google Sign-in library on iOS, check out this video. Learn more.
Quests are a great way of engaging your players with new goals, and with this update we have made managing Quests easier with the introduction of repeating Quests. You can create Quests that run weekly or monthly by checking the repeating quest box. This will make it easier for you to engage your players with regularly occurring challenges. Repeating Quests will be launching in the next few weeks.
If you have previously integrated Quests, you can easily convert them into repeating quests by following two easy steps.
1. Go to Quests section of developer console, and open up an existing Quest. Click the copy Quest button at the top of the page
2. Scroll down to the Schedule section of the Quest form, check the “Repeating quest” box, select between monthly and weekly quests under “Repeats”, and leave the “Ends:” field set to “Never”. After hitting save, you are done! From then on, the quest will run weekly or monthly until you decide to end it.
Google Play game services (GPGS) docs and SDK downloads
Posted by Jamal Eason, Product Manager, Android
Previewed earlier this summer at Google I/O, Android Studio 1.3 is now available on the stable release channel. We appreciated the early feedback from those developers on our canary and beta channels to help ship a great product.
Android Studio 1.3 is our biggest feature release for the year so far, which includes a new memory profiler, improved testing support, and full editing and debugging support for C++. Let’s take a closer look.
Performance & Testing Tools
Android Studio now allows you to capture and analyze memory snapshots in the native Android HPROF format.
In addition to displaying a table of memory allocations that your app uses, the updated allocation tracker now includes a visual way to view the your app allocations.
For more flexibility in app testing, you now have the option to place your code tests in a separate module and use the new test plugin (‘com.android.test’) instead of keeping your tests right next to your app code. This feature does require your app project to use the Gradle Plugin 1.3.
Android Studio now has inline code annotation support to help you manage the new app permissions model in the M release of Android. Learn more about code annotations.
New data brinding features allow you to create declarative layouts in order to minimize boilerplate code by binding your application logic into your layouts. Learn more about data binding.
Managing Android SDK updates is now a part of the Android Studio. By default, Android Studio will now prompt you about new SDK & Tool updates. You can still adjust your preferences with the new & integrated Android SDK Manager.
As a part of the Android 1.3 stable release, we included an Early Access Preview of the C++ editor & debugger support paired with an experimental build plugin. See the Android C++ Preview page for information on how to get started. Support for more complex projects and build configurations is in development, but let us know your feedback.
An important thing to remember is that an update to Android Studio does not require you to change your Android app projects. With updating, you get the latest features but still have control of which build tools and app dependency versions you want to use for your Android app.
For current developers on Android Studio, you can check for updates from the navigation menu. 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 are excited to launch this set of features in Android Studio and we are hard at work developing the next set of tools to make develop Android development easier on Android Studio. As always we welcome feedback on how we can help you. Connect with the Android developer tools team on Google+.
Posted by Shanee Nishry, Game Developer Advocate
To improve game performance, we’d like to highlight a programming paradigm that will help you maximize your CPU potential, make your game more efficient, and code smarter.
Before we get into detail of data-oriented programming, let’s explain the problems it solves and common pitfalls for programmers.
The first thing a programmer must understand is that memory is slow and the way you code affects how efficiently it is utilized. Inefficient memory layout and order of operations forces the CPU idle waiting for memory so it can proceed doing work.
The easiest way to demonstrate is by using an example. Take this simple code for instance:
char data[1000000]; // One Million bytes unsigned int sum = 0; for ( int i = 0; i < 1000000; ++i ) { sum += data[ i ]; }
An array of one million bytes is declared and iterated on one byte at a time. Now let's change things a little to illustrate the underlying hardware. Changes marked in bold:
char data[16000000]; // Sixteen Million bytes unsigned int sum = 0; for ( int i = 0; i < 16000000; i += 16 ) { sum += data[ i ]; }
The array is changed to contain sixteen million bytes and we iterate over one million of them, skipping 16 at a time.
A quick look suggests there shouldn't be any effect on performance as the code is translated to the same number of instructions and runs the same number of times, however that is not the case. Here is the difference graph. Note that this is on a logarithmic scale--if the scale were linear, the performance difference would be too large to display on any reasonably-sized graph!
The simple change making the loop skip 16 bytes at a time makes the program run 5 times slower!
The average difference in performance is 5x and is consistent when iterating 1,000 bytes up to a million bytes, sometimes increasing up to 7x. This is a serious change in performance.
Note: The benchmark was run on multiple hardware configurations including a desktop with Intel 5930K 3.50GHz CPU, a Macbook Pro Retina laptop with 2.6 GHz Intel i7 CPU and Android Nexus 5 and Nexus 6 devices. The results were pretty consistent.
If you wish to replicate the test, you might have to ensure the memory is out of the cache before running the loop because some compilers will cache the array on declaration. Read below to understand more on how it works.
What happens in the example is quite simply explained when you understand how the CPU accesses data. The CPU can’t access data in RAM; the data must be copied to the cache, a smaller but extremely fast memory line which resides near the CPU chip.
When the program starts, the CPU is set to run an instruction on part of the array but that data is still not in the cache, therefore causing a cache miss and forcing the CPU to wait for the data to be copied into the cache.
For simplicity sake, assume a cache size of 16 bytes for the L1 cache line, this means 16 bytes will be copied starting from the requested address for the instruction.
In the first code example, the program next tries to operate on the following byte, which is already copied into the cache following the initial cache miss, therefore continuing smoothly. This is also true for the next 14 bytes. After 16 bytes, since the first cache miss the loop, will encounter another cache miss and the CPU will again wait for data to operate on, copying the next 16 bytes into the cache.
In the second code sample, the loop skips 16 bytes at a time but hardware continues to operate the same. The cache copies the 16 subsequent bytes each time it encounters a cache miss which means the loop will trigger a cache miss with each iteration and cause the CPU to wait idle for data each time!
Note: Modern hardware implements cache prefetch algorithms to prevent incurring a cache miss per frame, but even with prefetching, more bandwidth is used and performance is lower in our example test.
In reality the cache lines tend to be larger than 16 bytes, the program would run much slower if it were to wait for data at every iteration. A Krait-400 found in the Nexus 5 has a L0 data cache of 4 KB with 64 Bytes per line.
If you are wondering why cache lines are so small, the main reason is that making fast memory is expensive.
The way to solve such performance issues is by designing your data to fit into the cache and have the program to operate on the entire data continuously.
This can be done by organizing your game objects inside Structures of Arrays (SoA) instead of Arrays of Structures (AoS) and pre-allocating enough memory to contain the expected data.
For example, a simple physics object in an AoS layout might look like this:
struct PhysicsObject { Vec3 mPosition; Vec3 mVelocity; float mMass; float mDrag; Vec3 mCenterOfMass; Vec3 mRotation; Vec3 mAngularVelocity; float mAngularDrag; };
This is a common way way to present an object in C++.
On the other hand, using SoA layout looks more like this:
class PhysicsSystem { private: size_t mNumObjects; std::vector< Vec3 > mPositions; std::vector< Vec3 > mVelocities; std::vector< float > mMasses; std::vector< float > mDrags; // ... };
Let’s compare how a simple function to update object positions by their velocity would operate.
For the AoS layout, a function would look like this:
void UpdatePositions( PhysicsObject* objects, const size_t num_objects, const float delta_time ) { for ( int i = 0; i < num_objects; ++i ) { objects[i].mPosition += objects[i].mVelocity * delta_time; } }
The PhysicsObject is loaded into the cache but only the first 2 variables are used. Being 12 bytes each amounts to 24 bytes of the cache line being utilised per iteration and causing a cache miss with every object on a 64 bytes cache line of a Nexus 5.
Now let’s look at the SoA way. This is our iteration code:
void PhysicsSystem::SimulateObjects( const float delta_time ) { for ( int i = 0; i < mNumObjects; ++i ) { mPositions[ i ] += mVelocities[i] * delta_time; } }
With this code, we immediately cause 2 cache misses, but we are then able to run smoothly for about 5.3 iterations before causing the next 2 cache misses resulting in a significant performance increase!
The way data is sent to the hardware matters. Be aware of data-oriented design and look for places it will perform better than object-oriented code.
We have barely scratched the surface. There is still more to data-oriented programming than structuring your objects. For example, the cache is used for storing instructions and function memory so optimizing your functions and local variables affects cache misses and hits. We also did not mention the L2 cache and how data-oriented design makes your application easier to multithread.
Make sure to profile your code to find out where you might want to implement data-oriented design. You can use different profilers for different architecture, including the NVIDIA Tegra System Profiler, ARM Streamline Performance Analyzer, Intel and PowerVR PVRMonitor.
If you want to learn more on how to optimize for your cache, read on cache prefetching for various CPU architectures.