Mark L. Murphy's Blog, page 30

April 30, 2018

scrcpy for Projecting Your Android Screen

When delivering presentations about Android, a frequent challenge is: how do I
get the audience to see what���s on a device���s screen?



In the beginning, we had two options:





Use the emulator, which back in the early days of Android was ARM-only and
very slow




Use a hardware projector (e.g., an ELMO), which were hard to find





In 2009, to help with this, I created DroidEx.
This has long been relegated to
the dustbin of history, outside of this fork.
DroidEx used the same protocol that adb uses for screenshots (e.g., from inside
Android Studio), just pushing the screenshots into a desktop window. It was
slow (~6 fps), but it worked.



Later, Jens Riboe took the DroidEx concept and created Droid@Screen,
with a better desktop UI. And that���s what I used for years for presentations���
until very recently.



If you can demo using an Android 5.0+ device, use scrcpy,
by Romain Vimont and Genymobile.



This uses a little H.264 server, pushed over onto the device, which the client
then plays back. This offers much better performance (30-60 fps). I even accidentally
demonstrated an Android device playing back video, and scrcpy handled it flawlessly.
It is as simple to use as was Droid@Screen ��� just run the scrcpy command
to push over the server bit, start it running, and launch the client UI. The
client UI even accepts input and forwards it to the device, so you can control
the hardware from your notebook.



If you are delivering presentations with Android demos ��� sales, conference
presentations, training, etc. ��� and you have a case where an emulator is
insufficient, scrcpy should be in your toolbox.

 •  0 comments  •  flag
Share on Twitter
Published on April 30, 2018 04:57

April 9, 2018

Manifest Merger, maxSdkVersion, and a Missing Permission

Manifest merger is a wonderful thing in Android app development��� usually.
It allows libraries to contribute elements and attributes automatically to
an app���s manifest, saving the app developer from adding those things
manually.



However, sometimes, it will not work in an intuitive fashion.



Such appears to have been the case for a developer, who posted
this Stack Overflow question,
outlining some curious symptoms. Despite having a <uses-permission> element
for WRITE_EXTERNAL_STORAGE, when he would request it at runtime, he would
never get it. In fact, if he did not also ask for READ_EXTERNAL_STORAGE,
Android would not even bother asking the user about the runtime permission.



This symptom ��� calling requestPermissions() and being rejected outright ���
sometimes is caused by the user having clicked ���Don���t ask again��� for the permission.
However, it can also occur if your manifest lacks the <uses-permission> element���
but that did not appear to be the case here.



Until the developer checked the merged manifest.



Something ��� I assume a library ��� was adding android:maxSdkVersion="18"
to WRITE_EXTERNAL_STORAGE. Presumably, the library is writing to getExternalFilesDir()
and needs this permission on older devices, but not newer ones. However, the
app needed the permission for all versions, as the app is writing elsewhere
on external storage. maxSdkVersion causes the <uses-permission>
element to vanish, in effect, on newer devices. That���s why runtime permissions
were not working. Even though the app had the <uses-permission> element,
the library���s contributed maxSdkVersion negated it for newer devices.



The fix for the app developer was to add tools:remove="android:maxSdkVersion" to
that <uses-permission> element, to block the maxSdkVersion attribute and allow
the permission to be requested on all devices.



From the standpoint of the library author, though, this is a case of ���being caught
between a rock and a hard place���. If you include maxSdkVersion, you correctly
advertise your library���s needs and you minimize the permissions that your library
contributes to the app. However, for dangerous permissions, it violates
the Principle of Least ���WTF?���
for app developers using the library. If you do not include maxSdkVersion,
you cause fewer problems for app developers who need the permission all the time,
but you may wind up requiring the permission in cases where it is not needed.



My guess is that WRITE_EXTERNAL_STORAGE is the #1 permission for use with
maxSdkVersion. If your library requests this permission, think about whether
maxSdkVersion is appropriate for your use case��� and then document your requirements.
In particular, if you use maxSdkVersion, make sure that your documentation
mentions this and prompts library users to add deal with this if their apps
require the permission for more API levels.



Developers using libraries should peer at the Merged Manifest tab of Android Studio
from time to time, to see what���s in there and tailor the results via tools:
attributes as needed.



With a bit two tons of luck,
we might get more information when this occurs in LogCat.

 •  0 comments  •  flag
Share on Twitter
Published on April 09, 2018 04:47

April 2, 2018

"Exploring Android" Version 0.2 Released

Subscribers now have
access to an update to Exploring Android,
known as Version 0.2, in PDF, EPUB, and MOBI/Kindle formats. Just log into
your Warescription page and download
away, or set up an account and subscribe!



Exploring Android is a collection of tutorials, to build up an Android
app from scratch. Version 0.2 adds 10 more tutorials, for a total of 30.
These new tutorials:





Migrate the app to use a formal GUI architecture pattern, specifically
Model-View-Intent (MVI)




Persist the data we collect in the app to a SQLite database, using Room





The next update is tentatively slated for mid-May.

 •  0 comments  •  flag
Share on Twitter
Published on April 02, 2018 05:08

March 27, 2018

Chrome OS Tablets, And Your App

Yesterday, Acer officially announced the first Chrome OS tablet,
the Acer Chromebook Tab 10. As with all newer Chrome OS devices, the Chromebook Tab 10
will run Android apps��� perhaps including yours.



Many Android developers have been avoiding Chrome OS, arguing that it is a fairly
fringe audience. And it is true that Android-capable Chrome OS devices make up
perhaps 1% of the Android device ecosystem. However, by default, your app ships
to Chrome OS devices, and blocking such distribution is not necessarily
straightforward. Hence, you really need to consider adding Chrome OS to the
lineup of test environments that you exercise your app on, as while Android
on Chrome OS is a remarkable achievement, things are a bit different than what
you may be used to. If Google makes a renewed tablet push
using Chrome OS, the percentage of Chrome OS devices may climb a fair bit.



Some Android developers who embraced Chrome OS may have been thinking that
keyboards were always part of the Chrome OS experience. This tablet indicates
otherwise.



That���s why, on the whole, it is best not to think of particular devices, but rather
particular features:





Supporting keyboards is not a Chrome OS thing, as keyboards have been an option
before (Pixel C, various Bluetooth keyboards)




Supporting freeform multi-window is not a Chrome OS thing, as we also see them
with Samsung DeX (and perhaps future environments)




Assumptions that you might make regarding available hardware, such as GPS or
rear-facing cameras, are not tied to Chrome OS, but could vary on any sort
of device





In these cases, while a Chrome OS device is a great testbed for how your app
handles such things, you are not supporting Chrome OS by handling keyboards and
such ��� you are supporting Android, and Chrome OS happens to be an environment
for testing that support.



It remains to be seen whether Chrome OS will jump-start the tablet form factor with
respect to Android. However, this is another sign that Chrome OS is here to stay,
and Android developers really need to take it into account, since your app may
be running on Chrome OS devices right now.

 •  0 comments  •  flag
Share on Twitter
Published on March 27, 2018 04:44

March 26, 2018

The Busy Coder's Guide to Android Development Version 8.11 Released

Subscribers now have
access to the latest release of The Busy Coder���s Guide to Android Development,
known as Version 8.11, in all formats. Just log into
your Warescription page and download
away, or set up an account and subscribe!



Principally, this update adds ~30 pages on Android P, based on Developer Preview 1.
This is a lot less than I was hoping for, because many things in Android P do
not work (e.g., HTTPS requirement, WebView tracing, directory access settings,
FOREGROUND_SERVICE permission) or are still very nascent (e.g., slices). Future
book updates will cover more of this, as these features stabilize.



Beyond Android P, this update:





Updates the chapter on Android Things for the DP7 release




Updates the chapter on ACRA to cover version 5.1.1




Updates many samples to use the Support Library edition of fragments,
in lieu of the native fragment implementation




Updates the chapter on the fused location api to cover
the newer API for getting location updates




