Android BroadcastReceiver inside service: issues - java

I am currently trying to create an Activity in Android with the capabilities of communicating with a started BroadcastReceiver inside of a service but I can't manage to do it well. I don't really know what the problem could be since (I think) I have followed all necessary steps.
In addition, I have other Activities which can communicate with this BroadcastReceiver without any problems. The code that I am using for the one I am having problems with is the following:
Registration of the name of the action in file ActivityList.java (Another activity):
public static final String ACTION1 = "com.test.ActionOne";
public static final String ACTION2 = "com.test.ActionTwo";
Registration of the actions with IntentFilter in the file GestTree.java which extends a Service:
Inside onCreate():
IntentFilter filter;
filter = new IntentFilter();
filter.addAction(ActivityList.ACTION1);
filter.addAction(ActivityList.ACTION2);
rec = new Receptor(); // This is a class which extends BroadcastReceiver
registerReceiver(receptor, filter);
Inside the function onReceive() of the private class Receptor of GestTree.java which extends BroadcastReceiver:
public final void onReceive(final Context context, final Intent intent) {
String action = intent.getAction();
if (action.equals(ActivityList.ACTION1)) {
Log.d(tag, "Test Passed!");
}
}
The definition of the service and the Activity State3Activity(the one I want to communicate with the service) in AndroidManifest.xml:
<activity
android:name="State3Activity"
android:label="#string/app_name" >
</activity>
<service
android:name="GestTree"
android:enabled="true"
android:label="#string/app_name" >
</service>
Code inside State3Activity.java:
public class State3Activity extends Activity {
Button mButton;
EditText editText_Name;
EditText editText_Desc;
private final String tag = this.getClass().getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.state3_layout);
mButton = (Button)findViewById(R.id.button_myButton);
editText_Nombre = (EditText)findViewById(R.id.editText_Name);
editText_Descripcion = (EditText)findViewById(R.id.editText_Desc);
mButton.setOnClickListener(
new View.OnClickListener()
{
public void onClick(View view)
{
Intent intent;
intent = new Intent();
intent.setAction(ActivityList.ACTION1);
// I have tried with all this combination of lines
// but none of them works
//intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
//intent.setClass(State3Activity.this, GestTree.class);
//intent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(intent);
}
});
}
There is where the problem comes. The intent never enters on the onReceive() function of the class when I press the button. What am I leaving?

Are you sure your service started? If you have not start the service, the method of onCreate() will not be executed, and the receiver will not be registed.

Related

How to unregisterReceiver from an activity

