12

Due to this annoying Android limitation I need users to reinstall my application so the manifest permissions are detected by other applications.

This is already going to be frustrating for the user, but in addition, I cannot see a way to reinstall my application from the apk stored in /data/app and I would therefore have to download the same version to the storage card before firing the usual install intent.

I eagerly await someone telling me that I'm missing something obvious! I've drawn a blank...

Thanks in advance.

Please do star the issue if you'd like to see it resolved! Cheers.


EDIT: With the comments of @hackbod in mind, you can use the following code to initiate the install dialog.

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(this.getApplicationInfo().sourceDir)),
"application/vnd.android.package-archive");
startActivity(intent);

On my Jelly Bean device, this presents two options: Package installer and Verify and install. I don't know if the latter will deal with the issue of:

  • Installing your app this way will probably remove ownership of it from the Play Store

My application is free, so I cannot test the paid issue of:

  • Note however if your app is forward locked (which is unavoidable for all paid applications starting with JB, due to the app encryption), then this won't work because your app executable is not readable by others

Although hackbod finishes with 'readable by others' which suggests that if you are executing this through your own code, for your own application, it is readable? Please do correct me if you can test this and I'm wrong.

brandall
  • 6,094
  • 4
  • 49
  • 103
  • 1
    You may be able to copy it from /data/app to the storage card. Although you cannot browse that directory, the files it contains are usually readable - though that's not guaranteed (and that is not always the install location anyway). An alternative might be to not use the permission system, but try to do your own authentication of the requesting package. – Chris Stratton May 16 '12 at 14:19
  • Thanks Chris - My application needs to be installed on the device otherwise it won't function correctly, so I've minimal worries about the user install location. I assume that's the only consideration you were referring to? Also, as /data/app is readable, I could check the apk was located there prior to anything else. From my searching, I cannot find a way to transfer the apk from that location unless using root functions... Would love to know if there is a way... I'm not certain what you meant by my 'own authentication'? Cheers. – brandall May 16 '12 at 14:28
  • If it's readable (as it usually is) you do not need root to copy it to somewhere you are allowed to write to (such as the sdcard, with appropriate manifest permission). However, /data/app is not always where it gets installed. And sometimes the apk filename is changed during installation. You may be able to determine the location and installed name from /data/system/packages.xml but at that point you are fairly deep into private internal functionality which may not be future proof. Really, re-downloading is probably your best bet - at the very least, have that as a fallback option. – Chris Stratton May 16 '12 at 14:58
  • 1
    Actually the app itself can determine its own apk file/location from /proc/self/maps as it has itself opened and mapped into memory as a consequence of running. Note I said the app itself - another process, such as the adb shell would see what is mapped into its own process, not your app's. – Chris Stratton May 16 '12 at 15:01
  • Thanks again, I'll look into your suggestions - I didn't know of the /proc/self/maps. If I had faith that Google would fix it in a few days I wouldn't be so bothered in the interim - but I've a feeling I'm looking for a longer term solution! – brandall May 16 '12 at 15:13
  • Be prepared for a long time solution :) Even if Google would fix that in a few days: it would take like 2 years before you can rely on the fix to be present in every Android device you develop for. And I doubt Google will fix your issue any time soon, maybe it is even working as intended (there might be security issues if they would do it differently). – zapl May 16 '12 at 15:33

1 Answers1

3

Conceivably you could just get the path to your .apk through Context.getApplicationInfo().sourceDir, and launch the app installer with that path. Not however if your app is forward locked (which is unavoidable for all paid applications starting with JB, due to the app encryption), then this won't work because your app executable is not readable by others. In that case you would need to copy the .apk to somewhere world readable (such as in external storage) and install it from there.

No matter what you do here, though, this has some unavoidable very negative consequences:

  • The only way to do any kind of install from your app is to go through the side-loading UI, which is (a) going to be a very scary experience for the user, and (b) will require that the user turn on side-loading to be able to proceed.
  • Installing your app this way will probably remove ownership of it from the Play Store (since it is no longer the one that has installed it). This may mean for example that the user can no longer report crashes or ANRs to you through the play store, or other negative consequences. I am not sure exactly what problems will actually happen here, but I really wouldn't assume that this is going to be okay.

Ultimately, I just would very much not suggest doing this. What permission are you needing that is forcing you to do this? For many reasons, I wouldn't recommend that third party applications declare their own permissions in most cases, because there are a lot of bad user experiences around permissions that are only known after they may have been needed.

hackbod
  • 90,665
  • 16
  • 140
  • 154
  • Thanks for your answer. A good example of this problem is the application Tasker, which requires net.dinglisch.android.tasker.PERMISSION_RUN_TASKS. As I'm sure you know, Tasker can do some major device changes, so it's understandable why the developer would want to bring this to the attention of the user that installs my app. If I suggest to my users that they install Tasker for its compatible features, I'm then presented with this situation, where the permissions in my Manifest are not detected. I'm not sure if I can mark your answer as 'correct' as there does not appear to be a solution? – brandall Aug 30 '12 at 13:21