Updates the Maps V2 samples to their newer API




Replaced all references to ���Android Wear��� with ���Wear OS���, to reflect the
branding change




Removes three elaborate examples, with an eye towards moving them to
Android���s Architecture Components
(after a substantial rewrite):





the dynamic tab sample from the chapter on advanced RecyclerView techniques




the TinyTextEditor sample from the chapter on consuming documents




the document mode sample from the chapter on tasks






Removes the chapter on the percent library, which has been deprecated
and supplanted by ConstraintLayout




Removes the chapter on implementing a nav drawer, pending some future
rewrite




Fixes a variety of errata





If you���re wondering about the naming convention, this book will hit 9.0
sometime later this year, once Exploring Android
covers enough of Android. At that time, I will retire the EmPubLite series of tutorials
and start the 9.x numbering series.



The next update to this book depends a lot on what Google does. If I had to guess,
I will not update this book until shortly after Google I|O 2018. However, if
Google ships a substantial Developer Preview 2 in April, I may push out an update
to this book sooner.

 •  0 comments  •  flag
Share on Twitter
Published on March 26, 2018 04:41

March 20, 2018

About the Potential Android P App Ban

Late last year, Google mentioned that:




Future Android versions will also restrict apps that don���t target a recent API level and adversely impact performance or security.




Friday, Android Police pointed out
something that I had missed: apps with a targetSdkVersion below 17
will get a warning dialog when they are first run on an Android P device.
Plus, the documentation for that minimal-accepted targetSdkVersion
mentions:




Applications targeting lower values will fail to install and run.




Let���s assume that the JavaDocs are correct, and so the ���restrict��� from my first
quote above really means ���ban���. So, for the developer previews, we just get
the warning dialog, but that the final version of Android P will block such
apps from being installed or run. This is on top of the Play Store���s already-scheduled
ban on new apps and updated apps that use older targetSdkVersion values.



Let���s talk about the ramifications of this, in the form of winners and losers.



Winner: Active Developers

Clearly, Google is trying to winnow out older apps, and that benefits
developers who are continually investing in their apps. For developers focused
on publicly-distributed apps in the Play Store, the primary driver for this will be the Play
Store ban, more so than the Android P ban. But, there are other ways of distributing
apps, and those channels may be limited more by an Android P ban.



Loser: Small Organizations

Historically, the vast majority of money for software purchases was not
spent on packaged software, but instead were for custom-developed pieces of software, usually in
support of some organization: a business, a government, a non-profit, etc.
Some of that custom development is now devoted to mobile, and those apps
are privately distributed by one means or another.



While many organizations are used to software obsolescence, they expect that to be
on fairly large time frames. I distinctly remember helping a firm in the early
2000���s keep a 16-year-old MS-DOS program running on Windows XP, for example.
The idea that a piece of software developed five years ago might stop running
because Google decided that it should stop running is not going to go over very well.



Larger organizations frequently are better equipped to try to do periodic maintenance on
apps to avoid such bans. Smaller organizations may lack the budget to
keep tinkering with an app just to make Google happy.



Winner: Web Developers

The solution is a fairly simple formula:





If you are willing to invest annually in an app, feel free to make Android apps




Otherwise, write a Web app





Web apps have their issues, to be certain. However, you are less dependent upon
Google infrastructure and Google decisions. For example, even if Google decides that Chrome
will no longer display Web pages written over five years ago, there are other
Web browsers.



Loser: Users

Probably I have fewer apps on my personal Android device than you do.



But some of the apps that I use might not run on Android P, such as the app
that I can use to track my blood pressure and the app that I use for its NYC subway
map. Are there alternatives? Sure. But I happen to be aware of this impending
change and might be able to migrate to some other app.



What happens to users if they get an upgrade to Android P, which then refuses
to run some of their installed apps?



If the ban is only imposed on newly-installed apps��� what does that say about
the stated rationale for the ban (���adversely affect performance or security���)?
Do existing installed apps somehow not adversely affect performance or security,
where a fresh install of the same app would?



