I want to start a service in a static way. So from my activity I call
SpeechActivationService.makeStartServiceIntent(
this.getApplicationContext(),
"WordActivator");
Here is the actual class that extends from service class http://dpaste.com/hold/928115/ As you can see there are several log points, e.g. in the onCreate method.
This is not logged. Only if I put log text in makeStartServiceIntent method it appears, however not in the onCreate method.
Here's the makeStartServiceIntent method:
public static Intent makeStartServiceIntent(Context context,
String activationType) {
Intent i = new Intent(context, SpeechActivationService.class);
i.putExtra(ACTIVATION_TYPE_INTENT_KEY, activationType);
return i;
}
In manifest file I have
<service android:name="root.gast.speech.activation.SpeechActivationService"/>
Any ideas why the service is not started?
Aside from you not posting code showing startService(), it looks like the package name of your Service in the manifest doesn't match your SpeechActivationService class (assuming the code link you posted is the actual SpeechActivationService class in your project, and not just a class you copied from).
<service android:name="com.mkyong.android.SpeechActivationService"/>
Your makeStartService() just creates an Intent for you. You don't seem to actually be firing that intent off to start the service. Try like this
Intent i = SpeechActivationService.makeStartServiceIntent(this,"WordActivator");
startService(i);
Note that if this.getApplicationContext() works you are likely already inside of a Context object so simply using this should work also.
Related
I have a basic level at android, and I still have problems understanding the life cycle of apps. So I'm doing this test.
Let's say I have an app that has three classes: the MainActivity, class A and class B.
Class A receives "external" intents. I've defined the receiver in the manifest and it works well. Now, what I want is that, when class A receives and intent, it should send a "local" intent using LocalBroadcastManager. If I register the receiver on the Main Activity class it works (it receives the local intent), so I know the code for registering the receiver is ok. However, if I do it on class B, it never arrives. That is perfectly normal because I have never used/defined class B in any place, so, since class B is never executed in any way the receiver never gets registered.
Now, here are my questions (please, correct me if what I'm about to say is wrong, because I'm not sure I've understood it):
Since we don't know when the external intent will come, maybe the Main Activity (or the class B if it's defined as activity, for example) is destroyed. However, the intent will always arrive to class A because we put the receiver part in the manifest and it will broadcast the local intent. What should class A do so we are sure the other class receives it? (specially if I want that the receiver goes in class B) Should class B be something like a singleton, to be sure that one and only one class B exists, and then class A can check and create if needed class B before sending the intent? Would there be better way to do this? Maybe local broadcasts are not thought to be used in this cases (when the receiver maybe doesn't exist)?
In short, what I want is to have a class that is not in the main activity and that can be able to receive local broadcasted intents at any time, even if the app is not actively used and Android has destroyed/paused/etc it.
Thanks for your help!
Update: I'll put some code so I can show you what I've want.
First, this is class ExternalReceiver (what I previously called class A). This class just receives the external intent and broadcasts a local intent within my app:
public class ExternalReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TestApp","ExternalReceiver: I've received the intent "+intent.getAction());
Intent localIntent = new Intent("TestIntent");
localIntent.putExtra("text", "Hello, I'm just a test");
LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
}
}
Then, this is my MainActivity class. If I uncomment the registerReceiver, MainActivity would correctly receive the local intent and log the content of "text". My problem with this is that if the activity is destroyed, then the local intent wouldn't arrive here (I'd also prefere if another class is the receiver):
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TestApp","MainActivity - OnCreate()");
// If I'd registered the receiver here, it would work as long as the activity exists:
//LocalBroadcastManager.getInstance(this).registerReceiver(localReceiver, new IntentFilter("TestIntent"));
}
private BroadcastReceiver localReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TestApp","MainActivity: I've received a local intent with text: "+intent.getStringExtra("text"));
}
};
}
Now, this is LocalReceiver (the class I've called B before). What I want is to receive the local intent here. Since I've never used this class (not in the manifest and not in the code) it will never arrive here, so right now it will never receive the intent. I've extended Activity too, but I haven't put it in the manifest. In fact, I don't need it to be an activity, but I thought maybe it would be good because then I could override onCreate. Suggestions are very welcome as how should I define this class:
public class LocalReceiver extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I register the receiver.
LocalBroadcastManager.getInstance(this).registerReceiver(localReceiver, new IntentFilter("TestIntent"));
}
private BroadcastReceiver localReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TestApp","LocalReceiver: I've received a local intent with text: "+intent.getStringExtra("text"));
}
};
}
Finally this is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testapp.localbroadcast"
android:versionCode="2"
android:versionName="#string/app_version" >
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/testapp"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.testapp.localbroadcast.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="com.testapp.localbroadcast.ExternalReceiver" >
<intent-filter>
<action android:name="com.testapp.localbroadcast.TEST" />
</intent-filter>
</receiver>
</application>
</manifest>
Now, to test everything, I'd send this intent through adb:
adb shell am broadcast -a com.testapp.localbroadcast.TEST -n com.testapp.localbroadcast/.ExternalReceiver
What I want:
Have a receiver on ExternalReceiver so it just listens to some intent
(com.testapp.localbroadcast.TEST in my example). It works now.
ExternalReceiver then should broadcast a local intent to other class (LocalReceiver) within the app.
That class (LocalReceiver) receives the intent and then just do something
(probably without even updating any UI).
My problem:
I want to be sure that the class that receives the local intent works even after a long time. For example, if the activity doesn't exists, then ExternalReceiver should do something to assure the other class receives the local intent. My guess: make LocalReceiver an activity and then, if needed, the ExternalReceiver class should start it if it doesn't exist. I still don't get how the ExternalReceiver works even if the MainActivity is destroyed. Shouldn't MainActivity be created or resumed as soon as any ExternalReceiver starts working?
I did a previous version of this within the Main Activity and everything worked ok as long as everything existed. Now I want to separate my code and make it ready to work even if Android has closed it. Maybe I haven't understood how this kind of things works, so any suggestion is very much welcome.
Thanks again for your help!
You should put some line of code so that we can understand what you exactly need.
Also this is code of class which receive Broadcast.
Please put this as Global class.
And put some code or exact your requirement for perfect solution.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Boradcast your local contents from here
}
}
Suppose that, I have an android app that launches browser with some url supplied when it receives a message containing some prespecified data(some code or something)
For this to work, my class inherits broadcastReceiver class(to receive messages).
Now as soon as it recieves a msg, it needs to launch another activity i.e browser and for this the same class needs to inherit Activity class also. But it is not possible, a class can not inherit 2 other classes.
My problem looks roughly like,
import android.content.broadCastReceiver;
import android.app.Activity;
public class sms extends broadCastReceiver{
onReceive(){
....
....
here it needs to launch another activity
}
}
Could anyone suggest how I can implement this...?
I tried creating an instance of Activity subclass inside and invoking startActivity method, but it did not work
The method for starting an activity is aContext.startActivity(new Intent(aContext, MyNewActivity.class)); Be sure that you place the proper declarations in the manifest though.
Look here.
For clarification, you can start an activity using a context. So just keep a short term reference to one and you should be fine.
EDIT:
You need to have a reference of a usable context to even create an activity. Then you do the following (using the passed reference!)
Intent i = new Intent(passedContext, MyNewActivity.class);
i.setFlags(Context.FLAG_ACTIVITY_NEW_TASK);
passedContext.startActivity(i);
Here i can launch a new activity using,
Intent i = new Intent(Context, MyNewActivity.class);
i.setFlags(Context.FLAG_ACTIVITY_NEW_TASK);
Context.startActivity(i);
here, context was passed to onReceive method of broadCastReceiver as a parameter, i can use that context itself. I can not use getBaseContext method here.
I am intercepting sms messages with some information in them. Then in my SmsListener I'm creating notification to show in statusbar.
Then, when user clicks on a notification I want
Bring MainActivity to foreground (If such activity does not exist yet it should be created)
Pass to it data from the sms
Perform some ui changes basing on this data in this MainActivity
My activity is defined as
<activity
android:name=".MainActivity"
android:screenOrientation="sensor"
android:label="#string/app_name"
android:launchMode="singleTask"/>
Activity is launched as
Intent i = new Intent();
i.setClass(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Also in my activity I have overridden method onNewActivity
#Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
// I have data from broadcast in intent variable passed to this activity
processDataFromBroadcast(intent);
}
It works fine if the MainActivity already exists but if MainActivity does not exist it is started however onNewIntent was not called
Then I tried to invoke processDataFromBroadcast from onCreate: processDataFromBroadcast(getIntent()).
First time data is passed correctly from my broadcast to the activity.
However if MainActivity is sent to background and then again brought to foreground either onCreate or onNewIntent is called and processDataFromBroadcast is executed again with intent sent by broadcast and thus my MainActivity is updated with data from broadcast every-time the app is bringing to foreground - the latter is unwanted, how can I make my activity to forget this intent after first handling.
Here is sample application.
For an activity to launch only one instance of itself, have a look at the <activity> manifest element, and particularly android:launchMode. You want to configure it with either singleTask or singleInstance.
To pass data to your activity, you add data to the Intent you use to open it. To pass data with the intent, use the putExtra() methods of the intent before sending it off, and getExtra() methods to retrieve them in your receiving activity.
I'm assuming that you know roughly how intents work, but if not you could learn more about intents by taking a look at this Android developers article.
in case your problem is still unresolved, as I was just running into the same issue, here's how I solved it:
I am putting a timestamp as intentId as an extra upon the intent during it's creation. the first time, I am handling the intent in onCreate() or onNewIntent() I am reading the intentId and store it as the last intent handled. so the next time onCreate() or onNewIntet() is invoked I can check the intentId and if it equals the id of the last intent handled, I ignore it! It don't know if this helps in your case, maybe you can adopt it.
To keep intentId independent from activity lifecycles you could persist it in the userdefaults.
I agree that one would expect calling setIntent(new Intent()) in onNewIntent should do the trick.
It it late to answer, but it might be helpful to others looking for the solution.
Just add below lines of code :
Intent mIntent = new Intent(this, SplashActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // You need this if starting the activity from a service
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
Where SplashActivity is the name of initial application that is the first screen of your application.
Hope it helps. :)
How can I fire a method instead of an Activity in my code?
I want to use the AddProximityAlert() method from the LocationManager but it needs an Intent to work and I don't want to call another activity since the method I want to fire is in the same Activity from where I'm using AddProximityAlert()
Goes like this:
public clase onCreate()
{
......
LocationManager LM; // already initialized
LM.addProximityAlert(lat,long,radio,expiration,INTENT) <--- This INTENT needs to call myMethod()
}
public void MyMethod()
{
.......
}
I have several hours trying to find a solution for this, and all I find is for calling another activity, please be as much specific, even if I have to do something with the manifest.xml because I haven't used intents before.
Thanks
What if you create a android service (or broadcast receiver might be more appropriate) within the same application that handles the intent.
You don't leave the same pid, it's a non-visual service and you never leave your activity?
You can call your service directly by creating a intent the references it's class name directly.
intent = new Intent(context, my_service.class);
It then will hit the services "onStartCommand()" function and you can do your intent processing from there.
I created a broadcast receiver in the main activity and the background service which is sending broadcast intents. The application crashes each time I try to run it and the Log displays the following error message:
10-04 13:30:43.218:
ERROR/AndroidRuntime(695):
java.lang.RuntimeException: Error
receiving broadcast Intent {
action=com.client.gaitlink.CommunicationService.action.LOGIN_STATUS_UPDATE
(has extras) } in
com.client.gaitlink.GaitLink$LoginStatusReceiver#431690e8
The broadcast message is sent from CommunicationService class in the following method:
private void announceLoginStatus(){
Intent intent = new Intent(LOGIN_STATUS_UPDATE);
intent.putExtra(SERVER_MESSAGE, mServerResponseMessage);
intent.putExtra(SESSION_STRING, mSessionString);
sendBroadcast(intent);
}
where
String LOGIN_STATUS_UPDATE = "com.client.gaitlink.CommunicationService.action.LOGIN_STATUS_UPDATE"
in the main activity the following broadcast reveiver is defined:
public class LoginStatusReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String serverMessage = intent.getStringExtra(CommunicationService.SERVER_MESSAGE);
String sessionString = intent.getStringExtra(CommunicationService.SESSION_STRING);
userInfo.setSessionString(sessionString);
saveSettings();
}
}
and registered in onResume method:
IntentFilter loginStatusFilter;
loginStatusFilter = new IntentFilter(CommunicationService.LOGIN_STATUS_UPDATE);
loginStatusReceiver = new LoginStatusReceiver();
registerReceiver(loginStatusReceiver, loginStatusFilter);
And the manifest file includes the following:
<activity android:name=".GaitLink"
android:label="#string/app_name">
<intent-filter>
...
<action android:name="com.client.gaitlink.CommunicationService.action.LOGIN_STATUS_UPDATE" />
</intent-filter>
</activity>
I would really appreciate if anyone could explain why the Log displays the message above and the application crashes.
Thanks!
I solved it by adding intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); when you start a new activity.
If not started from an activity, intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); is needed.
You have two Intent filters; you only need one. If you register the BroadcastReceiver via registerReceiver(), only use the IntentFilter that is the second parameter to that API call -- do not also put an <intent-filter> element in the <activity> in the manifest.
I do not know for certain if that is your problem, but it certainly does not help.
Have you gone step by step in the debugger to find exactly where the crash occurs?
One thing to look out for is if you are overriding any Android lifecycle events that you are properly calling the base class's constructor when necessary.
when you are looking at error logs, you are just looking at first few lines.
but surprisingly actual problem is mentioned in lines way below it-
Fatal Error : Main
error receiving broadcast...bla bla bla <- you are just looking here only
at x.y.z.....
at x.y.z......
at x.y.z.....
at x.y.z......
caused by : ........................... <- but actual problem is here!
at x.y.z.....
at x.y.z......
at x.y.z.....
at x.y.z......
I'm not sure that you can understand what I want to say, because of my English.
I think this line of code is cause of a problem:
userInfo.setSessionString(sessionString);
My project was wrong because I want to:
int i = Integer.parseint(intent.getExtars("9"));
and you register two times.
i think you have to use life cycle method onPause() and onResume() Method for unregister and register broadcast intent.
I found that making sure the intent was run from the original activity and putting things into one class got rid of the entire issue.
This is a very old question, but I think many people would still be searching answers for it. My situation is quite similar to this one.
What I wanted to do, is to call finish() in the child activity when certain events occur in parent activity i.e. by sending the broadcast message from MainActivity to Child Activity.
Following is the code in MainActivity when the event is occurred (e.g. when network connection is broken etc etc):
Intent intent = new Intent("ACTIVITY_FINISH");
intent.putExtra("FinishMsg","ACTIVITY_FINISH: Network broken.");
sendBroadcast(intent);
In the child activity's OnResume() function:
IntentFilter quitFilter = new IntentFilter();
quitFilter.addAction("ACTIVITY_FINISH");
registerReceiver(m_quitReceiver, quitFilter);
In the child activity's OnPause() function:
unregisterReceiver(m_quitReceiver);
Within the child activity class:
BroadcastReceiver m_quitReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, final Intent intent)
{
if (intent.getAction().equalsIgnoreCase("ACTIVITY_FINISH"))
{
Log.d("INFO", intent.getExtras().getString("FinishMsg"));
finish(); // do here whatever you want
}
}
};
Hope this helps.
It might because you keep registering BroadcastReceiver. I made that mistake before as a result it returns this error. Make sure BroadcastReceiver only registered once.
Ok what worked for me was declaring the onNotification method as follows:
window.onNotification = function(event) {
alert('onNotification called!');
};