Houston I have a problem, here it goes:
I have a broadcast receiver that runs when my app is updated, I've achieved that using this:
Android Manifest, inside <application> tag:
<receiver
android:name=".control.background.services.UpdateReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<data android:scheme="package" android:path="br.com.soutsapp.waiter.soutsw" />
</intent-filter>
</receiver>
And this BroadcastReceiver class:
public class UpdateReceiver extends BroadcastReceiver {
public UpdateReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)){
String packageName = context.getPackageName();
if(packageName.equalsIgnoreCase("br.com.soutsapp.Souts_v3")){
final Context appContext = context.getApplicationContext();
SharedPreferences sp = appContext.getSharedPreferences(ConstantUtils.SHARED_PREFERENCES, Context.MODE_PRIVATE);
String json = sp.getString(ConstantUtils.TAG_SHARED_PREFERENCES_USER_INFO, null);
UserModel user = null;
if(json != null){
user = new JsonParserUtils<>(UserModel.class).serialize(json);
}
if(user != null && user.getFacebookUserId() != null && user.getFacebookUserId().length() > 0){
FacebookSdk.sdkInitialize(appContext);
LoginManager.getInstance().logOut();
}
sp.edit().clear().commit();
Log.d("SOUTS", "Running broadcast receiver");
}
}
}
}
Inside my Launcher activity I've printed a log when onCreate ends;
And I got this two prints, when my app runs with a update:
06-28 21:58:48.629 24984-24984/br.com.soutsapp.Souts_v3 D/SOUTS:
Running onCreate EstablishmentActivity
06-28 21:58:51.572 24984-24984/br.com.soutsapp.Souts_v3 D/SOUTS:
Running broadcast receiver
As you can see, broadcast receiver runs 3 seconds after the Launcher activity, so here goes my question, is there a way to be sure that my BroadcastReceiver will run before my Launcher activity?
If not, how would you suggest I workaround this?
Related
I want to start services from Broadcast Receiver but Marshmallow and above SDK's will not callback. BOOT_COMPLETED is working fine with app foreground & background but CONNECTIVITY_CHANGE is not working on background .
My requirement is, i want to get callback when app with app foreground & background.
My manifest :
<receiver
android:name=".receivers.MessageBroadCastReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
My Broadcast Receiver:
public class MessageBroadCastReceiver extends BroadcastReceiver {
private static final String TAG = "MessageBroadCastReceive";
private Context ctx;
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "AppBroad " + intent.getAction());
this.ctx = context;
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
RestartMessageService();
} else if (intent.getAction().equals("android.net.conn.CONNECTIVITY_CHANGE")) {
RestartMessageService();
}
}
}
am tired to registered the Broadcast actions in my main activity its working fine on foreground, once i close my app it will not call (Marshmallow and above SDK's).
Registered code:
private void RegisterReceivers() {
try {
MessageBroadCastReceiver broadCastReceiver = new MessageBroadCastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
getBaseContext().registerReceiver(broadCastReceiver, intentFilter);
PrefManager.getInstance(this).setBroadcastReg(true);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
Please give me solution.
Advance thanks...
I have App A and App B. In App A I want to send broadcast to App B.
This is the code for App A:
final Intent intent = new Intent();
intent.setAction("com.pkg.perform.Ruby");
intent.putExtra("KeyName", "code1id");
intent.setComponent(new ComponentName("com.pkg.AppB", "com.pkg.AppB.MainActivity"));
sendBroadcast(intent);
And in App B - In MainActivity, I have MyBroadCastReceiver Class.
public class MainActivity extends Activity {
private MyBroadcastReceiver MyReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Receive broadcast from External App
IntentFilter intentFilter = new IntentFilter("com.pkg.perform.Ruby");
MyReceiver = new MyBroadcastReceiver();
if(intentFilter != null)
{
registerReceiver(MyReceiver, intentFilter);
}
}
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MainActivity.this, "Data Received from External App", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(MyReceiver != null)
unregisterReceiver(MyReceiver);
}
}
I am getting the error - Receiver is not registered.
First thing first declare the receiver in app B in the manifest file like this:
<receiver android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.pkg.perform.Ruby" />
</intent-filter>
</receiver>
when sending the broadcast add FLAG_INCLUDE_STOPPED_PACKAGES flag to the intent [src] because when you broadcast from app A to app B , app B might not be running, this flag insures that the broadcast reachs out even apps not running:
FLAG_INCLUDE_STOPPED_PACKAGES flag is added to the intent before it
is sent to indicate that the intent is to be allowed to start a
component of a stopped application.
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
In your case it will be like this:
final Intent intent=new Intent();
intent.setAction("com.pkg.perform.Ruby");
intent.putExtra("KeyName","code1id");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent(
new ComponentName("com.pkg.AppB","com.pkg.AppB.MyBroadcastReceiver"));
sendBroadcast(intent);
In App A: Send the broadcast here.
final Intent i= new Intent();
i.putExtra("data", "Some data");
i.setAction("com.pkg.perform.Ruby");
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
getApplicationContext().sendBroadcast(i);
In App B manifest
<receiver android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.pkg.perform.Ruby" />
</intent-filter>
</receiver>
In App B MainActivity: register the receiver oncreate(), and unregister onDestroy()
public class MainActivity extends AppCompatActivity
{
private MyBroadcastReceiver MyReceiver;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter("com.pkg.perform.Ruby");
if(intentFilter != null)
{
registerReceiver(MyReceiver, intentFilter);
}
}
#Override
protected void onDestroy()
{
super.onDestroy();
if(MyReceiver != null)
unregisterReceiver(MyReceiver);
}
}
In App B BroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String data = intent.getStringExtra("data");
Log.i("BR" ,"Data received: " + data);
}
}
There may be two cases :
Your appB is not running, hence the activity is not instantiated, and so the receiver is not registered.
Your activity is destroyed, means that you have unregistered your receiver that you registered via registerReceiver() in onCreate()
Solution :
Register your broadcast receiver in manifest.
Inside manifest of appB :
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="com.pkg.perform.Ruby" />
</intent-filter>
</receiver>
And comment out the line in appA
intent.setComponent(new ComponentName("com.pkg.AppB","com.pkg.AppB.MainActivity"));
Write the logic in MyBroadcastReceiver to display relevant data/launch new activity
MyReceiver is class not object. Create
myReceiver = new MyReceiver();
and put...........
registerReceiver(myReceiver,intentFilter);
If this helps some one and it works for me
In App A in activity or in a content provider-
Intent intent = new Intent("Updated");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent (new
ComponentName "com.exam.appA",
"com.exam.appA.DbaseChanged"));
getContext().sendBroadcast(intent);
In App B in the manifest
<receiver
android:name=".DbaseChanged"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="Updated" />
</intent-filter>
</receiver>
In App B Broadcast receiver class-
public class DbaseChanged extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent
intent) {
String act = intent.getAction();
if(act != null && act.equals("Updated") )
{
Toast.makeText(context, act ,
Toast.LENGTH_SHORT).show();
}
}
}
I needed to call setPackage("package_name") to ensure explicitness when I registered the broadcast receiver in the Manifest. I was then able to receive the data even if the app was closed completely.
// sending app sends broadcast
Intent intent = new Intent(ACTION_RECOMMEND);
intent.putExtra(LISTEN_RECOMMENDATION, "Triggered - Jhene Aiko");
intent.putExtra(WATCH_RECOMMENDATION, "Goblin - Kim Go-eun");
intent.setPackage("com.example.package.receiverapp");
sendBroadcast(intent);
//receiving app manifest registers receiver
<receiver
android:name=".ManifestRegisteredBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.random.action.RECOMMEND" />
</intent-filter>
</receiver>
I didn't need to add intent.setPackage(package_name) when registering the receiver via an activity, but this also meant that I couldn't get the data if the activity was destroyed (app closed, app in background for long period)
My issue here is more the result of the framework I'm using than Android itself. My app needs to register a ContentObserver after the user has installed a specific plugin associated with the AWARE framework. The framework has a sensor for installation of plugins, and sends a broadcast once this happens. Documentation can be found here: http://www.awareframework.com/installations/
I would like to accomplish this using a BroadcastReceiver.
I have a few questions regarding how to properly do this:
The way I interpret this documentation and Android is that if I register a BroadcastReceiver in my Manifest file with the intent filter "Installations.EXTRA_PACKAGE_NAME", every time a package is installed, it will activate my InstallationReceiver. If my understanding is still correct, I will be able to use getAction() on the received intent to parse the package name. Does this look like a correct understanding? Do intents works this way?
Is it proper to have my BrodcastReceiver in my Service class? Or should I make it a standalone class?
Did I register my receiver properly?
My MainService code:
package hcii.tracker;
public class MainService extends Service {
public static final Uri ACTIVITY_URI = Uri.parse("content://com.aware.plugin.google.activity_recognition.provider/plugin_google_activity_recognition");
public HashMap<Uri,ContentObserver> mContentObservers;
public void onCreate(){
Log.d("SERVICE", "Service created!");
Context context = this;
mContentObservers = new HashMap<Uri,ContentObserver>();
//Activate installations sensor
Aware.setSetting(context, Aware_Preferences.STATUS_INSTALLATIONS, true);
//Activate Accelerometer
Aware.setSetting(this, Aware_Preferences.STATUS_ACCELEROMETER, true);
//Set sampling frequency
Aware.setSetting(this, Aware_Preferences.FREQUENCY_ACCELEROMETER, 60);
Aware.setSetting(getApplicationContext(), "frequency_google_fused_location", 60,
"com.aware.plugin.google.fused_location");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.fused_location");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.activity_recognition");
sendBroadcast(new Intent(Aware.ACTION_AWARE_REFRESH));
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
try {
ContentObserver observer = mContentObservers.get(ACTIVITY_URI);
getContentResolver().unregisterContentObserver(observer);
mContentObservers.remove(ACTIVITY_URI);
} catch (IllegalStateException ise) {
Log.d("SERVICE", "No ContentObservers registered");
}
}
public class ActivityRecognitionObserver extends ContentObserver {
public Uri CONTENT_URI = Uri.parse("content://com.aware.plugin.google.activity_recognition.provider/plugin_google_activity_recognition");
public ActivityRecognitionObserver(Handler handler) {
super(handler);
}
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// Get the latest recorded value
Log.d("OBSERVER", "Change in activity data detected");
Cursor activity = getContentResolver().query(CONTENT_URI, null, null, null,
"activity_name" + "DESC LIMIT 1");
if( activity != null && activity.moveToFirst() ) {
// Here we read the value
String activity_name = activity.getString(activity.getColumnIndex("activity_name"));
if (activity_name.equals("in_vehicle")){
Aware.setSetting(getApplicationContext(), "frequency_google_fused_location", 60,
"com.aware.plugin.google.activity_recognition");
Log.d("OBSERVER", "Recognized in vehicle");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.activity_recognition");
}
else {
Aware.setSetting(getApplicationContext(), "frequency_google_fused_location", 180,
"com.aware.plugin.google.activity_recognition");
Log.d("OBSERVER", "Recognized on foot");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.activity_recognition");
}
}
if( activity != null && ! activity.isClosed() ) activity.close();
}
}
public class InstallationReceiver extends BroadcastReceiver {
public InstallationReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals("com.aware.plugin.google.activity_recognition")){
ActivityRecognitionObserver so = new ActivityRecognitionObserver(new Handler());
getContentResolver().registerContentObserver(ACTIVITY_URI, true, so);
mContentObservers.put(ACTIVITY_URI, so);
Log.d("SERVICE", "Observer registered");
}
}
}
}
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="hcii.tracker" >
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
tools:replace="android:icon, android:theme" >
<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>
<service
android:name=".MainService"
android:exported="false" />
<receiver android:name="hcii.tracker.MainService$InstallationReceiver" >
<intent-filter>
<action android:name="Installations.EXTRA_PACKAGE_NAME" >
</action>
</intent-filter>
</receiver>
...
There are several problems here:
1) You can use an inner class for your BroadcastReceiver, but if so it must be declared static, because Android needs to be able to instantiate the class itself using new. This is not possible in your current architecture (because the class is an inner class). In general it is better (easier) to use a stand-alone class for this.
2) Your Intent filter is wrong. The linked documentation from Aware indicates that the broadcast Intent is Installations.ACTION_AWARE_APPLICATION_ADDED, so your intent filter needs to look like this:
<intent-filter>
<action android:name="Installations.ACTION_AWARE_APPLICATION_ADDED"/>
</intent-filter>
3) Once you have declared the BroadcastReceiver correctly, it will be triggered whenever Aware adds a plugin. The package name of the installed plugin is put into an "extra" in the Intent. To determine which plugin has been installed, you need to do something like this:
public void onReceive(Context context, Intent intent) {
String packageName = intent.getStringExtra("Installations.EXTRA_PACKAGE_NAME");
if (packageName != null && packageName.equals("your.plugin.package.name") {
// Do your stuff here...
}
}
I am building an app that starts a service each time a call is being made, the first time I create a call the broadcast receiver starts the service and all is well.
But then the problem: Once I run the dialer again I get the following error in LogCat:
10-30 10:10:38.674: E/StrictMode(171): class com.android.phone.OutgoingCallBroadcaster; instances=2; limit=1
I have tried solving the problem by calling this command at the end of the onReceive:
this.abortBroadcast();
This removes the error, but also stops the service from running again, can anyone help me fix this problem, or is there anyone who has experienced this inconvieniance?
This is the receiver:
public class OutgoingCallReceiver extends BroadcastReceiver {
public OutgoingCallReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
// Extract phone number reformatted by previous receivers
String phoneNumber = getResultData();
if (phoneNumber == null) {
// No reformatted number, use the original
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
Intent in = new Intent(context, OutgoingCallHandler.class);
context.startService(in);
OutgoingCallHandler.phonenumber = phoneNumber;
}
}
And here are the declarations in the manifest:
<service
android:name=".IncomingCallHandler"
android:label="#string/title_activity_main" >
</service>
<receiver android:name=".OutgoingCallReceiver" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
All the help is very welcom!
Do not call abortBroadcast(), as the NEW_OUTGOING_CALL broadcast is an Ordered Broadcast. It has a final broadcast receiver with some post-processing and clean-up to do.
your context.startService(in); will not start another instance of your service if OutgoingCallHandler is still alive. Add a log message to your onStartCommand to check. And, See if you can avoid saving reference to OutgoingCallHandler.phonenumber = phoneNumber; from your onReceive
In one of my apps I use a subclass of Application (MyApplication) and a BroadcastReceiver (MyBroadcastReceiver) that's added to the Manifest. The BroadcastReceiver registers the actions android.intent.action.PACKAGE_ADDED and android.intent.action.PACKAGE_REPLACED.
These intents are fired when the APK is added to or replaced on a device. The app itself is not shown during the installation process so my question is: Will the Application subclass get started along with the app process?
Here's the code:
Manifest:
<application
...
android:name=".MyApplication" >
...
<receiver
android:name=".MyBroadcastReceiver" >
<intent-filter>
<action
android:name="android.intent.action.PACKAGE_ADDED" />
<action
android:name="android.intent.action.PACKAGE_REPLACED" />
<data
android:path="xxx.yyy.zzz"
android:scheme="package" />
</intent-filter>
</receiver>
</application>
MyApplication:
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Log.d(this.getClass().getName(), "onCreate");
// ...
}
#Override
public void onTerminate() {
// ...
super.onTerminate();
}
}
MyBroadcastReceiver:
public class MyBroadcastReceiver extends BroadcastReceiver {
public static final String TAG = "xxx.yyy.zzz.MyBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getDataString() != null) {
if (intent.getDataString().contains("xxx.yyy.zzz")) {
if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
Log.d(this.getClass().getName(), "onReceive(Package added)");
// ...
} else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
Log.d(this.getClass().getName(), "onReceive(Package replaced)");
// ...
}
}
}
}
}
Will the Application subclass get started along with the app process?
Yes. The Application object should be created before your BroadcastReceiver instance is created and called with onReceive().