Winner: App Repackagers

I expect a cottage industry to arise where people will skills in decompiling
and recompiling Android apps start distributing versions of apps that have
their targetSdkVersion raised to a level that avoids these bans. Whether those
repackaged apps will work ��� and whether they contain malware ���
remains to be seen. But, some people will want some of these older apps and will
be willing to turn to unconventional sources to get them.



Winner: Regulators

For anyone worried about Google���s power, these bans become yet another lever
to pull to try to convince regulatory bodies that Google���s behavior should
be curtailed. There will be a variety of aggrieved parties who can point out
how their organizations were harmed by these bans.



Loser: Google

These bans play right into the issues that
Steve Yegge outlined last week.
Google deciding to drop support for certain Android apps adds a risk factor to developing
Android apps in the first place. Avoiding these or future bans requires either abandoning
native development or ensuring that continuous native app maintenance is super cheap.
���Super cheap��� is unlikely to be traditional Java-based development, or even
Kotlin-based development.



That, plus the regulation concerns, means that it is unclear how Google comes
out ahead from this. Yes, they will be able to retire some amount of legacy logic. Is
it worth it?



Alternative Scenarios

Perhaps all Android will do, at least for Android P, is show the ���this app is
damn old��� dialog, but will still allow the app to run ��� the behavior that we
see today in the developer preview. There is still risk
to Android app development that Google is introducing, but it will have less immediate impact,
since everything will still run as it had before.



Perhaps Android P will show that dialog, then treat the app as having a targetSdkVersion
of 17, even if the manifest declares something lower. This would allow the app
to try to run while stopping it from ���adversely affect[ing] performance or security���.
Some apps might fare just fine. Others might fail spectacularly. But even if less
than 100% of the apps work, that is better than 0% of the apps working because Android P
refuses to run them.



Perhaps this is a ���trial balloon��� and Google will revert all of this before Android P
ships in final form.



This fall, we will know for certain what the shipping Android P will do and how
it compares to what we see today.



And if you���re reading this blog, probably you are an active developer, and
probably you are keeping your targetSdkVersion close to current, and so
probably neither of these bans will affect you directly. Unless you use Android
apps, in which case, you may have problems.



Which reminds me��� perhaps I should hold off checking my blood pressure for a bit���

 •  0 comments  •  flag
Share on Twitter
Published on March 20, 2018 08:10

March 9, 2018

REQUEST_DELETE_PACKAGES, For Realz Now

One of the changes announced for Android 8.0 was that apps needed to hold
the REQUEST_DELETE_PACKAGES permission to be able to delete apps
using ACTION_UNINSTALL_PACKAGE, once their targetSdkVersion rose to 26 or higher.



It didn���t work, as apps
could use ACTION_UNINSTALL_PACKAGE even without holding this permission.



Now, on P Developer Preview 1, this actually works as (currently) documented. Once your
app has a targetSdkVersion of 'P' (or, presumably, 28 or higher), you
need to have a <uses-permission> element for REQUEST_DELETE_PACKAGES
in order to be able to use ACTION_UNINSTALL_PACKAGE. Without it, you get
an error in LogCat:



E/UninstallerActivity: Uid 10145 does not have android.permission.REQUEST_DELETE_PACKAGES or android.permission.DELETE_PACKAGES


Note that this error does not come from your process, so it will not show
up in LogCat if you are filtering for the selected app. There is no exception
thrown, either ��� from your app���s standpoint, your startActivity() call is
just fine. However, the user is not presented with the ���do you want to uninstall
this app?��� dialog.



REQUEST_DELETE_PACKAGES is a normal permission, so you do not need to mess
around with runtime permissions to hold it.



So, if you use ACTION_UNINSTALL_PACAKGE (or equivalent methods), you���ll need
to add a line to your manifest for it to keep working.

 •  0 comments  •  flag
Share on Twitter
Published on March 09, 2018 12:45

March 8, 2018

Random Musings on the P Developer Preview 1

