Android Developers Office Hours - EMEA


Uploaded by androiddevelopers on 12.12.2012

Transcript:

NICK BUTCHER: A little later than advertised, you are
joining an Android Developers Office Hours.
So we're coming to you live from London.
And my name is the Nick Butcher, and I'm joined by--
MATT GAUNT: Matt Gaunt.
RICHARD HYNDMAN: Hey, and I'm Richard Hyndman, also from the
Android Developer Relations team.
NICK BUTCHER: So this your opportunity to talk to us
about all things Android dev.
And as always, this is not an opportunity to talk about
unreleased products, when is x feature going to launch?
Why is Rich and Matt sharing headphones like they're
teenagers on the bus?
MATT GAUNT: Are you giggling?
NICK BUTCHER: Those topics will not be discussed.
But otherwise, yeah.
Come along and ask us all things Android.
Yeah, so it looks like we're joined by a couple of regular
watchers, who we've got in the Hangout live.
Say hello.
AL SUTTON: Hey guys, it's Al.
MATT GAUNT: Hey Al, how's it going?
Mr. Sutton.
NICK BUTCHER: Who else do we have?
[INAUDIBLE]
RICHARD HYNDMAN: Peter?
Peter Brooks there, I think, and [INAUDIBLE].
Nice to see you all.
Thanks for joining.

All right, then.
I'd better go and mute [INAUDIBLE].

NICK BUTCHER: So is there any news?
Anything in the news at the moment that we
want to talk about?
Exciting Android developments?
RICHARD HYNDMAN: Something since Maps [INAUDIBLE]?
AL SUTTON: [INAUDIBLE]
API.
RICHARD HYNDMAN: I'm still just, like, up here on the
fact that Android apps can have awesome maps
in them right now.
NICK BUTCHER: So yeah, Billing V2 has launched.
Has anyone had a chance to look at the new, streamlined,
easier way to make in-app payments?
RICHARD HYNDMAN: I have.
MATT GAUNT: Yep.
I've been playing with it.
RICHARD HYNDMAN: Matt's been playing with it, as well.
NICK BUTCHER: What do you think of it?
Much improved?
MATT GAUNT: Yes.
NICK BUTCHER: Many, many fewer lines of code to implement.
MATT GAUNT: Yeah.
Much, much simpler, much, much easier.
Training's really good as well.
Yeah.
RICHARD HYNDMAN: You can do the whole thing in 50 lines of
code now, which isn't too bad.
NICK BUTCHER: There's been a lot of the feedback I've
heard, that the developers love the kind of monetization
opportunities it affords them but find it hard to implement.
RICHARD HYNDMAN: In the old version.
NICK BUTCHER: In the old version-- the old version.
RICHARD HYNDMAN: And you can finally request the pricing
information from the Play store.
So inline inside your application, you can say, buy
a sword for $0.99.
And when you put sales on in the Play store, it just comes
down to your application.
NICK BUTCHER: Yep.
You don't have to synchronize a change to your SKU price
list with an update to your app and hope the
user gets the update.
So the app can see the right price.
It's much simpler.
RICHARD HYNDMAN: Hopefully that reduces the number of
cancellations as well, because they can see the price in your
app before going through to the Play store and finding out
the cost of the in-app item.
OK.
I haven't checked today's moderator out, but I'm sure we
have some questions on it.
NICK BUTCHER: Are there any questions from people in the
Hangout, before we jump into the moderator?
AL SUTTON: I've got one, but I don't know whether you guys
can actually answer it.
It's based on the new Android tools.
There's a new license term.
AUDIENCE: I've got a question.
AL SUTTON: They can't be used for doing
fragmentation of Android.
Is there any guidance on what would be considered
fragmentation?
NICK BUTCHER: Say that again.
There was a lot of noise during the middle of that.
Would you mind repeating?
AL SUTTON: Sure.
The new Android toolkit for, I think it's for 4.2, has a
clause in the license that says it can't be used for
anything that would contribute to fragmentation.
Is there anywhere that we can get guidance on what would be
considered fragmentation and what's not?
NICK BUTCHER: So you're talking about the Terms Of
Service, which sounds like it's a lot like a voyage into
lawyer land, which I am not qualified to make any kind of
a judgment upon.
It's a good question, though.
So that was the change in the Terms of Service you agreed to
when you updated ADT, right?
AL SUTTON: Yeah, those ones.
NICK BUTCHER: I don't know.
Have you posted this in the tools development forum?
AL SUTTON: I have, and there was a discussion in the tools
development.
Because if you build the tools from the Open Source Project
you're, of course, not bound by the same license.
So there was a lot of to-ing and fro-ing on that.
But it's just, basically, looking for a definition of
what fragmentation means in that context.
NICK BUTCHER: Yeah.
Yeah, that's a good question, which unfortunately, I don't
think, any of us even know or are qualified to weigh in on,
unfortunately.
How could we get an answer to that?
I guess maybe we email the PM for that project and
try and find out?
RICHARD HYNDMAN: We could try.
Yeah.
NICK BUTCHER: Leave it with us.
We'll try and follow up on that for you.
AL SUTTON: Cool, thanks.
NICK BUTCHER: No problem.
Any other live questions in the room?
PETER BROOKS: A very quick one.
Well, I think very quick.
In terms of Google Play error codes, do you guys know, or
does anyone else know, these kind of 914 error codes which
we had yesterday throughout the entire market or 948?
They seem really kind of random, and we would love to
tell our users what's wrong with them
buying our apps, really.

NICK BUTCHER: All I know is that there was an outage at
some point, and it got resolved.
RICHARD HYNDMAN: Yeah, [INAUDIBLE] some payment--
PETER BROOKS: OK.
RICHARD HYNDMAN: --had been declined for
some reason or other.
It was showing the 914 error.
We had quite a lot of partners reporting it.
[INAUDIBLE].

