PayPal callback does not trigger after login to the PayPal account - android

I'm stuck with the next issue.
I integrated PayPal sdk into my android app.
implementation 'com.paypal.checkout:android-sdk:0.6.1'
My app has an underscore in the package name so I have to use ‘App links’. I tested it in the test-app, all works fine like on the first screenschoot.
But in the main app when I successfully log in to a paypal account and redirect back to the app, the callback does not trigger.
I also figured out if I press on close button, callback yes triggers.
Also when I returns to the app I receive Intent like this:
app.mobile.main.app.name://paypalpay?code=C21AALAqib-oCkJXmgsoDPPbpAiYza7KJgVoA_01gzzYtawIsgofw0PmCpr186xkz1OY6tSQ....
Please write if you have any suggestions.
Thanks and have a nice day.
Here snippets of Manifest file and PayPalFragment.
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.mobile.main_app.name">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera" />
<application
android:name=".MyApplication"
android:allowBackup="false"
android:hardwareAccelerated="true"
android:icon="#mipmap/logo"
android:label="#string/app_name"
android:largeHeap="true"
android:requestLegacyExternalStorage="true"
android:roundIcon="#mipmap/logo"
android:supportsRtl="true"
android:theme="#style/MaterialTheme"
android:usesCleartextTraffic="true"
tools:replace="android:allowBackup">
<activity
android:name=".Ux.Activities.MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:excludeFromRecents="true"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustResize">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="paypalpay"
android:scheme="app.mobile.main.app.name" />
</intent-filter>
</activity>
</application>
</manifest>
PayPalFragment.kt
class PayPalFragment : Fragment() {
override fun onAttach(context: Context) {
super.onAttach(context)
PayPalCheckout.registerCallbacks(
onApprove = OnApprove { approval ->
approval.orderActions.capture { captureOrderResult ->
Log.i("tester", "OnApprove called.")
}
},
onCancel = OnCancel {
Log.i("tester", "OnCancel called.")
},
onError = OnError { errorInfo ->
Log.i("tester", "onError called.")
},
onShippingChange = OnShippingChange { shippingChangeData, shippingChangeActions ->
Log.i("tester", "onShippingChange called.")
}
)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val fragView = inflater.inflate(R.layout.fragment_pay_pal, container, false)
val payPalButton = fragView.findViewById<Button>(R.id.paypal_button)
payPalButton.setOnClickListener {
PayPalCheckout.startCheckout(
CreateOrder { createOrderActions ->
val order = Order(
intent = OrderIntent.CAPTURE,
appContext = AppContext(
userAction = UserAction.PAY_NOW
),
purchaseUnitList = listOf(
PurchaseUnit(
amount = Amount(
currencyCode = CurrencyCode.USD,
value = "10.00"
)
)
)
)
createOrderActions.create(order)
}
)
}
return fragView
}
}

So solution is to add default PayPal activity to AndroidManifest.xml
You just copy the code below and change YOUR-CUSTOM-SCHEME to what you declared in ReturnUrl in the PayPal developer account.
No need to create this activity, it comes with the PayPal SDK.
It will redirect you back into your app and trigger a PayPal payment sheet.
After the user has completed or canceled the payment, the corresponding callback will be called.
<activity
android:name="com.paypal.openid.RedirectUriReceiverActivity"
android:excludeFromRecents="true"
android:theme="#style/PYPLAppTheme">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="paypalpay"
android:scheme="YOUR-CUSTOM-SCHEME" />
</intent-filter>
</activity>

Related

Screen not turning on when alarm manager is fired in physical devices