Each time Google releases a new developer preview, I rummage through
the API differences report
and the high-level overviews,
to see if there are things that warrant more attention from
developers, with an emphasis on mainstream features that any developer
might reasonably use. I also tend to emphasize things that may not
get quite as much attention, because they are buried in the JavaDocs.



As with Android O, Android P seems to be lacking a signature user-facing feature.
It even lacks what I would consider to be a signature developer-facing feature.
P, at least in the first
developer preview, is an incremental advance. This might represent maturation
of the platform, a focus on cleaning things up in preparation for future versions
of Android, or changes in staff allocation emphasizing other Google projects. It might
also be ���sandbagging���, with signature features showing up in future developer
previews.



That being said, there are a number of things that I found curious and interesting.



AppComponentFactory

Usually in these ���random musings��� posts, I have something that scares me. Occasionally,
I have lots of things that scare me. Fortunately, this is a fairly mild release, and
while these are early P days, I���m not scared yet.



However, AppComponentFactory is going to be a double-edged sword.



You can define a subclass of AppComponentFactory and register it in the
manifest in the <application> element. Then, whenever the framework
needs to create an instance of an Activity, Application, ContentProvider,
BroadcastReceiver, or Service, your AppComponentFactory will be asked
to do that work. You are given a ClassLoader, the String of the component name
that appeared in the manifest, and an Intent (for Activity, Service,
and BroadcastReceiver). Your job is to return the desired object. It would
appear that you could chain to the superclass for those components that
you do not want to handle differently, allowing you to focus on the scenarios
where you want to do something different than what the framework normally does.



Let���s use an Activity an an example. Normally, when the user taps the
home screen launcher icon, Android creates an instance of the designated
Activity subclass using the zero-argument public constructor. However,
if the app has a registered an AppComponentFactory and overrides the
instantiateActivity() method, that will be called, and it needs to return
the Activity.



For example, instantiateActivity() could:





Use some other sort of constructor, perhaps involving dependency
injection




Have a generic placeholder <activity> element, and decide in Java code
what the actual Activity will be, by using other information in the
Intent and perhaps other state information in the app




Create some sort of ActivityWrapper that wraps the real Activity
subclass, where the wrapper can do logging and such, forwarding all
calls onto the wrapped Activity





And so on. Hence, this capability could be useful for a variety of scenarios.



However, it certainly simplifies the implementation of certain types of malware
and crapware. Now I don���t even need to mess with the existing code. All
I need to do is:





Create and register an AppComponentFactory that overrides instantiateActivity() (or
whatever) to put my own wrapper around the app���s real component




Ship the altered app by whatever my preferred distribution channel is




Get results from my wrappers (e.g., report everything the user
types in, slap ad banners over the UI, replace the app���s own ad banners
with my own)





So, app repackagers will be all over this. Right now, that���s probably a
semi-manual process; this change makes it easier to automate. So, with the
good, we also get the bad.



This facility first came to my attention from Mishaal Rahman of XDA-Developers.
It existed in some Android 8.0 builds, and possibly Android 8.1, as hidden
APIs on Application, rather than through this separate AppComponentFactory
class.



Changes You Should Pay Attention To

Some deprecations that I pointed out earlier ��� such as
accessing hidden APIs and
device admin policy changes,
do appear to be coming to fruition. In particular, libraries that you use
might be using some hidden APIs, even if you are not. Keep a close eye on your
dependencies and upgrade them as appropriate.



Also, a rumored change has come to pass: the framework Fragment- and Loader-related
classes are deprecated. This is a nudge to get you to use the ones from the Support
Library, for consistent implementations across device versions. Note that there
are not direct analogues for everything in the Support Library (e.g., no WebViewFragment).



Once you set your targetSdkVersion to P (or, eventually, 28?), you will be
forced to use https by default. Attempts to use http URLs will result in
an exception. If you still need access to unencrypted Web content, you will need to
opt into that behavior.



Also, once you set your targetSdkVersion to P, you need to request
a new FOREGROUND_SERVICE permission.
This is a normal permission, so you just need the <uses-permission> element
in the manifest. It is not really clear why they introduced this, but it is something
that you will need. OTOH, this seems to be the only change related to the
years-old ���War on Background Processing���, so perhaps we have turned the corner
on that subject.



If you have ancient instrumentation tests, they may break, until you either
update them to use JUnit4 or you opt into the legacy testing library.



Android 7.0-8.1 stopped requiring FLAG_ACTIVITY_NEW_TASK. I pointed out this
flaw ~18 months ago, and again
a year ago. Much to my shock
and amazement, this has been addressed with P, and so
you need that flag again
when starting an activity from a non-activity Context, such as from a Service
or BroadcastReceiver. This returns us to the behavior from Android 6.0 and
older OS versions, and so you probably already have this flag, unless your
minSdkVersion is 24 or higher.



While there are many other behavior changes, those seem to be the ones that are likely
to affect the most developers.



Stuff That Needs More Explanation

Android P has slices of��� something. There is a whole family of classes
related to this, including
SliceManager and
SliceProvider.



The JavaDocs for SliceProvider has:




A SliceProvider allows an app to provide content to be displayed in system spaces. This content is templated and can contain actions, and the behavior of how it is surfaced is specific to the system surface.




However:





It is unclear what ���system spaces��� and ���system surfaces��� refer to (lockscreen?
notification shade? something else?)




The JavaDocs for Slice and the release notes for 28.0.0-alpha1 Support Library
suggest that the content is app-to-app, not app-to-system-surface





So, there may be something cool here, but the documentation is really scant on the subject.



Also, Activity, Dialog, and View (at minimum) have a new requireViewById()
method. This works just like findViewById(), but it throws an exception when
there is no View matching the ID, instead of returning null. It is unclear
where and why we would use this.



In addition, there is a StatsLog class
that ���provides an API for developers to send events to statsd���. It is unclear
what this means or why we would use it.



You can now attach a ���semantic action��� to a Notification.Action, such as indicating
that this action will delete something, archive something, ���thumbs up��� something, etc.
It is unclear if this will be used for accessibility or if it has some other role.



Stuff That Seems Intriguing

We now have a Magnifier
that we can attach to a widget. Presumably, it embiggens things.



There is a static disableWebView() method on WebView, which tells Android
to not allow any WebView use in this process. If you have a multi-process app,
and you know that some of your processes do not use WebView, calling this will
prevent you from accidentally loading WebView and incurring the memory overhead.
However, it does this by throwing an exception, so this may be the sort of thing
that you only use in debug builds for tracking down unexpected WebView usage.



StrictMode now offers callbacks. For any violation, you can have a listener
called on an Executor that you supply. Your listener is handed a Violation
object, which is a subclass of Throwable. Hopefully (presumably?) this
Violation is generated at the point of the bad code, so you can examine
the stack trace and decide what to do. This may make it possible to create
more advanced StrictMode reporting tools, including tying them into your
existing crash logging system.



WebView offers a TracingController that can be used to ���enable/disable tracing for parts
of code and to collect tracing data���. You get a JSON block back, designed for
use with chrome://tracing in your favorite Web browser whose name starts
with ���Chrom���.



Apps can now find out what autofill service the user has chosen, if any, via
.
This would be useful if your app wants to have a whitelist of trusted autofill
services that you are willing to use, blocking autofill if the user chose one
that you do not recognize.



Other Stuff Worth Noting

An AccessibiltyService can now
take screenshots
on behalf of the user.



The API differences report will note things being removed that do not appear
to be removed. For example,
the differences report indicates that a bunch of methods were removed
from AbstractCursor.
Those methods are still there in the full JavaDocs.



There is a new Settings action (ACTION_STORAGE_VOLUME_ACCESS_SETTINGS)
to take the user to a screen listing the removable media on the device and
which apps have access to that media. In particular, if the user denied
your app access to the removable media, and clicked ���Don���t ask again��� on the
dialog, sending the user to the Settings app is the only way your app will
ever get access to that storage volume.