I start a service from activity button click that fire a service class and start Broadcastreceiver and it's run in background but I want to unregisterReceiver with a button click from same activity class.it seem not working.I added receiver class to menifest.
Here is my code.
Activity button click for registerreceiver
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent svc = new Intent(this, DemoService.class);
startService(svc);
});
DemoService.class
public class DemoService extends Service {
static final String LOGGING_TAG = "MyDemo";
private static Alarm1 tickReceiver =new Alarm1();
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startId){
super.onStart(intent, startId);
Log.v(LOGGING_TAG, "DemoService.onStart()");
}
#Override
public void onCreate(){
super.onCreate();
Log.d(LOGGING_TAG, "DemoService.onCreate()");
registerReceiver(
new Alarm1(),
new IntentFilter(Intent.ACTION_TIME_TICK));
}
}
Activity button click for unregisterReceiver
unreg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DemoService demo=new DemoService();
demo.unreg();
});
And receiver class
public class Alarm1 extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("tag","working");
}
How can I unregisterReceiver from unreg button click.
If I click in unreg button it show me error java.lang.IllegalArgumentException: Receiver not registered:
create a method for unregistering Receiver in Service class. And call the service with action like.
Intent svc = new Intent(this, DemoService.class);
svc.setAction("com.package.UN_REGISTER");
startService(svc);
and in Service class handle them in onStartCommand ()
like
if(intent.getAction().equals("com.package.UN_REGISTER")
//call your unregister method
Add action in Manifest in your service Tag
<IntentFilter>
<action name = "com.package.UN_REGISTER">
</IntentFilter>
You should use Bound Services for this. Check link for implementation and usage
If you want to correctly register and unregister a BroadcastReceiver. The BroadcastReceiver passed in registerReceiver() and unregisterReceiver() must be the same instance, so is the Context instance be invoked. Because the implement uses Context and BroadcastReceiver instances to uniquely map to a "Register operation".

Service containing BroadCastReceiver not functioning correctly

Please see edits before answering!
I have an app which contains a BackgroundService class:
public class BackgroundService extends Service {
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter();
filter.addAction("com.spotify.music.playbackstatechanged");
filter.addAction("com.spotify.music.metadatachanged");
filter.addAction("com.spotify.music.queuechanged");
registerReceiver(receiver, filter);
Log.e("Playing:", "APP IS PLAYING");
Notification notification = new Notification();
startForeground(1, notification);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long timeSentInMs = intent.getLongExtra("timeSent", 0L);
String action = intent.getAction();
if (action.equals(BroadcastTypes.METADATA_CHANGED)) {
String trackId = intent.getStringExtra("id");
String artistName = intent.getStringExtra("artist");
String albumName = intent.getStringExtra("album");
String trackName = intent.getStringExtra("track");
int trackLengthInSec = intent.getIntExtra("length", 0);
// Do something with extracted information...
} else if (action.equals(BroadcastTypes.PLAYBACK_STATE_CHANGED)) {
boolean playing = intent.getBooleanExtra("playing", false);
Log.e("Playing:","TRUE");
}
}
};
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
static final class BroadcastTypes {
static final String SPOTIFY_PACKAGE = "com.spotify.music";
static final String PLAYBACK_STATE_CHANGED = SPOTIFY_PACKAGE + ".playbackstatechanged";
static final String METADATA_CHANGED = SPOTIFY_PACKAGE + ".metadatachanged";
}
}
and this is declared in my manifest:
<service
android:name=".BackgroundService"
android:enabled="true" >
<intent-filter>
<action android:name="com.spotify.music.playbackstatechanged" />
<action android:name="com.spotify.music.metadatachanged" />
<action android:name="com.spotify.music.queuechanged" />
</intent-filter>
</service>
So essentially my objective is to have my BackgroundService initialized when my app is opened, and to have it continue to run in the Background doing whatever I need it to do. As of now, I am using logs to determine whether my "setup" is working, but when I run my app, I am unable to see an logs even after I tested all actions that should have triggered my BroadCastReceiver. Furthermore, my persistent notification should have changed had my service been running, but it does not...
Edit::
So, I added logs to my BackgroundService's onCreate() and onReceive() methods, however, neither seem to be appearing. Im wondering, do I need to do something in my launcher activity to initialize the service? Furthermore, no notification is shown so I assume the Service is not being started for some reason...
Latest Edit:
So I added the following code to my Main activity to see if it would make a difference:
startService(new Intent(this,BackgroundService.class));
And after debugging my app, I began to see the following error:
java.lang.RuntimeException: Unable to create service com.aurum.mutify.BackgroundService: java.lang.SecurityException: Isolated process not allowed to call registerReceiver
pointing to my BroadCast Receiver class.
Intent services are designed for short tasks. And your intent handling method is empty.
If you need long running task in the background use standard service and call start foreground. This will minimize chance of system destroying your service.
To learn more go here
EDIT
Try overriding onStartCommand method. this method is called when service is started and usually you do all stuff here. Remember that there are 3 options to return.
Edit 2:
try something like this
in on create
PendingIntent pi;
BroadcastReceiver br;
Intent myIntent;
#Override
public void onCreate()
{
super.onCreate();
myIntent = new Intent("something")
if(Build.Version.SDK_INT >= 16) //The flag we used here was only added at API 16
myIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//use myIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); if you want to add more than one flag to this intent;
pi = PendingIntent.getBroadcast(context, 1, myIntent, 0);
br = new BroadcastReceiver ()
{
public void onReceive (Context context, Intent i) {
new thread(new Runnable()
{
public void run()
{
//do something
}
}).start();
}
};
And then in on start command
this.registerReceiver(br, new IntentFilter("something"));

Notification.Builder does not create a notification

Im trying to create a notification from an edittext and broadcast receiver. In my first Activity the user should input a message and push the broadcast button. I want to take that string and create a notification from it and open a new activity that displays the message. I am doing all the notification work in my broadcast receiver class.
I have looked around onlne at examples and other peoples code but im not sure what im not getting right. The application loads up just fine and the broadcast button sends the broadcast to the receiver and Logs the string but the notification is never created.
Thanks for any help.
Broadcast class that sends broadcast message:
public class BroadcastReceiverActivity extends Activity
{
EditText et;
Button btn1;
public static String BString = "HappyHemingway";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast_receiver);
et = (EditText)findViewById(R.id.et1);
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String message = et.getText().toString();
send(message);
}
});
}
/*
* This function creates an intent and
* sends a broadcast from the message
* parameter passed in.
*/
protected void send(String msg)
{
Log.i("msg", msg);
Intent i = new Intent();
i.putExtra("message",msg);
i.setAction(BString);
sendBroadcast(i);
}
}
Receiver class that creates notification:
public class Receiver extends BroadcastReceiver
{
// #SuppressLint("NewApi")
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action!=null&&action.equals("HappyHemingway"))
{
String msg = intent.getStringExtra("message");
Log.i("Received",msg);
Intent i = new Intent(context,ViewNotification.class);
i.putExtra("message",msg);
PendingIntent pi = PendingIntent.getActivity(context, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(context).
setSmallIcon(0).setAutoCancel(true).setTicker(msg).
setWhen(System.currentTimeMillis()).setContentTitle("New Notification!").
setContentText(msg).setContentIntent(pi);
NotificationManager mgr = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification n = builder.build();
mgr.notify(0, n);
Log.i("Received again",msg);
}
}
}
notification viewer class that is never launched
public class ViewNotification extends Activity
{
String text;
TextView txttext;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.viewnotification);
NotificationManager notificationmanager;
notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationmanager.cancel(0);
Intent i = getIntent();
text = i.getStringExtra("message");
txttext = (TextView) findViewById(R.id.text);
txttext.setText(text);
Log.i("made it", "made it made it made it");
}
}
manifest
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".BroadcastReceiverActivity"
android:label="#string/app_name" >
<action android:name="android.intent" />
<category android:name="android.intent.category.LAUNCHER" />
</activity>
<activity android:name=".ViewNotification"></activity>
<receiver android:name="Receiver">
<intent-filter>
<action android:name="HappyHemingway">
</action>
</intent-filter>
</receiver>
</application>
</manifest>
Hopefully its just a simple error I'm overlooking.This is my first time using Android Studio instead of Eclipse but I dont see how that could make any difference under than my unfamiliarity with the IDE.
Anything helps
thanks.
I'm not sure why I had setSmallIcon(0.)
When I changed it to setSmallIcon(R.drawable.ic_launcher) everything worked fine.