I'm working on an android application and i need alarm manager to fire events at certain times , the code works fine and the notification fires in time but only in one scenario is not working when the screen is off , the device is not waking up and wait for notification to fire up , actually this works in emulators ( i guess because there is no such power saving mode like in some physical devices ) , I've looked up most topics and could not find any solution , any help would be appreciated Thank you .
Firing Alarm Manager
fun fireAlarmManager(context: Context , time : MutableList<Long>){
val intent = Intent(context, AlarmReceiver::class.java)
for (i in 0 until time.size){
if(time[i] > deviceTimeInMillis()){
list.add(time[i])
val pendingIntent = PendingIntent.getBroadcast(context,time[i].toInt(),intent,PendingIntent.FLAG_IMMUTABLE)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time[i],pendingIntent)
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP,time[i],pendingIntent)
}
}
}
setDataFromSharedPreferences(list)
}
Broadcast receiver
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context : Context?, intent : Intent?) {
wakeUp(context)
val serviceIntent = Intent(context,OnClearFromRecentServices::class.java)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
context!!.startForegroundService(serviceIntent)
} else {
context!!.startService(serviceIntent)
}
}
private fun wakeUp(context: Context?) {
val pm = context!!.getSystemService(Context.POWER_SERVICE) as PowerManager
val wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.FULL_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, "app::tag")
wakeLock.acquire(60000)
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val keyguardLock = keyguardManager.newKeyguardLock("TAG")
keyguardLock.disableKeyguard()
}
}
Alarm Service
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
fireNotification(this)
return START_STICKY
}
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.kotlin.quranapp">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".koin.BaseApplication"
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:largeHeap="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.QuranApp"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="false"
android:launchMode="singleInstance"
android:screenOrientation="portrait" />
<activity
android:name=".views.SplashActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".alarm.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver
android:name=".alarm.PlayerReceiver"
android:exported="false" />
<service android:name=".alarm.services.OnClearFromRecentServices" />
</application>
</manifest>

Why am I getting a MissingPluginException when using platform-specific code (Kotlin) in my Flutter app?

I've been trying to use Android code in a Flutter project to do audio-related tasks, and I've been following Flutter's guide to do so. However, when I try to call the method on the method channel, I've been getting a MissingPluginException that says that the method (getAudioSessionID) isn't implemented. I found a post on a similar issue, but it doesn't seem like it was solved. I put some print statements in MainActivity, but they aren't being called.
This is what the MainActivity class looks like in MainActivity.kt:
class MainActivity: FlutterActivity() {
private val CHANNEL = "XXX.XXX/eqAndroid"
override fun configureFlutterEngine(#NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
print("This is being called")
if (call.method == "getAudioSessionID") {
val audioSessionID = getAudioSessionID()
print(audioSessionID)
} else {
result.notImplemented()
print("else block in if/else statement")
}
}
}
private fun getAudioSessionID(): String {
return AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION
}
}
I defined a global variable for the method channel in a constants.dart file:
const eqAndroidPlatform = MethodChannel('XXX.XXX/eqAndroid');
, and this is the function that is supposed to invoke the getAudioSessionID method:
Future<void> getAudioSessionID() async {
String audioSessionID;
try {
final String result = await eqAndroidPlatform.invokeMethod('getAudioSessionID');
audioSessionID = 'Currently playing audio session ID is $result .';
} on PlatformException catch (e) {
audioSessionID = "Failed to get audio session ID: '${e.message}'.";
}
setState(() {
this.audioSessionID = audioSessionID;
});
}
This is the code in AndroidManifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="XXX.XXX.XXX">
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:name="${applicationName}"
android:icon="#mipmap/ic_launcher"
android:label="XXX">
<activity
android:name="com.ryanheise.audioservice.AudioServiceActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:windowSoftInputMode="adjustResize"
tools:ignore="Instantiatable">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.ryanheise.audioservice.AudioService"
android:exported="true" tools:ignore="Instantiatable">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver"
android:exported="true" tools:ignore="Instantiatable">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.AudioSessionReceiver">
<intent-filter>
<action android:name="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION"/>
</intent-filter>
</receiver>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

Crash on GoogleSignInClient.signInIntent - A required meta-data tag in your app's AndroidManifest.xml does not exist