PETER BROOKS: Right.
OK.
NICK BUTCHER: Yeah, as to is there anything, actually, you
can do in your app?
No, I don't think there's any.
We don't publish these error codes and advise any kind of
response to put to the user.
I'd say just catch them gracefully and say,
there was an error.
RICHARD HYNDMAN: We update the known issues page, as well.
If you do a Google search of Google Play developer known
issues, we work pretty hard making sure that page is
updated so at least you can show your users that it's our
problem, not yours.
PETER BROOKS: Right, OK.
RICHARD HYNDMAN: Cheers.
Thanks, Peter.
NICK BUTCHER: Is this the first Hangout
you're doing, Peter?
Have you been a lurker for a while, or first time joining?
RICHARD HYNDMAN: Don't ask people that.
PETER BROOKS: I lurked last week and only just found out
about it recently.
So I'll join you guys in the future.
RICHARD HYNDMAN: Cool.
NICK BUTCHER: Yep, spread the word.
RICHARD HYNDMAN: You're more than welcome.
AL SUTTON: We can post it in the Android developer's
community on Google+.
NICK BUTCHER: Yeah, we should.

We've got some more people seem to have
joined us, as well.
Who else have we got there?
RICHARD HYNDMAN: Yeah.
Hugo's joined in.
NICK BUTCHER: Ah.
Mr. Visser.
RICHARD HYNDMAN: And Giuseppe of course.
HUGO VISSER: Hi guys.
NICK BUTCHER: Hi.
MATT GAUNT: Hi there.
NICK BUTCHER: Hugo, I think you had a question in the
moderator, right?
HUGO VISSER: I actually had two.
But the most important one was the one that I already posted
on Google+ a while ago.
And it was a question about the voice recognition, the
streaming stuff.
I couldn't find any documentation on it, but what
I would like to do is what the Google Now app is doing is,
like, listen for a certain kind of word.
So I think the voice recognition could be useful
for that, but I'm not sure if I can start it in a sort of
streaming background way in my app.
NICK BUTCHER: There's no way to do it, really.
The only way you can do it is by throwing up
the recognition dialogue.
There's no kind of background recognition.
HUGO VISSER: AUDIENCE: OK, so it would also require a custom
IME or something like that?
NICK BUTCHER: Quite possibly.
I don't even know if you'd be successful that way.
I think the custom IME froze up the standard UI, right?
RICHARD HYNDMAN: It does.
Yep.
So you can either do fixed-length detection and
then process that and then go back [INAUDIBLE], procedures,
like check every 30 seconds and then cancel it and start
again, which is not ideal.
Or go with [INAUDIBLE], but then you're not going to know
when [INAUDIBLE].
HUGO VISSER: Yeah.
AUDIENCE: I agree.

