Reputation: 401
I am working on rooted device. I have created an application to run as a system app. I have copied the apk file to sd card and then to /system/priv-app after mounting the /system directory from adb shell as su user. The manifest file looks as follows
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="abc.def.settings"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<service
android:name="abc.def.settings.service.SystemSettingsService" >
</service>
<receiver android:name="abc.def.settings.boot.DeviceBootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="abc.def.settings.start_after_reinstall"/>
</intent-filter>
</receiver>
</application>
</manifest>
Once I copied the apk to /system/priv-app i changed the permission to 777 from shell. The application is starting on device boot very much fine. But I am unable to start the service before rebooting. One of my limitations is that the device should not be rebooted to start this service.
I tried the following but none of them worked.
adb shell am startservice -n abc.def.settings/.SystemSettingsService
adb shell am startservice -n abc.def.settings/.service.SystemSettingsService
adb shell am startservice -a abc.def.settings.start_after_reinstall
adb shell am broadcast -a abc.def.settings.start_after_reinstall
adb shell am broadcast -a abc.def.settings.start_after_reinstall -f 32
Is there anything i am missing.!! Thanks in advance.
Upvotes: 1
Views: 7587
Reputation: 724
I know this is an old question, but I wanted to post an answer here for the sake of others who may wish to customise ROMs or install their own apps on existing devices that work with internal or restricted APIs. I had to search for quite some time to garner the information I provide here, since information can be tricky to find.
For a priv-app
APK to work correctly, or even at all depending on the permissions, it needs to be signed with the system key that has been used for key system apps in a ROM and for the framework JAR files (usually in /system/framework
).
In some cases (such as Chinese ROMs based on MediaTek CPUs, etc.), the APK signing keys being used are the standard Android AOSP (Android Open Source Project) signing keys, which can be found in the Android source code distribution. There are 4 default keys provided as part of the AOSP distribution, each coming as a private/public pair. Their names are:
media.pk8
media.x509.pem
platform.pk8
platform.x509.pem
shared.pk8
shared.x509.pem
testkey.pk8
testkey.x509.pem
If you want to add an APK to a ROM that has used these signing keys, you're in luck! I've included a script and some links to the needed files below for going through that process.
However, if you're trying to customise a ROM from a major manufacturer such as Samsung, you may find that you'll need to re-sign all system APK files with a new key to get your app to work in the /system/priv-app
directory.
You'll also need to modify the framework APKs for your ROM so they are signed by your new key as well, and as you can imagine this process is fraught with dangers as it could result in an unusable ROM if you miss something important. This process is outside the scope of the answer, but you can find some good resources for different manufacturers on XDA Developers. I'd link it but my reputation is too low at the moment for me to share more than two links.
If your app is using any of the internal APIs that are only available to signed privileged system apps, this step will be necessary for you to be able to call those APIs. These APIs include ones that are accessed using reflection, as well as direct calls to those APIs.
I see in your manifest that you're using at least two restricted permissions in your APK. Those are:
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
and
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
Without the signing, these permissions are pretty much useless, especially the WRITE_SECURE_SETTINGS
permission.
I wrote a small shell script that signs my priv-app
APKs when needed, and here's the source for that. You need to also zip-align
your APK once you've performed the signing process. It works on OS X/macOS and Linux:
#!/bin/bash
echo Signing with Android Platform key...
java -jar signapk.jar -w platform.x509.pem platform.pk8 <app-name-for-signing>.apk <app-signed-output>.apk
echo Zip-Aligning...
./zipalign -f 4 <app-signed-output>.apk <final-app-name-signed-zipaligned>.apk
echo Done!
echo
You'll need to obtain the signapk.jar
and zipalign
tools for your platform, and you can find those here:
[CROSS-PLATFORM] APK Sign/Zipalign/Install
You'll also need to grab the AOSP standard keys, which are available in many locations including https://github.com/android/platform_build/tree/master/target/product/security.
If you want to find out which signing key was used for the priv-app
APK files in your ROM, you can perform a two-step process using standard Java tools, so make sure you have the Java SDK (any flavour) installed, then follow the steps in this answer:
How do I find out which keystore was used to sign an app?
If you find the ROM is using an AOSP key, then you just need to sign your own APK file with the same key and drop it in the priv-app
directory for it to work correctly.
Upvotes: 7