Running background service through shortcut

So I want to launch a service from a shortcut. I know that this is not possible to do directly, so I've set up a activity with the sole purpose of starting the service.
The aim of my service is to send an intent to another app and then 5 seconds later send another so I've used a CountDownTimer to do this.
However, when I launch the Activity that starts the service from the shortcut (this is getting confusing) it launches the apps UI. I don't want this, as I want it to be a background service.
What am I doing wrong. I've only just got into development, so it could be something obvious, but I've been battling with this for a few days now.
For some reason when I run it from the service it just launches the app straight away...
When I run it straight from the invisible activity it runs properly for the 1st 5 seconds fine and then loads the app...
I can't figure out why it's loading the app at all.
I've included as much info as I can that would be relevant.
Any help is appreciated!
My service:
public class Pop1_5Service extends IntentService {
public Pop1_5Service() {
super("Pop1_5Service");
}
#Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
new CountDownTimer(5000, 2500) {
public void onTick(long millisUntilFinished) {
Intent i = new Intent(INTENT_ACTION);
Bundle b = new Bundle();
b.putInt(BUNDLE_VERSION_CODE, 1);
b.putString(BUNDLE_STRING_NAME, "POP1");
b.putString(BUNDLE_STRING_VALUE, "1");
i.putExtra(BUNDLE_NAME, b);
sendBroadcast(i); }
public void onFinish() {
Intent i = new Intent(INTENT_ACTION);
Bundle b = new Bundle();
b.putInt(BUNDLE_VERSION_CODE, 1);
b.putString(BUNDLE_STRING_NAME, "POP1");
b.putString(BUNDLE_STRING_VALUE, "1");
i.putExtra(BUNDLE_NAME, b);
sendBroadcast(i); }
}
}.start();
}
}
Activity that launches service:
public class Pop1_5Activity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, Pop1_5Service.class);
startService(intent);
finish();
}
}
Subsection of Manifest:
<activity
android:name=".Pop1_5Activity"
android:theme="#android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".Pop1_5Service" />
And the 'Create a Shortcut' Activity:
public class CreateShortcutActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent shortcutintent = new Intent(this, Pop1_5Activity.class);
ShortcutIconResource iconResource = Intent.ShortcutIconResource.fromContext(this, R.drawable.ic_launcher);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutintent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Pop1_5");
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
setResult(RESULT_OK, intent);
finish();
}
}
From the look of things, it looks like CreateShortcutActivity does nothing.
Your LAUNCHER is Pop1_5Activity, so when the user presses the app icon, this Activity will run, and it launches the Service.
All the code you have showed us are "invisible", the two Activities finish() themselves, and the Service is a Service.
You might want to look at how your BroadcastReceiver handles your broadcast. For instance, does it create another Activity through PendingIntent? Is the Activity created invisible?
Maybe you should try creating a pending Service instead of pending Activity in the BroadcastReceiver.

Listening for downloads when application is minimized

I am trying to create an application that listens for downloads and performs an action upon hearing it. The key here is that I want the application to do this even when it's minimized (like when a user downloads from the browser). The following code does not seem to be tripping the receiver:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("did download");
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
String downloadPath = intent.getStringExtra(DownloadManager.COLUMN_URI);
System.out.println(downloadPath);
}
}
};
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
}
Anyone know what's wrong?
Your almost there just move your BroadcastReceiver to a separate file . Do what you want with the received String downloadPath. In this example I save it to SharedPreferences.
public class MyBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(final Context context, Intent intent) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = settings.edit();
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
String downloadPath = intent.getStringExtra(DownloadManager.COLUMN_URI);
editor.putString("downloadPath", downloadPath);
editor.commit();
}
}
}
In your manifest add this and edit the action
<receiver android:name=".MyBroadcastReceiver " >
<intent-filter>
<action android:name="PUT YOUR ACTION HERE DownloadManager.ACTION_DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
Just declare the broadcast receiver in manifest. More about the differences between the dynamically register and statically register, please see BroadcastReceiver

Categories

Resources