Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Sir_Substance posted:

That's exactly what I'm looking at doing, but I can't pretend to be impressed at a toolset that makes me do it that way, if that's really the only way :sigh:

The reason you need to do things this way is so that things don't break when the framework kills your app and then restarts it at some deeply-nested activity.

If you're passing around some complicated object graph, potentially with embedded references to the existing application context, it's basically going to be impossible to recreate that when relaunching your app. Forcing you to stick to communicating persistable information makes things much cleaner, unless you go out of your way to try and subvert it (in which case you kind of deserve the pain you're going to get).

Adbot
ADBOT LOVES YOU

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Tunga posted:

ListViews seem to be unnecessarily complicated. Anyone have a good article explaining the best way to get a bunch of structured data (in my case some JSON) into a ListView with multiple text/image items on each line? I'm guessing I need a custom View which inherits from whatever a ListView displays?

The easy way to get data into a ListView:

- Create a custom subclass of BaseAdapter.
- Implement getCount() to return the total number of items in your data set.
- Implement getView(int position, View convertView, ViewGroup parent) to inflate a new view from whatever layout you want to use, populate it with the data from the appropriate position in your data set, and return it.
- Give the ListView your adapter.

Once you've got that working, there are some other steps that you'll want to do:

- call notifyDataSetChanged() when the underlying data changes so that the ListView knows to refresh itself.
- Re-use the convertView that gets passed into your getView() method (if possible) to avoid re-inflating views all the time.

There are other classes like ArrayAdapter and CursorAdapter and SimpleCursorAdapter and stuff - you can just ignore them for now. Subclassing BaseAdapter is both easy, and gives you the best understanding of how the framework actually works. After you've figured everything out, then you can take a look at the other options and see if one of them fits your use case better.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Tunga posted:

Thanks, this was wonderfully succinct and a lot easier to comprehend that a lot of the giant articles I found which started going into a ton of details before explaining the basics.

No problem! I honestly did consider just linking to the documentation, but then I decided to read it from the perspective of someone who doesn't already know how this stuff works and ... it is not particularly helpful. Either there's a hidden section I haven't been able to find, or they just left out the basics and jumped straight into the "so now that you know how adapters and such work, here's some convenience implementations that could save you some time" part. So I figured I'd better write something about the correct way to get started.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Super Dude posted:

I'm receiving the following Uri from the Photos app
code:
content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F21930/ACTUAL
What is the best way for me to decode it to get the correct characters back? The Uri returned from Gallery doesn't have %2F or %3A.

You don't. A content uri is an opaque string that you can use to manipulate a resource. If another app wants to put % characters in their content uris, that shouldn't affect your app at all.

What are you actually trying to do?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Essentially, you want to encapsulate that data inside the Runnable you're sending back to the UI thread. You could do this in a few different ways, for example by making a custom subclass of Runnable that takes some parameters:

code:
class UpdateUiRunnable implements Runnable {
  private final int value;
  public UpdateUiRunnable(int value) {
    this.value = value;
  }
  public void run() {
    // do stuff with value
  }
}

But by far the easiest way is to let the language do all that heavy lifting for you, by simply capturing those values inside an anonymous class.

code:
public void backgroundThreadStuff() {
  final int value = computeTheValue();
  context.runOnUiThread(new Runnable() {
    public void run() {
      // because it was declared 'final', you can
      // just use 'value' here like normal.
    }
  }
}

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
For an ACTION_SEND intent, you should put the content uri in the EXTRA_STREAM extra rather than in the intent data.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
What are you trying to achieve, and why is playing with the tile mode the way to achieve that?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

speng31b posted:

Windows + adb not seeing device = driver issue. The adb driver for debugging and dev isn't necessarily working just because the storage driver is. Google adb driver + your tablets name and model #, see if anyone has a working driver for it. I've had to manually modify driver files and/or reboot windows in its special relaxed driver signing mode to get adb debugging working with some Android tablets on windows. Good luck.

That's probably not the problem if the device has USB debugging disabled. Doesn't matter what drivers you install on your PC if the device is just going to ignore everything anyway.

I would investigate further into why there is no USB debugging option.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Subjunctive posted:

We released ReDex today, a bytecode optimizer for Android apps. It takes in an APK and produces an optimized one. 25% improvements in speed and size aren't uncommon.

http://fbredex.com/ is the main site. https://code.facebook.com/posts/1480969635539475/optimizing-android-bytecode-with-redex is the post where we first announced it, which describes some of the optimizations it performs.

Nice :)

Are those comparisons against "plain" compiled code, or is that being compared against the same app with Proguard's optimizations?

Does running something through Proguard impair later optimizing it with redex?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
That's pretty impressive.

Is there a similar performance gain if you're just using redex (without proguard)? The reflection-aware optimizations seem really cool, but of slightly dubious value if you still have to tell proguard about everything you're doing there. Or do you just have proguard keep everything and let redex do all of the class renaming and dead-code removal?

How fast is the actual optimization process? Is it feasible to use on dev builds?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Honestly just skimming the problem description, it seems like you're X-Ying a hell of a lot. Why do you need to distribute these presentations as individual apks instead of just as data files for a single app to read?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Either package it with the binary you're shipping, or have a first-run state where the user can provide that information.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
If you're putting something (like an ML model) in your APK with the intention of it being unpacked and executed on the device, there's no practical way to prevent someone else from unpacking and executing it the same way your software does. There are ways to make it more challenging, but you're really just raising it to the level of "bored teenager with a few hours to kill".

If you're willing to relax the offline requirements then you could only provide the decryption key transiently to devices that have passed attestation, which would make your bored teenager need to work a lot harder (but still wouldn't be NSA-level stuff).

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
https://developer.android.com/training/safetynet/attestation

The general flow is your own server will be in charge of providing the decryption key, but you get to outsource the "check that the thing asking for it is an authentic version of your app running on an un-hosed-with device" step to someone else.

But keep in mind:

quote:

The API is not designed to fulfill the following use cases:
[...]
- Replace or implement strong DRM checks.
Again, it just makes the bored teenager need to work a little harder.

You could alternatively license a DRM system from somebody willing to sell it to you, and trust that their efficacy in practice matches up with their marketing copy.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Yes, a foreground service is the correct way to do this. The visible notification is a reminder to the user that your application is still doing what they asked it to.

It shouldn't be particularly onerous to set up, everything's gonna be running in the same process so you can ignore all the aidl poo poo. Just call startService() when the user does the thing and have the service call startForeground().

Probably the biggest hassle is making sure your Activity cleans itself up properly instead of not bothering.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Use a Slider with a step size of 1, and give it a LabelFormatter to map that to your custom values for display.

This has the extra upside of making your tick marks evenly spaced out so it's easy to hit them, instead of being all bunched together at one end and really far apart at the other.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
If I was doing this, I would just write a "wrapper" viewgroup that handles the rotation. Just have it measure and lay out its one child according to the specific rotation you want it to have.

Adbot
ADBOT LOVES YOU

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
You probably want some combination of rotating and moving your planet view, rather than purely rotating it.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply