5

Back in the day, installing an app as a system app was as simple as moving the APK file to /system/app or /system/priv-app. Removing them was as simple as deleting the APK.

Now, while I'm customizing the phone's stock ROM, I've noticed that each and every app on the system partition was inside their own folder. I've tried to simply drop the APK in /system/app or /system/priv-app, but they don't work.

How do I install an app as a system app on Lollipop? I suspect something's up with SELinux and context, but I don't have root access. However, I have read/write access to the filesystem (by mounting the image in Linux).

UPDATE: I've tried Death Mask Salesman's suggestion and taken a look at logcat. The apps I want to pre-install (e.g. Instagram) are throwing this error:

01-01 01:04:45.108 5538-5538/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 Process: com.instagram.android, PID: 5538
                                                 java.lang.RuntimeException: Unable to instantiate application com.instagram.app.InstagramAppShell: java.lang.ClassNotFoundException: Didn't find class "com.instagram.app.InstagramAppShell" on path: DexPathList[[zip file "/system/framework/com.google.android.maps.jar"],nativeLibraryDirectories=[/custpack/app/removeable/withlibs/com.instagram.android-1/lib/arm, /vendor/lib, /system/lib]]
                                                     at android.app.LoadedApk.makeApplication(LoadedApk.java:572)
                                                     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4818)
                                                     at android.app.ActivityThread.access$1500(ActivityThread.java:178)
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1531)
                                                     at android.os.Handler.dispatchMessage(Handler.java:111)
                                                     at android.os.Looper.loop(Looper.java:194)
                                                     at android.app.ActivityThread.main(ActivityThread.java:5624)
                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                     at java.lang.reflect.Method.invoke(Method.java:372)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
                                                  Caused by: java.lang.ClassNotFoundException: Didn't find class "com.instagram.app.InstagramAppShell" on path: DexPathList[[zip file "/system/framework/com.google.android.maps.jar"],nativeLibraryDirectories=[/custpack/app/removeable/withlibs/com.instagram.android-1/lib/arm, /vendor/lib, /system/lib]]
                                                     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
                                                     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
                                                     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
                                                     at android.app.Instrumentation.newApplication(Instrumentation.java:985)
                                                     at android.app.LoadedApk.makeApplication(LoadedApk.java:567)
                                                     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4818) 
                                                     at android.app.ActivityThread.access$1500(ActivityThread.java:178) 
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1531) 
                                                     at android.os.Handler.dispatchMessage(Handler.java:111) 
                                                     at android.os.Looper.loop(Looper.java:194) 
                                                     at android.app.ActivityThread.main(ActivityThread.java:5624) 
                                                     at java.lang.reflect.Method.invoke(Native Method) 
                                                     at java.lang.reflect.Method.invoke(Method.java:372) 
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959) 
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754) 
                                                    Suppressed: java.lang.ClassNotFoundException: com.instagram.app.InstagramAppShell
                                                     at java.lang.Class.classForName(Native Method)
                                                     at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
                                                     at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
                                                     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
                                                            ... 13 more
                                                  Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

Symptoms:

  • All of the apps I've installed force closes
  • Their package names and the generic logo shows up on the launcher instead of their app name and logo
  • They simply don't work

To people planning to flag this as a duplicate, these answers don't work/are outdated/not applicable (not a live system/no root access):

  • From 5.1.1 onwards, apps to be installed as system apps needs to be located in a subfolder under /system/priv-app/. For example, if you planned to install Termux as a system app, you'd have to place the Termux APK under something like /system/priv-app/com.termux/. You'd also have to change the appropriate permissions and ownership, and to set the correct SELinux context. – Death Mask Salesman Sep 17 '16 at 15:49
  • @DeathMaskSalesman I just moved an APK in /system/app (Stock Android 6.0.1 - Nexus 6), didn't bother to change permissions from rwx-rwx-rwx to rw-r-r, didn't follow naming convention and simply soft-rebooted the system. Post reboot I found my app installed as a system app. So yours is a sweeping generalization, I would say. :-) – Firelord Sep 17 '16 at 16:02
  • 1
    @DeathMaskSalesman How do I set an app's SELinux context on an offline system? – PNDA Sep 17 '16 at 17:11
  • @Firelord Yeah, mine is primarily a convention, but just dropping the desired APK into /system/app didn't work on my CM12.1: any app would force close anytime I opened it. – Death Mask Salesman Sep 17 '16 at 20:04
  • @DeathMaskSalesman SAME, although I've placed them in their individual folders, but still nothing. I've also tried installing them as a user app then moving the folder from /data/app to /system/app. – PNDA Sep 18 '16 at 4:35
2

Okay, I got it working. Here's how I did it:

  1. Copy the APK file to /system/app/some-folder/ or /system/priv-app/xyz-folder/.
    • Keeping them in their own folders may/will prevent conflicts. Some apps want to have their libs and other files extracted and placed alongside the APK in specific folders, although they're pretty rare.
    • Try checking out some folders of other system apps. Notice that some of them have a lib or other folder beside the APK.
    • That's why almost all of the apps in the folders mentioned above have their APKs inside their own folders.
    • Following step 1 is usually enough.
  2. Change the APK file's context using the command
    • chcon u:object_r:system_file:s0 /path/to/apk-file.apk
    • Or, if you copied it into its own folder, run chcon -R u:object_r:system_file:s0 /folder/where/the/APK/is/saved.

If the context isn't changed, Android won't treat your app as a system app. It will show up on the launcher as an app with a generic icon and zzz.package.name as the name.

In ye olde days (e.g. Gingerbread), you simply had to copy the APK in /system/app/ and set proper permissions. Times have changed.

  • As a supplement to your answer, some apps even require you to extract and place its libs in a specific folder too - if only the APKs are there, their icons show normally, but will complain about missing libs in logcat once you start them. – Andy Yan Nov 1 '16 at 7:57
  • @AndyYan Exactly. I typed that while making the answer, but decided it wasn't important enough to mention :) – PNDA Nov 1 '16 at 7:58
  • How would one go about doing that extraction @AndyYan? – RubberDuck Nov 15 '17 at 15:55
  • @RubberDuck I haven't had the need to do such a procedure, but if I remember what I read correctly, if you don't put such libs there, the app will throw errors in logcat, telling you it needs what libs at what location. The libs themselves should be self-contained within the APK, extract those and put in respective locations. – Andy Yan Nov 15 '17 at 16:04
  • @AndyYan I think it has something to do with SELinux, at least on my specific phone. Good to know that Chinese-made phones (Alcatel, unfortunately) have some level of system security. I was customizing the phone on the NAND level for someone and ran across this issue. – PNDA Nov 15 '17 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.