RICHARD HYNDMAN: [? Predrag's ?] just come in.
[? MATT GAUNT: Predrag? ?]
RICHARD HYNDMAN: He's just come in from the Hangout post.
NICK BUTCHER: Cool.
Excellent.
And you had a second question, Hugo?
HUGO VISSER: Yeah.
But that's regarding the new billing API.
Just a confirmation.
I assume that in the new billing API, your old
purchases will also pop up, right?
Like if you have managed purchases.
RICHARD HYNDMAN: [INAUDIBLE] was compatible.
But new items that you should create now should be managed.
HUGO VISSER: Right.
Because I read some comments on Twitter
that something broke.
But I'm not sure what to think.
I thought, let's ask.
NICK BUTCHER: Yeah, I saw that as well, [? by Raoul. ?]
He said something broke.
HUGO VISSER: Yeah, he said that.
So I'm not sure what's going on there.
But from what I understand later, that he's still using
the older API, and that broke for him.
But I haven't noticed that in my app yet.
RICHARD HYNDMAN: So we shouldn't
have changed anything.
If you're still saying V1 or V2, it should still have V1 or
V2 functionality.
It's only as soon as you specify V3 that you'll get the
new functionality.
HUGO VISSER: Yeah.
OK, cool.

RICHARD HYNDMAN: Cool.
NICK BUTCHER: So are there any more live questions in the
room, or should we jump into the moderator?
AUDIENCE: I want to ask you why the Android is
the best over iOS?

NICK BUTCHER: So why should you develop for
Android rather than iOS?
AUDIENCE: Yeah.

NICK BUTCHER: I guess it's the world's largest software and
mobile operating system, is a pretty compelling reason.
I would say, if reach is important to you, then, that's
a good reason.
AUDIENCE: I have a good article if he wants to read.
RICHARD HYNDMAN: Yeah, stick it into the chat window.
AUDIENCE: Yeah, still getting the hang of this.
RICHARD HYNDMAN: It's OK.
Top-left corner, you should have a little Chat button, and
you can press it.
And the window will open up.
AUDIENCE: It's an article from three years ago, but it's
still pretty good.
RICHARD HYNDMAN: No, no.
It's exponentially more important.
NICK BUTCHER: What is it they say?
75% of all smart phones shipping run Android?
That's a pretty strong reason, I think.
RICHARD HYNDMAN: There's a lot of good reasons.
AUDIENCE: Yeah, the biggest reason for me is that you
don't need wait two, three weeks to
get your app in store.
RICHARD HYNDMAN: Yeah, but that's [? not for ?]
publication.
AUDIENCE: It's especially crazy if you want to publish
up the existing app.
You know, like Apple's App Store, there are people that
abandoned their app, because Apple [INAUDIBLE].
NICK BUTCHER: Yeah, you're in control of your own software
release cycles, which is awesome.
RICHARD HYNDMAN: And it's a whole ecosystem, as well.
It's not just controlled by one company.
We have all the OEMs, the operators, the handset
manufacturers, the developers, people with their own music
stores, their own app stores.
Everything [INAUDIBLE]
Android to create this massive ecosystem.
People working together to create something.
[INTERPOSING VOICES]

NICK BUTCHER: Whoa, massive feedback.
RICHARD HYNDMAN: Thanks.

NICK BUTCHER: Cool.
I think this is a pretty open-ended
question, which really--
[INTERPOSING VOICES]
NICK BUTCHER: Yeah, it's been a long time since
someone has asked why.
It's more the how, now.
How do I do x?
But thanks for the question.
Hopefully there was some convincing arguments for you.
Any more live questions, or should we go
back into the moderator?
MARIJN OOSTERVELD: I have a question, which
is also in the moderator.
It's about a three-pane view which I would like to
implement, just like Gmail has.
So one on the left side and one on the right side.
And if you choose any content on the right side, you get
this slider, which just slides over one of those fragments.
And then there's some other content.

Without using any external library.
NICK BUTCHER: So you want to build it yourself.
Yeah, so basically these will just be fragment animations.
MARIJN OOSTERVELD: OK.
NICK BUTCHER: So every time you kind of-- you know in
Gmail, so when you select an individual message, it'll
queue up a set of animations where it'll slide out the
label view and slide in the detail view.
MARIJN OOSTERVELD: OK, is there an example or any code
available to try something like that out?
NICK BUTCHER: Yeah.
Sure there is.
One that was really good is the Romain Guy published
something called xlarge-demos.
If you Google for Romain Guy, xlarge-demos--
this was launched a while back now when Honeycomb just
launched, but it was a really nice demonstration of how to
use fragments and how to animate them around.
Since then, the animation API has only got better and
stronger and faster and so on.
So there's a few improvements that you can use, things like
adapters and so on.
[INAUDIBLE].

MARIJN OOSTERVELD: OK.
So that was x super?
NICK BUTCHER: Sorry, I think the demo is something like
xlarge-demos, you know, like the screen
size modifier, xlarge.
MARIJN OOSTERVELD: OK.
Thank you so much.
NICK BUTCHER: Yeah, you're welcome.
RICHARD HYNDMAN: Android 3 animation demos, maybe.

NICK BUTCHER: Hello, Mr. Banes.
CHRIS BANES: Hey guys.
NICK BUTCHER: You have a time shifted version
of us in your window.
CHRIS BANES: Yeah.
NICK BUTCHER: Any other questions live from the
Hangout, or should we crack on with the moderator?
[INAUDIBLE].

No?
OK, cool.
So Timothy Kist in Swansea says, how can I show that the
user can't swipe a certain way in a view
page by over scrolling?
How do I force over scrolling when the view page
is not at the end?
RICHARD HYNDMAN: What would you use?
You'd use the [? force field ?]
for this, right?
NICK BUTCHER: I don't understand what do you mean
when the view page is not at the end.
So you want to kind of arbitrarily cut them off
before they can get to the end, the last views, perhaps?
MATT GAUNT: It kind of sounds like if you had a wizard, you
might not want to enable them to go to the third pane until
they completed certain criteria on the second pane.
So my guess would be to just do this in the adapter, do
some tricky stuff just to say there's only two view pages.
And then once they've completed it, then fire off
and change the adapter, let's say, OK, now
the third one's available.
RICHARD HYNDMAN: Do you know how [? Raoul ?] did it in the
wizard template view?
NICK BUTCHER: You can always [INAUDIBLE].
RICHARD HYNDMAN: It's [INAUDIBLE].
Yeah, you could override the on touch as well--
the on-touch events-- and just decide whether or not you're
going to pass them through to the ViewPager.
So if they have not completed the requisite, whatever item's
on the form, just hold onto them.
NICK BUTCHER: That's a good argument, actually.
If you haven't done it, it's really, really worth taking a
look at the ViewPager sources.
Incredibly readable, and you'll learn a lot about how
to create custom views.
But, yeah if you look at the section where it's just a
touch drag, and it decides whether to tell the data to
give you a new view or not.
You could do it then.
Just invoke the edge effect stuff instead to get the
[? force field ?] clear At that point.
Hopefully that's the answer to your question.
Yeah, the AdapterView sounds like the right way to go so.

Al seems to be going through and adding timed YouTube
responses to each of the questions.
That's very [INAUDIBLE].
Thank you.
[STATEMENT REPEATS]
RICHARD HYNDMAN: The Chris Banes delay.
AL SUTTON: Just in case I missed it
the first time round.

CHRIS BANES: Rich, you seem to be in the Hangout twice.
RICHARD HYNDMAN: I am, yes.
Hey, hey.
NICK BUTCHER: Double Rich this week.
RICHARD HYNDMAN: That's what happens when we're unprepared
and we get to campus late.
NICK BUTCHER: So there's a question here from Giuseppe.
Do you want to unmute and ask us live, Giuseppe?

GIUSEPPE: Yes.
Hello.
NICK BUTCHER: How do I send a file over Bluetooth?
GIUSEPPE: Hello?
NICK BUTCHER: Little joke for the [INAUDIBLE] watching.
RICHARD HYNDMAN: We can hear you fine, Giuseppe.
Hi.
GIUSEPPE: Good, good, good.
I just put my [INAUDIBLE] question to
the moderator's panel.
If you want, I can ask here.
I would like to know in the case of a situation, where LVL
license failed, I mean that, actually, we have about 20,000
real users that paid the application.
But because we have a back-end server, we know that there are
about 300,000 users that they just downloaded the
application from Aptoide.
Is Aptoide just a center of crackers?
They remove they LVL license from the application, and they
make downloadable the application from everybody.
The bad situation at the moment is that the Play Store
is making possible this Aptoide exist, as there is the
client on the Play Store.
And this is not very good.
What is your point of view?
I would like to know.

RICHARD HYNDMAN: Yeah.
Well, first of all, there's the pirates and vampires talk
from Google I/O, which explains how to secure your
LVL past the standard documentation that we have.
Securing LVL is a long and in-depth topic.
If you put more effort into it, but it's worth cracking
your application--
especially in your case where you have quite a valuable
application--
hackers are going to spend more time trying to break it
and get that valuable app back out into the wild.
But as Hugo says, you've got your own servers that each of
the applications are porting to.
I would definitely try and maintain the list of
authorized users on those servers.
And whenever you get a pirated app, you can just disable it
from the server.

AL SUTTON: Another thing that I'd recommend is looking at
ProGuard or even going for Eric Lafortune's more
commercial offering, DexGuard, which is focused on Android.
That makes it more difficult to extract out things like LVL
and other routines, and bits and bobs like that.
So if the app hasn't been fed through at least ProGuard,
then it's definitely worth giving that a shot.
RICHARD HYNDMAN: Absolutely.
Yeah, that's mentioned in pirates and vampires.
Have you obfuscated your app, Giuseppe?
GIUSEPPE: Yes.
Has it been obfuscated with the ProGuard?

I have a mike on--
probably someone has the microphone open.
I think, this guy.
NICK BUTCHER: We'll try and find it.
GIUSEPPE: Uh, [? Patrick? ?]
[? Patrick? ?]

NICK BUTCHER: OK.
GIUSEPPE: OK, let's continue.
Well, the main solution, as everybody knows here, is just
to use a back-end server.
I would like to use the back-end server just to get to
each purchase, store the purchase in our back-end
server, and through the account manager, compare if
the user has been booked.
But in my special case, as you remember, we can't use the API
of Checkout, because they're available only
in UK and the USA.
And so this solution is not applicable for us.
The code has been obfuscated.
Everything has been done.
The check license--
it's not always in any update in the same
position of the code.
I used to change the position of the license checking,
sometimes in some activity, sometimes in some fragments,
sometimes somewhere else--
or some preference, everywhere.
I tried all that my small mind can suggest, but I didn't find
how to save it.
Well, someone told me, Giuseppe, never mind about
these people, because the people that crack it up will
never pay you for the application.
Yes, that is a good suggestion.
But the technical problem is very important, because
actually, my back-end server, it's giving, like downloading,
serving the information about.
So I have the 97% of the users that are using my
[? artworks, ?]
my resource for zero, for nothing.
That is the situation.
I believe that it's the time to find some
solution for this problem.
That's all.
Probably mine could be not the right question.
Seems to be not a question but is a way, here, to open the
discussion between us.
That's it.
NICK BUTCHER: Hey, have you tried verifying?
AUDIENCE: What is the name of your application?

GIUSEPPE: Sorry, [? Patrick? ?]
AUDIENCE: What is the name of application, like, that you're
talking about?
GIUSEPPE: I believe that here is not the right place to say
the names of our application.
We are not here for advertising.
If you want later, I would let you know.
AUDIENCE: Yeah, yeah, I was just curious, what [INAUDIBLE]
and the problem.
GIUSEPPE: Yeah, if you go on Aptoide website, then in the
music category, my application is the first one.
So you cannot [? wrong. ?]
OK?
Simple.

NICK BUTCHER: So have you tried the--
GIUSEPPE: I would like to say that my application is the
first on the Play store, not on the Aptoide store.
NICK BUTCHER: Have you tried all the recommendations in the
talk Rich talked about, the talk from Google I/O, "Evading
Pirates and Vampires," which talked about
exactly this problem?
GIUSEPPE: Yes.
NICK BUTCHER: So you tried verifying the signatures of
the device on your server and all this?
GIUSEPPE: Change this [INAUDIBLE].
Change the numbers that, any version I change the numbers?
No.
No way.
No way.
I tried to encrypt the device ID.
I tried to encrypt the--
everything.
Everything I tried.
They just remove.
They just remove the check.
They find, where is my do check, and they
then move the do check.
And then they return through anytime.
It's very simple.
I have already downloaded from Aptoide my APK.
And I understood very well, how they do that.
So I can try to follow any guidelines but I will not find
the solution if we continue to use LVL as a system.
That's it.
AL SUTTON: Do you have a free version of your application
and then allow people to purchase while in app?
GIUSEPPE: No.
We haven't the free version.
AL SUTTON: Because that might be a solution.
Because a lot of the times, you'll find people are trying
the application out to see if they like it.
Just taking it from another perspective, it might be worth
switching to in-app payments and offering a small free
trial to get people hooked in.
And then get them to buy once they're happy that they like
the application, rather than giving them the only choice of
pay up beforehand, or go and get it from a pirate site.

GIUSEPPE: Yes, but Al, you must agree with me that this
is just a workaround.
It's not the real solution to the problem, right?
AL SUTTON: It's not a technical
solution to the problem.
But from the statistics I've seen, there's a lot more
conversion to customers, a lot more purchases, when you
switch to something like in-app billing with the free
bit up the front.
Which could be a way to--
yeah, it won't cure the problem, but you'll certainly
find that you're getting a lot more paid
users on your server.
And so you may get to the stage where you're talking
50-50 or even 80-20 paid versus unpaid.

GIUSEPPE: Yes, that's true, that's true.
NICK BUTCHER: Yeah, I think that's a great point.

GIUSEPPE: It's a good suggestion, but frankly, I
hope that someday we can get also the technical solution.
NICK BUTCHER: Do you have any way of verifying which users
contacting your servers have paid and which haven't?
Can you, for example, look at a test on--
[INTERPOSING VOICES]
GIUSEPPE: Yes, I do that.
I do that.
I do that.
I check each customer.

I know from where they downloaded the application And
if they downloaded the APK from the Google Market,
because they're a constant inside the application.
But the only that I can do is, when I upgrade to new version,
just to block the old version.
This is actually what I am doing now.
But because the users demand to use it to upgrade to the
new version very fast, sometime I'm [INAUDIBLE] in
the problem to block users that have paid for, too.
AL SUTTON: Have you looked at check reporting the signature,
the APK file, to your server and only responding to
requests from an APK that's been signed
with the right signature?
GIUSEPPE: I lost you.
Can you repeat again please?
AL SUTTON: Sure.
Using the Package Manager, you can get the signature for your
APK, or the APK that's running.
Now, you should be able to report that to your server,
and it will only report your signature for application
versions which don't have your check removed, ie, you've
authored and you've distributed.
So if people are removing it and re-signing the APK in
order to get it installed, you'll probably find that the
signatures that get reported to your server are not the
ones who are expected.
And so you could just block those users straight off.
CHRIS BANES: The trouble with that is that they can easily
replace that code and just return what the proper
signature should be.
GIUSEPPE: Correct, Chris.
Correct.
CHRIS BANES: I don't think you're ever going to fix it,
because it's always going to be code, which
is out of your control.
It's always going to be on their device.
They can always [INAUDIBLE] to change it.
So you're never going to completely fix it.

I think you just have to bite the bullet and just accept it.
GIUSEPPE: OK.
Can I just put here one of my idea, and each of us try to
see if it's correct?
When the device downloaded the APK from the Play Store, the
Play Store knows the device ID in that moment, OK?
What is the problem for Google to give us in the back end
information--
the device ID?
Then we can collect this device ID, we can store
somewhere in our server, and to compare with the buyer?
I don't know if my question is clear.
RICHARD HYNDMAN: The problem is, I think, [INAUDIBLE] for
the buyer, though, you might have--
especially now with multiple users on a single tablet,
multiple accounts on a single tablet, it's the Gmail account
that's purchased it, not the device.
NICK BUTCHER: And then how would you use that?
You mean, you're proposing to send the device ID with each
request to your server?
Because then you just get in the same situation that Chris
talked about, where they'll find a valid device ID and
just always send that.

GIUSEPPE: You mean they can change the device ID too?
HUGO VISSER: No, they can send the device ID,
which is not good.
RICHARD HYNDMAN: Have you gone as far-- because I know you've
used the NDK a lot in your application.
But have you gone as far as doing the APK signature checks
in the NDK, in the native library that you compile off?

Because we would much rather decompile than reconstruct
that part of the application.
And then just disable the whole application if the
native library check fails.
Then you can check which signature the app was signed
with, the hash of the entire APK file, or
other things like that.
It's explained in the video.
GIUSEPPE: Richard, is there any of the suggested solution
already working and guaranteed that there would be not crack?
No.
RICHARD HYNDMAN: Never, ever.
There's nothing in the world that's not
been cracked, right?
Or has a secure system for anything.
NICK BUTCHER: It's not a secure computing platform.
You're not in control of the hardware, right?
AL SUTTON: Nothing's uncrackable.
GIUSEPPE: So we just make harder for them to make this--
RICHARD HYNDMAN: You need to make it harder to crack it
than your application is worth.
AL SUTTON: All of security is just about an
effort-reward ratio.
And it's making the effort so high and the reward so low
that people don't think it's worth doing.
NICK BUTCHER: I really think that the idea of going free
with in-app purchase is a really, really good idea,
actually, as well.
I think, yeah, when you make it so easy to get access to
the application and very easy to pay to--
if you've proven that you like it, then I think that removes
some of the curiosity-type pirating.

RICHARD HYNDMAN: Yeah, it's just hard to figure out,
especially in this kind of application, how much of the
functionality you give away for free.
Because users will install it expecting it to do a certain
amount of things.
And then you're like, oh, to do that, you
need the pro upgrade.
Please buy it here for $0.99 or whatever it is.
So you've got to still get the balance right, because you
could lose a lot of ratings on it.
NICK BUTCHER: Yeah, it's not trivial, but
it's worth it, I think.

RICHARD HYNDMAN: OK?
GIUSEPPE: OK, thank you very much.
RICHARD HYNDMAN: Since then, there's been a big
conversation going on in the chat window that I haven't
been reading.
NICK BUTCHER: There is?
What's been going on, Rich?
RICHARD HYNDMAN: I just don't have an idea how they manage
to change obfuscated code.
Whenever I decompile an obfuscated app, it's a mess.
[INAUDIBLE] says it's easy.
NICK BUTCHER: It's because they're [? leet. ?]
RICHARD HYNDMAN: Hackers just rip out the
Android Java checks.
Check out the Droidcon UK videos, for
example, for Apkudo.
HUGO VISSER: Yeah, there was a presentation on hacking, Words
With Friends or something like that?
NICK BUTCHER: Yeah, "Reverse Engineering for Fun and
Profit" or something, I think it's called.
HUGO VISSER: Yeah, it was a very cool thing, but it also
shows how easy it is.
It's just the matter of time that you put in it.
NICK BUTCHER: I think you need a lot of this stuff, these
checks and NDKs Rich suggested, also.
HUGO VISSER: And I'm not sure how LVL works, but couldn't
you just send the response [INAUDIBLE] to your server and
then do something with that to verify it?
NICK BUTCHER: Yeah, that's what I was suggesting, because
it is signed with your public key, right?
RICHARD HYNDMAN: Yeah, but that bit in the
middle, where the app--
because it goes from our servers to your application
and then your servers.
The bit in the middle where your application gets hold of
it can just say, true.
HUGO VISSER: Yeah, but you could also just check if it
phoned home at all.
If somebody removes that check, and it doesn't phone
home, or it phones home with the same value all the time,
that could make it a bit harder.
It will never be perfect.
RICHARD HYNDMAN: There's always going to be--
just make it a bit harder, a bit harder.
Eventually, at some point, it's hard enough.
Other people leave the stock LVL implementation inside
their application, as well, so people think
they've cracked it.
But then they have a more secure [INAUDIBLE].

HUGO VISSER: And one other thing that I do on forms, if
you try to spam, for example for the spammer, it looks like
everything works.
But in reality, stuff doesn't work.
So I can imagine, for this particular application, that
maybe some things work, and some things just don't work if
it detects that you have a cracked app.
NICK BUTCHER: One of my favorite ones is a partner I
work with who, when they detect someone's a pirate,
they don't tell or do anything.
They just make it possible to finish that level.
The baddies are suddenly like a bit rock hard.
AL SUTTON: There's one I saw that enabled the game.
But after playing for an hour or two, you actually got a
pop-up that took you to the Play Store and said if you
want to continue, you're going to have to buy it.
Which is quite a nice way of doing things.
NICK BUTCHER: Fair enough, I say.
That's a good strategy.
RICHARD HYNDMAN: Yeah, get them addicted.
Push that on them.
NICK BUTCHER: Yeah, exactly.
If you pop up a thing saying, you're a filthy pirate, people
are going to get all defensive and not going to be
inclined to buy it.
But if you say, hey look, you've been playing for two
and a half hours, now.
You've got this much progress, which we'll keep for you.
Just freaking pay the 99p.
AL SUTTON: And don't forget the picture of you with the
begging bowl.
NICK BUTCHER: Something like that, I guess.
Anyway, we've been on piracy for a long time.
Let's move on.
GIUSEPPE: Sorry, sorry again.
It's Giuseppe again.
I like the question of Peter Brooks.
Has the Google service API got the Play Store transaction?
This is something that seems to be interesting.
NICK BUTCHER: I missed that.
Is that in the sidebar?
Has the what?
GIUSEPPE: Has the Google service API got Play Store
transactions?

NICK BUTCHER: Google Pay services?
Yeah.
GIUSEPPE: Yeah, yeah.
If the Google Play services could return back to us in the
API the transactions, probably we can double check if the
application has been paid or is using something different.
NICK BUTCHER: No, I don't think it is.
RICHARD HYNDMAN: Certainly not for a paid application, no.
You can't use the Play Store [INAUDIBLE]
Play Store for an outside application.
MATT GAUNT: If it's an in-app purchase, you could get the
list of purchase of that account.
GIUSEPPE: Yes, correct.
MATT GAUNT: That way, again, you're still going to then go
on to the root of them stepping in the middle and
just saying, yep, he's paid, so--
RICHARD HYNDMAN: Yeah, but the new Play Services API doesn't
have anything for paid applications-- or the new V3--
CHRIS BANES: If you're externally, trying to check--
is there a Checkout API?

GIUSEPPE: Checkout API, it's not usable for our
countries, you know.
RICHARD HYNDMAN: Yeah, I believe Checkout merchant's
port is only in US and UK.
And they're the only countries [INAUDIBLE] the API.

GIUSEPPE: Well, one must ask to the Google service API team
to implement something for transaction checking.
So please, do that.

NICK BUTCHER: Cool.
RICHARD HYNDMAN: Wow.
The topic in my moderator right now
is a Windows 8 question.
NICK BUTCHER: Oh, really?
Going to go for it, Rich?
RICHARD HYNDMAN: Well, I don't know the answer.
I don't have Windows 8, I've never tried Windows 8.
I saw it in an airport once.

Is it possible to connect an Android 4 phone with Wi-Fi
Direct to a Windows 8 PC using Windows networking proximity?
Same question for Windows 7 PC and Namespace API.
I have no idea.
NICK BUTCHER: I don't know, well, Wi-Fi Direct is a
standard, right?
I just don't know of anything else that implements it.
RICHARD HYNDMAN: I don't know what you'd want to run over
the Wi-Fi Direct, necessarily, once you'd connected your
device to your PC using Wi-Fi Direct.
NICK BUTCHER: Maybe again, maybe, yeah, you can send
files or something.
RICHARD HYNDMAN: We clearly have no idea.
All we've used Wi-Fi Direct for is hooking phones up
directly to play games and things like that.
NICK BUTCHER: And doing [INAUDIBLE].
RICHARD HYNDMAN: And doing Wi-Fi Direct discoveries.
I've never connected to a PC.
I've connected to a TV, I guess, because Miracast comes
over Wi-Fi Direct, right?

If anybody has any information on Windows 8 and Wi-Fi Direct,
send it to Cedric in Switzerland.
There's only one.
NICK BUTCHER: OK, [? Zerdis ?] in the moderator asks another
favorite question of the office hours.
He wants to do a horizontal list, basically.
He wants to replace gallery, and horizontal scroll view
isn't an adaptive view.
And he can't use ViewPager to show multiple views unless he
uses an external [INAUDIBLE], apparently?
Can you point me to a good tutorial?
So there are a huge number of horizontal list view
implementations out there on GitHub, and code.google.com,
and so forth, each with their own various implementations
and drawbacks and so forth.
Has anyone used a good one?

[INTERPOSING VOICES]

CHRIS BANES: You're talking about lists, well,
I haven't got that.
RICHARD HYNDMAN: Speaking of horizontal lists.
CHRIS BANES: Yeah, horizontal lists.
No, I was going to make a horizontal bridge view.
But you could do a one--
[INTERPOSING VOICES]
NICK BUTCHER: One at a time, please.
CHRIS BANES: He's on the list.

RICHARD HYNDMAN: OK, [INAUDIBLE]
just dropped out.
We'll go to webcam view.
We'll officially be back in a second.
Hopefully you can still hear us.
Somebody nod if you can hear us.
AL SUTTON: We can hear you.
The second session in the Hangout now becomes obvious.
RICHARD HYNDMAN: It was only so I could see the chat
window, as well.
One way or another.
MATT GAUNT: So my approach I've taken with horizontal
scroll view in the past, has been, I've done it myself with
taking the gallery source code.
Someone had actually taken that and wanted to add in
recycling of views.
So there's an example somewhere on Stack Overflow
where they've posted a load of code.
If you really want to get your hands dirty, that might be one
way of doing it.
But it's a lot of extra work.
If you can find the library on GitHub, then
I'd stick with that.

That would be kind of only my input on that.

GIUSEPPE: Yossi, Yossi it is too strange to see you too
late today.
What happened?
YOSSI ELKRIEF: No, l was waiting for the Hangout.
And the Hangout was late, so I went to do other stuff.
RICHARD HYNDMAN: Yeah, we were.
Sorry about that.
We were seven minutes late today because we were setting
up in the studio.

I have no other excuse.
Let's go to the next question in the moderator.

MATT GAUNT: So next question is, what is the reasoning
behind making the method setText in TextView final?
And Chris has responded with, I question why you need to
override the method.

Fair enough.

Yeah, why would it be defined as final?
And yeah, why would you need to override it?
NICK BUTCHER: I don't know.
Might check the source to see if there are any comments.
RICHARD HYNDMAN: I would check the source, as well.
I was thinking that.
MATT GAUNT: Use the source.
RICHARD HYNDMAN: I might check it now.
NICK BUTCHER: That'll make for good TV.
RICHARD HYNDMAN: You can just hold the thought for a second.
NICK BUTCHER: I hope the is, clearly, we don't know.
RICHARD HYNDMAN: Unless it's a comment in the source.
NICK BUTCHER: There is another question in the moderator.
It's Etienne.
It says, I have been able to implement a custom
MultiAutoCompleteTextView backed by a
SimpleCursorAdapter with a custom tokenizer.
I was just wondering, is it possible to implement this
using the CursorLoader instead?

I have not done MultiAutoCompleteTextView.
Has anyone done that before?
I've done a regular one.
MATT GAUNT: No.
NICK BUTCHER: Has anyone got any experience with that?

I guess it sounds like it could be possible, instead.
I mean, when you're doing an AutoCompleteTextView, it's
best if you have a way to asynchronously fire off a
query against your data source and return back
a data set to be--
to provide the autocomplete suggestions.
So you could use the load infrastructure
for doing that stuff.
But if you've got it working using, probably, the
AsyncQueryHandler, I imagine, at the moment, then probably
stick with that.
But I don't see any innate advantages to moving.
MATT GAUNT: Yeah, she's just posted a Stack Overflow link.
So maybe we can add it to the comments to see if anyone else
can add another.
NICK BUTCHER: A bit later.
What are you doing Rich?
RICHARD HYNDMAN: It looks like setText is final because it's
the helper method.
There is setText which takes text and a buffer type, which
isn't final.
So it just fixes the buffer type on the text that you're
passing in.
NICK BUTCHER: And what is it passing?
What's the buffer type?
RICHARD HYNDMAN: [? M ?] buffer type.
It's a long file.
NICK BUTCHER: Who is that with the crazy Android cake?

MATT GAUNT: My guess would be Yossi.
YOSSI ELKRIEF: It's me, it's me.
Yeah, guessed it right.
NICK BUTCHER: 10M?
YOSSI ELKRIEF: Yeah.
10 million downloads.
[INTERPOSING VOICES]
NICK BUTCHER: 10 million downloads, for who?
CHRIS BANES: Well done.
GIUSEPPE: Bravo, bravo, bravo.
Bravo.
Bravo.
RICHARD HYNDMAN: Passes in buffer type normal.

So setText is final because it passes in a
buffer type of normal.
But if you want to override setText, you setText, which
takes the string and the buffer type.

CHRIS BANES: Rich, is it because setText is remotable?
RICHARD HYNDMAN: Nope.
It's not, is it?
CHRIS BANES: Yeah.
RICHARD HYNDMAN: [INAUDIBLE], as well?
CHRIS BANES: Well, I hope so.
RICHARD HYNDMAN: Or do you just know
that setText is remotable?
MATT GAUNT: Yeah, it must be, right?

RICHARD HYNDMAN: It might be you're right.
Could be.
CHRIS BANES: There might be some reflection and stuff
going on in the background, isn't there?

NICK BUTCHER: Are there any other
questions that we've missed?
Have they all come in?
MATT GAUNT: I think so.
RICHARD HYNDMAN: Finished up the moderator.
NICK BUTCHER: Yeah, I think we flied through it today.
PETER BROOKS: I've got some question here.
NICK BUTCHER: Please.
PETER BROOKS: It's a bit about the security discussion you
had earlier.
I was wondering, because I'm at the moment developing some
framework, where the developer that uses this framework needs
to make some configuration files.
So we need to give the framework some key value
pairs, somehow.
And I've wondered, where would I let the
developer store this?
Since if I understood it right, if he put it to the
resources, every other app code accesses via code,
because they are not private to that.
And of course, that's also what you mentioned earlier.
I know that anywhere where I store it on the device, it
won't be safe.
It just obfuscated somehow.
But where could I let him put it so that it's at least so
much obfuscated that another app couldn't
access it via code?
RICHARD HYNDMAN: So I'm not quite sure what you mean by if
it's in the resources, another app would be able to
access it via code.
PETER BROOKS: Yeah. perhaps that's the first question.
If I got [INAUDIBLE], another app can have access to the
resources of another app via the Package Manager Class?
So another app could just--
I thought about some XML file that stores the configuration.
But that way, another app could just load it via Package
Manager Class?
Did I got that right, or--
NICK BUTCHER: There are some areas of your resources which
are accessible.
I mean, that's how you can write a third-party launcher,
for example, because you can access each APK's icon,
resource, and things like this.
I forget-- do you guys remember?
There's some areas of your resources which aren't public,
aren't more readable, and some which are.
And I can't, offhand, remember which is which.
Has anyone got any--
RICHARD HYNDMAN: I'm just looking it up at the moment.
NICK BUTCHER: Everyone's rapidly Googling.

Beyond that, I mean, any code resources are obviously going
to be private to the application.
Could you force them to implement an interface or
something like this instead?
PETER BROOKS: Yeah, I could, but I thought it might be a
bit more handy for them, since I only need key value pairs,
if they could place it in some XML file or property file.
NICK BUTCHER: What was that, Chris?
CHRIS BANES: You can put it in assets.
NICK BUTCHER: So assets isn't readable,
whereas resources is?
PETER BROOKS: Isn't it?
OK.
Because as I looked, you can get from the Package Manager
the resource.
And from the resource class you can also
access the asset directory.
But I might have got that wrong.
CHRIS BANES: I don't remember why you can access assets.

NICK BUTCHER: Or is it even in res.raw, maybe?

CHRIS BANES: I can't remember, but I thought before there was
one area which is public and one area that isn't.
But I can't remember, offhand, which is which.
Don't know if you guys know, either.

NICK BUTCHER: So is this some kind of client secret or
something like this that they need to have in their
application?
Or an identifier of some sort?
PETER BROOKS: Sorry?
NICK BUTCHER: So, what is the key value pair,
you're trying to--
PETER BROOKS: It's first some server address that I need to
install, that shouldn't be so sensitive, and some kind of
application ID to authenticate against the server.
CHRIS BANES: Can't they just define it in code?
Can't you just have a hash mark, and just--
[INTERPOSING VOICES]
PETER BROOKS: Yeah, it could, but I thought it might be a
bit more handy for the developers if they use the
framework and they don't need to write--
because at the moment, they don't need to
write any other code.
And so this would be just for configuration, implementing
interfaces, [INAUDIBLE].
Yeah, it would work.
CHRIS BANES: So if you write the framework, and they don't
have to write any code, what does your framework do?
PETER BROOKS: Synchronizing.
It's for--
should synchronize Java objects to a server
transparently.
So actually, there should be only less code, as less code
as possible needed from the developer.
HUGO VISSER: I wouldn't mind passing something through code
for configuration, since it would also [? time ?]
check stuff.
NICK BUTCHER: The standard way most apps seems to be doing
it-- like Maps API and Backup Server and stuff--is a
metadata tag in your manifest, right?
PETER BROOKS: Yeah, that's also what I thought about in
the first place.
Then I read that you can access via the Package Manager
[INAUDIBLE].
So I thought it might be nice if at least other apps can't
access the key via code.
So of course, as long as it's on the device, you can get it
out there, but perhaps not via another
application on your device.
NICK BUTCHER: It comes down to, I guess that's the
convention, so I think that would be the conventional way
most people will be used to it.
But yeah, if you would make it much harder for apps to read
them, then yeah, you could put it in code.
PETER BROOKS: Thanks, guys.
NICK BUTCHER: You're welcome.

All righty.
Any other questions?
I've seen there's a few in the G+ thread as well.
RICHARD HYNDMAN: I'm starting to look at them now.
Mostly, it's about the privacy issues, protecting your
application.

NICK BUTCHER: Is there an example on how to style the
preference widgets from PreferenceActivity?
I find it difficult to style the list of radio buttons from
a ListPrefence, for example.
Has anyone done this?
MATT GAUNT: No, I was always [INAUDIBLE].
RICHARD HYNDMAN: Absolutely not.
I always just make my own.
MATT GAUNT: I thought that that was the point of
PreferenceActivity, just kind of does everything for you,
and you kind of--
NICK BUTCHER: It's a [INAUDIBLE].
RICHARD HYNDMAN: You can choose your theme.
MATT GAUNT: There's a light theme and a dark theme.
RICHARD HYNDMAN: Why would you want deviate?
MATT GAUNT: I mean, Chris, is this something you might be
able to do where you could insert a theme at run time?
CHRIS BANES: I don't know.
I don't know if the preference styles are
actually public there.
They might be internal.
So I don't think you can override them.
I don't know.
I've never done it, so I've never looked.
NICK BUTCHER: Yeah, I'd verge on the side of not
wanting to do that.
I think there's some utility to preferences looking the
same and operating the same.
Yeah, you've got the choice of light or dark, but that's
about it, really.

There is something like unified preferences, as well,
if you look at the library.
Unified preferences, that's quite a nice little library
which helps you to do this kind of thing and produce
fragment-based preferences, which work across phones and
tablets, as well.
So I think there's some utility in not doing this,
unless there's a specific thing
you're trying to achieve.

Cool.
I feel like we're running out of questions, unless there's
anything live.
RICHARD HYNDMAN: Absolutely.
Anyone have any last questions?
I think someone just put something in the chat window.
NICK BUTCHER: Oh yeah?
RICHARD HYNDMAN: I guess, [INAUDIBLE].
No.
OK.
It's just him saying OK.

NICK BUTCHER: Ah, here's one.
In Java, I can start an application with my custom
class loader.
Is there a way to do it in Android?

You can, can't you, right?
Didn't Fred write an article on the Android Developer blog
about this?
RICHARD HYNDMAN: That was for loading class files off the
internet and then loading inside your application with
the class loader, but not a custom class loader.
I'm not quite sure what he means.
NICK BUTCHER: Oh, you can't do a custom class loader?
RICHARD HYNDMAN: I don't know what he means by a custom
class loader.

CHRIS BANES: I didn't think you could
change a class loader.
NICK BUTCHER: No, I don't think so either.
Think this might be a Dalvik thing.

Ah, there's a next page of the moderator questions as well.
Perhaps we hadn't answered them all.

Answered that one.

Is there any way to accept some parts of a software
update and reject others, asks Bob of BBB.
No.
Not unless you're coding your own kind of update mechanism.
But not through the Play Store.

Last question.
Cy from Southend says, now that the protection level
definition of change configuration has been changed
in Jellybean, breaking apps like MoreLocale2, is there a
way to change a device language to a custom
one, such as Welsh?

Anyone know that?
RICHARD HYNDMAN: No, I'm just looking it up now.
NICK BUTCHER: So is this one of the settings that I
wasn't aware of?
Is this one of the settings that moved from local settings
to global settings and had their protection changed?
RICHARD HYNDMAN: Allows an application to modify their
current configuration, such as Locale since API level one.
What's changed about it?
NICK BUTCHER: The protection level, it says.
I'm guessing it had gone to system signature.
CHRIS BANES: Is it the secure setting stuff?
NICK BUTCHER: That's what I thought, yeah, with the
multi-user stuff.
RICHARD HYNDMAN: It may be because of the multi-user--
NICK BUTCHER: That's my gut feeling of what the answer is,
in which case it's the same answer as we gave before, that
many of these things, it's not that we've changed it, because
there wasn't ever a very well-defined API for it.
You weren't supposed to be able do this.
It's just that you were able to poke certain settings into
the thing, and behavior would change.
But it wasn't like it was a well-defined API that we
guaranteed not to break.

RICHARD HYNDMAN: Changing device language in Locale from
inside an app doesn't sound like something--
NICK BUTCHER: Yeah, I would just send the users to the
appropriate screen in settings, really.
Fire off an intent.
RICHARD HYNDMAN: Absolutely.
NICK BUTCHER: I mean, I know for apps like Locale, that's
not going to be exactly the behavior you want, but that's
what the platform supports.

RICHARD HYNDMAN: OK.
In which case, it's going on 3 o'clock.
We'ver run out of questions in the
moderator and the G+ string.
I can finally get this echo out of my ear.
That feels good.
And thank you for joining us today.
We'll be back at the normal time for next
week's office hours.
But then I'm guessing there'll be a hiatus for Christmas, for
the holiday break for a couple of weeks.
And we'll be back-- well, we'll decide by next week when
we'll be back after Christmas.
But thanks, you all, for joining us again, and we'll
catch you next week.
NICK BUTCHER: Cheers, guys.
GIUSEPPE: Thank you.