Apps can now help the user enroll a fingerprint, via ACTION_FINGERPRINT_ENROLL.



The change to yet another APK signing system means that there are new APIs
and deprecations if you check signatures at runtime. The former signatures
field on PackageInfo is replaced with signingCertificateHistory, which has
details about signing key revisions.



Also, the versionCode is moving from an int to a long, as apparently
232 app versions weren���t quite enough.



In addition to regular KeyEvent processing in a View, there is now the notion
of a ���fallback���, in the form of onKeyFallback() and addKeyFallbackListener().
If the regular KeyEvent processing does not consume the event, any fallbacks
are tried, before the KeyEvent is handed to the window callback. It is not
completely clear where this would be useful, other than serving as a low-priority
handler of some KeyEvent (i.e., if somebody else wants the event, have it, otherwise
I will use it).



You can call getMainExecutor() on Context to get an Executor that will
execute its jobs on the main application thread. There are other ways of accomplishing
this, using Looper and a custom Executor implementation, but this is simpler.



JobInfo.Builder has a few new options:





setEstimatedNetworkBytes() provides a hint for how much bandwidth should be
needed to execute this job. The idea is that jobs needing a lot of bandwidth
may be postponed when the device has a lousy network connection, as excessive
retries may chew up the battery.




setImportantWhileForeground() is strange. Based on the docs, it appears as
though it will relax some of the restrictions imposed by Doze mode, if your app
happens to be in the foreground at the time of the job. I guess this includes
cases where the screen is off and your app was the last one to be in the foreground.
Otherwise, if the screen is on and you are in the foreground, there should be no
Doze restrictions in the first place.




setIsPrefetch() indicates that this job is pre-fetching some data for the
user. JobScheduler may adjust your job���s timing as a result, either to invoke it
as part of launching your UI (e.g., if the user clicks on your launcher icon) or
if there is a lot of spare bandwidth (even if that bandwidth is metered and you
ordinarily try to avoid metered data).




setRequiredNetwork() allows you to spell out the details of what sort of
network connection that you need, based on capabilities and transport
types, as defined by a NetworkRequest.





Where I Go From Here

Over the next several days, I will be putting Android P through its paces, in part
by testing and re-raising a bunch of issues that probably haven���t been addressed yet.



An update to The Busy Coder���s Guide to Android Development, with
coverage of Android P, should be out by the end of the month, if not sooner.

 •  0 comments  •  flag
Share on Twitter
Published on March 08, 2018 08:40

March 5, 2018

Upcoming Device Admin Deprecations?

TL;DR: If you use the device admin APIs on Android (e.g., DevicePolicyManager),
keep a close eye on the upcoming Android P release, as parts of that API may
be deprecated, with an eye towards elimination in the Android Q timeframe.



One of the reasons that I help out on Stack Overflow is that reviewing questions
is a bit like panning for gold ���
you never know what you might find, and occasionally some of it is useful.



Today���s bit of gold points to
this piece of Android EMM documentation,
where Google attempts to explain some upcoming changes to the device admin API.
I say ���attempts��� because the
explanation raises almost as many questions as it provides answers.



What seems clear is that four policies that you might be requesting for use
from your device admin app are going to be marked as deprecated in Android P
and ���will throw a SecurityException��� in Android Q:





Blocking camera access (USES_POLICY_DISABLE_CAMERA)




Disabling certain unspecified keyguard features (USES_POLICY_DISABLE_KEYGUARD_FEATURES)




Forcing the user to reset their password after an admin-defined time period (USES_POLICY_EXPIRE_PASSWORD)




Forcing the user to use passwords meeting certain quality guidelines, such
as minimum length (USES_POLICY_LIMIT_PASSWORD)





In some cases, there appears to be replacement behavior in the APIs surrounding
work profiles and managed devices. In other cases, there may not be ��� for
example, the Stack Overflow question
is inquiring about how to block camera usage. With luck, Android P documentation
will provide clear and unambiguous instructions for how to replace use of these
deprecated features.



The Android EMM documentation specifies three policies that will be kept intact:





Locking the device (USES_POLICY_FORCE_LOCK)




Resetting the password (USES_POLICY_RESET_PASSWORD)




Wiping the device (USES_POLICY_WIPE_DATA)





This leaves two policies unaccounted for:





Requiring encrypted device storage (USES_ENCRYPTED_STORAGE)




Monitor failed login attempts (USES_POLICY_WATCH_LOGIN)





Also, the documentation does not address capabilities in DevicePolicyManager that are not
tied specifically to those sorts of policies yet seem to be available to
active device administrators (e.g., setLongSupportMessage()). Plus, for the
deprecated items, it is unclear exactly when the SecurityException would
be thrown in Android Q:





At install time?




On first run of the app?




When the user attempts to activate the device administrator app?




When the app attempts to use the affected DevicePolicyManager APIs?





(I presume the solution is the latter, but stranger things have happened.
Also, Stranger Things have happened.)



There is always the possibility that this documentation is incorrect, for any
number of reasons, such as:





The plan is still there, but execution was delayed by a full release




The plan is still there, but execution was delayed until a maintenance release
(e.g., a P MR1 that might come out late this year)




The plan was scrapped for various reasons




The documentation understated the situation, and more device admin capabilities
will be affected, or the one-year deprecation period will be reduced or dropped





So, if you use the device admin APIs, when Android P ships, head to the ���Behavior Changes���
portion of the release notes and see what changed that will affect your
app.

 •  0 comments  •  flag
Share on Twitter
Published on March 05, 2018 04:59

March 1, 2018

The @hide Penny Drops

As XDA Developers originally reported,
and as I covered ~6 weeks ago,
Google is going to start
blocking your ability to access classes and members marked with the @hide pseudo-annotation,
as part of Android P (Pretzel? Pumpernickel? Pumpernickel Pretzel?).



They indicate that this will be a phased rollout, stating
that ���Initially, this restriction will impact interfaces with low or no usage���.
So, right now, we do not know exactly what will and will not be blocked.
My guess is that they will roll out these restrictions over 2-3 releases.



The upcoming developer preview is supposed to offer warnings when you are
using ���a non-SDK interface that will be subject to blacklist or greylist in the final release���.
That will tell you the stuff that you really need to fix quickly, lest your
code start to fail outright on Android P devices.



However, I do not recommend that you wait around for the developer preview.



Developers should start examining their code bases for any signs of using
reflection to access hidden members: Class.forName(), getConstructor(),
getField(), and so on. This is particularly important for library authors,
as issues with a library get amplified by the number of library users.



The big reason is that Google has set up a dedicated issue tracker component
for requests to make formerly-private APIs public. The results of filing issues
on the issue tracker can be generously described as ���mixed���. However, what has
become clear is that Google does not make changes to a release once the first developer
preview has shipped, outside of egregious problems. So, if you want some APIs
to be made public for 2019���s Android Q, you had best
get those requests filed
quickly, so that they can get in the pipeline. Plus, if it happens that your
desired API collides with a plan for Android P���s ���blacklist or greylist���, the
faster that you get your request into the system, the more likely it is that
it will have a positive effect.



Note that not all uses of reflection will need to result in changes in Android P.
Of note:





Using reflection for accessing your own code is fine, if perhaps heavyweight




Using reflection for accessing things on older devices, where newer devices
have some official solution, will not change based on Android P���s release ��� while
this is still risky, the risk is not any greater now than before




Using reflection for accessing manufacturer-supplied libraries ��� the kind that
you need to use <uses-library> for in the manifest ��� should be unaffected
by this change





Once a developer preview of Android P is released, hopefully we can work out a
list of the affected hidden items that are on the ���blacklist or greylist���.



So, a partial ban on @hide is real, and its results may be spectacular��� in terms
of the amount of wailing and gnashing of teeth that we will see on Stack Overflow.
The sooner you come to grips with how it will affect your app, the better off
you will be.

 •  0 comments  •  flag
Share on Twitter
Published on March 01, 2018 07:34