I am working on Android app.Firstly, I am not familiar with BroadcastReceiver. I need to create an app in which, if install app have specific package like "com.whatsapp" a broadcast receiver will show the Toast
public class PackageAddedReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Package Installed: ", Toast.LENGTH_LONG).show();
}
}
Manifest
<receiver android:name=".receiver.PackageAddedReceiver" android:label="Package added Receiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
How can I add BroadcastReceiver for the specific package?
Try this
public class PackageAddedReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Uri data = intent.getData();
String mypkg="package:com.pck.name";
Log.e("DATA",data+"");
Log.e( "Action: " ,intent.getAction());
if(mypkg.equals(data.toString())){
Toast.makeText(context, "Package Installed: ", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(context, "not match ", Toast.LENGTH_LONG).show();
}
}
Manifest code
<receiver android:name=".PackageAddedReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
A. Create BroadcastReceiver class (implement onReceive): you can extract the data related to package
import android.content.*;
import android.net.Uri;
import android.util.Log;
public class PackageChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
Uri data = intent.getData();
Log.d(TAG, "Action: " + intent.getAction());
Log.d(TAG, "The DATA: " + data);
}
}
B. Declare receiver with intent-filter in AndroidManifest.xml:
<receiver android:name="PackageChangeReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
The receiver should be registered programmatically as below :
val packageAddedReceiver = PackageAddedReceiver()
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addAction(Intent.ACTION_PACKAGE_FIRST_LAUNCH)
intentFilter.addAction(Intent.ACTION_PACKAGE_INSTALL)
intentFilter.addDataScheme("package")
registerReceiver(packageAddedReceiver, intentFilter)
for further explanation check CommonsWare answer in the link
Can't receive broadcasts for PACKAGE intents
Related
I am trying to send string from app to app.
First app called "send" has only "MainActivity" class and layout:
private void sendMsg(){
final TextView msg = (TextView) findViewById(R.id.sendText);
Button snd = (Button)findViewById(R.id.sendButton);
snd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!msg.getText().toString().trim().equals("")){
Intent intent = new Intent("Updated");
intent.setAction(Intent.ACTION_SEND);
intent.putExtra("TEXT", msg.getText().toString().trim());
intent.setType("text/plain");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent(new ComponentName("com.example.rec","com.example.rec.broadcastReciver"));
getApplicationContext().sendBroadcast(intent);
}else{
Toast.makeText(getApplicationContext(), "Write text that You want to broadcast!", Toast.LENGTH_LONG).show();
}
}
});
}
Second app called "rec" has two classes "broadcastReciver" and "MainActivity".
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
zoviBroadCast();
}
private void zoviBroadCast(){
broadcastReciver brcv = new broadcastReciver();
registerReceiver(brcv,
new IntentFilter("action"));
}
}
broadcastReciver:
public class broadcastReciver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent)
{
//String data = intent.getStringExtra("TEXT").trim();
if (intent != null)
{
String sIntentAction = intent.getAction();
if (sIntentAction != null && sIntentAction.equals("action"))
{
String data = intent.getStringExtra("TEXT").trim();
Toast.makeText(context, data, Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(context,"Something went wrong",Toast.LENGTH_SHORT).show();
}
}
}
}
I also added lines between tag "receiver" in "AndroidManifest.xml":
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rec">
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".broadcastReciver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="action" />
</intent-filter>
</receiver>
</application>
</manifest>
What application should do is when I type something in first application and send it another over button it should "broadcast" (show) toast at second app.
My second application is not showing any data when run.
Nowadays it is essential to specify an action in intent filter of your broadcast receiver.
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_ACTION">
</action>
</intent-filter>
</receiver>
When sending the broadcast, you need to set exactly the same action to the intent you send.
Intent i = new Intent();
i.setAction("android.intent.action.MY_ACTION");
context.sendBroadcast(i);
Notation of action name may be not very important to get your code working, but I recommend to give names related to the package of your sending app.
For example: "com.username.example.myApplication.ACTION_EXAMPLE"
I've some problem with Oreo and Broadcast Receiver on Boot. My method work for earlier version of Android, but with Oreo (Huawei P20 Lite with Pie) it doesn't work.
The Log.e in the Boot Receiver is not displayed in the LogCat and the action in BootService onCreate is not executed (No Log in log cat).
Boot Receiver
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "Boot Receiver : Boot Start Service : AlarmNotification");
if ( Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) ) {
Intent myIntent = new Intent(context, BootService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(myIntent);
} else {
context.startService(myIntent);
}
}
}
}
I've set the permissions in the Manifest file
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".BootReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service
android:name=".BootService"
android:enabled="true"
android:exported="true">
</service>
BootService
The Boot Service works on earlier versions of Android
public class BootService extends Service {
public BootService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
//Is fired by the Boot Receiver... on Boot !
Context context = this;
Log.e(TAG, "Start Alarm");
//Do something with the code
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
}
Perhaps I forget something, or do I something wrong ? Can somebody help me on this case, I already tested multiple solutions from StackeOverflow and read the doc, but for me it's not very clear for this case.
Thanks
I am trying to create a custom solution, to notify on SMS Receive.
I found some solutions on Stackoverflow, but they are not working, can anybody help me, where i am wrong. Below is my code.
public class MainActivity extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast toast = Toast.makeText(context,"Message Received", Toast.LENGTH_LONG);
toast.show();
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My notification")
.setContentText("SMS Received");
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, mBuilder.build());
}
}
and Manifest file:
<receiver android:name=".MainActivity"
android:enabled="true"
android:exported="true"
>
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
Try this:
<receiver
android:name=".IncomingSmsReceiver"
android:permission="android.permission.BROADCAST_SMS"
android:priority="1000">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
public class IncomingSmsReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
String messageBody = "no data";
String messageFrom = "no data";
for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
messageBody = smsMessage.getMessageBody();
messageFrom = smsMessage.getDisplayOriginatingAddress();
}
Log.d("Sms:", messageBody + " " + messageFrom);
}
}
}
I needed to restore alarm after reboot for this I added this broadcast receiver:
public class ClsRestartAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Logging.logMessage("Broadcast");
Intent i = new Intent(context, BootService.class);
context.startService(i);
}
}
}
and registered in manifest like this:
<receiver android:name=".classes.ClsRestartAlarm"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
and as result of broadcast I'm doing this:
public class BootService extends IntentService {
public BootService() {
super("boot service");
}
#Override
protected void onHandleIntent(Intent intent) {
AlarmManagerUtils.setStartAlarm();
AlarmManagerUtils.setEndAlarm();
}
}
I guess I'm not receiving BOOT_COMPLETE broadcast in ClsRestartAlarm class, because after restart alarm was not set and I was unable to get notification(the starting alarm start a job scheduler for sending notification and end alarm cancels job scheduler)also I have BOOT_COMPLETE permission like this:
<uses-permission android:name="ANDROID.PERMISSION.RECEIVE_BOOT_COMPLETED"/>
Use WakefulBroadcastReceiver instead. This is my workable solution:
public class BRAutoStart extends WakefulBroadcastReceiver {
private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";
#Override
public void onReceive(Context ctx, Intent intent) {
_A.APPCTX = ctx.getApplicationContext();
if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
//code
}
}
}
<receiver android:name=".BRAutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
I declared in AndroidManifest permission and receiver
<uses-permission android:name="android.permission.REAL_GET_TASKS"/>
<receiver android:name=".UninstallIntentReceiver">
<intent-filter android:priority="0">
<action android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
<data android:scheme="package" />
</intent-filter>
</receiver>
And here is my java class receiver
public class UninstallIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String[] packageNames = intent.getStringArrayExtra("android.intent.extra.PACKAGES");
if(packageNames!=null){
for(String packageName: packageNames){
Log.d("User selected: ",packageName);
}
}
}
When I open settings of other apps it works well - I get notification
(I can see in logs package name of chosen application), but
when I open settings my own application, I don't receive anything