Due to a broadcast behavior change since Android 3.1, your app must be started before it can receive the app installation/removal intents. See kabuko's answer in this thread.
The following receiver works for me on a Android 4.0 device (I have an activity in the app, first start the activity i.e. the app is also started, then the receiver can receive the broadcast).
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_CHANGED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
(some apps run a dummy sticky service to keep the app process alive, so that they can receive certain broadcasts)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…