I use Google OAuth to let users sign in to the android app via Google account. When the user taps the Google login button it immediately crashes with information that
A required meta-data tag in your app's AndroidManifest.xml does not exist. You must have the following declaration within the <application> element: <meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
doesn't exists in AndroidManifest when it does. google_play_services_versions value is 12451000, hardcoding it doesn't changes anything
Stacktrace
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mateuszsiedlecki.whatsthere, PID: 578
java.lang.IllegalStateException: A required meta-data tag in your app's AndroidManifest.xml does not exist. You must have the following declaration within the <application> element: <meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
at com.google.android.gms.common.GooglePlayServicesUtilLight.isGooglePlayServicesAvailable(com.google.android.gms:play-services-basement##17.1.1:17)
at com.google.android.gms.common.GoogleApiAvailabilityLight.isGooglePlayServicesAvailable(com.google.android.gms:play-services-basement##17.1.1:5)
at com.google.android.gms.common.GoogleApiAvailability.isGooglePlayServicesAvailable(com.google.android.gms:play-services-base##17.1.0:96)
at com.google.android.gms.auth.api.signin.GoogleSignInClient.zzg(com.google.android.gms:play-services-auth##18.0.0:9)
at com.google.android.gms.auth.api.signin.GoogleSignInClient.getSignInIntent(com.google.android.gms:play-services-auth##18.0.0:18)
at com.mateuszsiedlecki.whatsthere.login.SocialLoginFragment.googleSignIn(SocialLoginFragment.kt:101)
at com.mateuszsiedlecki.whatsthere.login.SocialLoginFragment.access$googleSignIn(SocialLoginFragment.kt:24)
at com.mateuszsiedlecki.whatsthere.login.SocialLoginFragment$onViewCreated$2.onClick(SocialLoginFragment.kt:70)
at android.view.View.performClick(View.java:7161)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:7133)
at android.view.View.access$3500(View.java:804)
at android.view.View$PerformClick.run(View.java:27416)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:241)
at android.app.ActivityThread.main(ActivityThread.java:7604)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Code
class SocialLoginFragment : Fragment() {
val gso: GoogleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestProfile()
.requestId()
.build()
private val facebookRequestedData = "id,first_name,last_name,email,picture,name"
private var fbCallbackManager: CallbackManager = CallbackManager.Factory.create()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_social_login, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
FacebookSdk.sdkInitialize(this.context)
LoginManager.getInstance().registerCallback(
fbCallbackManager,
object : FacebookCallback<LoginResult?> {
override fun onSuccess(loginResult: LoginResult?) {
Log.d("login", "Facebook Login")
val fbUser = getFbUserData(loginResult!!.accessToken)
UserDataManager.user = fbUser
loginFinished()
}
override fun onCancel() {
Log.d("login", "Facebook Login Cancel")
}
override fun onError(exception: FacebookException) {
Log.d("login", "Facebook Login error")
}
}
)
val googleLoginButton = getView()?.findViewById<Button>(R.id.googleLogin)
googleLoginButton?.setOnClickListener {
googleSignIn()
}
val facebookLoginButton = getView()?.findViewById<Button>(R.id.facebookLogin)
facebookLoginButton?.setOnClickListener {
LoginManager.getInstance().logInWithReadPermissions(
this,
listOf("public_profile", "email")
)
}
val emailLoginButton = getView()?.findViewById<Button>(R.id.emailLogin)
emailLoginButton?.setOnClickListener {
val intent = Intent(this.context, EmailLoginActivity::class.java)
startActivity(intent)
}
val noLogin: Button = getView()?.findViewById<Button>(R.id.noLogin) as Button
noLogin.setOnClickListener {
(activity as LoginActivity?)?.openEmailFragment()
}
}
private fun googleSignIn() {
val mGoogleSignInClient: GoogleSignInClient = GoogleSignIn.getClient(
this.context!!,
gso
)
val signInIntent: Intent = mGoogleSignInClient.signInIntent // crashing here
startActivityForResult(signInIntent, 1)
}
...
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mateuszsiedlecki.whatsthere">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity android:name=".EmailLoginActivity" />
<activity
android:name=".osmMapsActivity"
android:label="#string/title_activity_maps" />
<activity android:name=".login.LoginActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id" />
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
</application>
</manifest>

Why don't my Android BroadcastReceiver messages arrive?

This is yet another question about why a BroadcastReceiver doesn't see the messages being sent to it. I've looked at a dozen examples and other questions their solutions seem the same as mine but mine doesn't work.
My receiver is in a service. Here's the manifest fragment:
<service android:name="com.madurasoftware.vmnotifications.services.BLEService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
The service registers the receiver like this:
private val messageReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive() called")
val message = intent.getStringExtra(BluetoothService.MESSAGE)
NotificationQueue.add(message)
}
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate() called")
val filter = IntentFilter()
filter.addAction(BluetoothService.MESSAGE_ACTION)
baseContext.registerReceiver(this.messageReceiver, filter )
}
override fun onDestroy() {
baseContext.unregisterReceiver(this.messageReceiver)
}
Because I am dynamically registering the receiver I don't add anything about it to the manifest.
I send from a button in my MainActivity like this:
Intent().also { intent ->
intent.setAction(BluetoothService.MESSAGE_ACTION)
intent.putExtra(BluetoothService.MESSAGE, "xyz")
sendBroadcast(intent)
}
Log.d(TAG, "sendBroadcast() called")
When I press the button I see that the logged sendBroadcast() message shows up, but the onReceive() log message does not. So it isn't being delivered.
Can anyone see why?
I'm using API 29 and this is my full manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.madurasoftware.vmnotifications">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:fullBackupContent="#xml/my_backup_rules">
<activity android:name=".ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.madurasoftware.vmnotifications.services.NotificationService"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service android:name="com.madurasoftware.vmnotifications.services.BLEService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
<service android:name="com.madurasoftware.vmnotifications.services.BluetoothService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
</application>
</manifest>
Thanks for any help

How to get action that android application is trying removed/uninstalled from device

When user want to uninstall app from android device, I want user uninstall button click event for that application.
I am getting event of application is removed from device, but I want to show pop-up before application is removed. I am trying to achieve same like doing in 'App Lock' application.
Here is my code to get application removed event through broadcast receiver. But I am totally blank about uninstall button click or before pop-up click. Please guide me in right direction.
Thanks in advance.
public class MainActivity extends Activity {
CustomBroadcastReceiver mApplicationsReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mApplicationsReceiver=new CustomBroadcastReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_PACKAGE_VERIFIED);
filter.addAction(Intent.ACTION_PACKAGE_INSTALL);
filter.addAction(Intent.ACTION_PACKAGE_FIRST_LAUNCH);
filter.addAction(Intent.ACTION_DELETE);
filter.addAction(Intent.ACTION_DEFAULT);
filter.addDataScheme("package");
registerReceiver(mApplicationsReceiver, filter);
}
}
public class CustomBroadcastReceiver extends BroadcastReceiver {
/**
* This method captures the event when a package has been removed
*/
#Override
public void onReceive(Context context, Intent intent)
{
System.out.println("Hello from CustomBroadcastReceiver");
if (intent != null) {
String action = intent.getAction();
System.out.println("L1123 : "+action);
if (action.equals(intent.ACTION_PACKAGE_REMOVED)) {
//Log the event capture in the log file ...
System.out.println("The package has been removed");
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bits.uninstallappdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_ADDED" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_CHANGED" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_INSTALL" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REPLACED" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- <receiver android:name=".CustomBroadcastReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_CHANGED" />
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
</intent-filter>
</receiver> -->
</application>
</manifest>
Please try to get the top activity in the task via ActivityManager, and check if it is the uninstall activity.
Core code:
ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity;
String packageName = topActivity.getPackageName();
String className = topActivity.getClassName();
Log.v(TAG, "packageName" + packageName);
Log.v(TAG, "className" + className);
if ("com.android.packageinstaller".equals(packageName)
&& "com.android.packageinstaller.UninstallerActivity".equals(className)) {
//Do anything you want here
}
The following permissions which you are using are granted to system apps only. Make sure you have rooted device to allow such permissions.
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />

Categories

Resources