How to restart a service in android? - java

has anyone know how to restarting a service in android?? i have a service that called when device is booting.. and i have an option.java for saving my configuration..
if i editing a configuration in option.java, then i must restarting my service to takes the effect..
i only know how to start a service and after it running, i don't know how to restart it after a new configuration was made.. any idea??
startService(new Intent(this, ListenSMSservice.class));

Just stop the service and start it again
stopService(new Intent(this, ListenSMSservice.class));
startService(new Intent(this, ListenSMSservice.class));

In your element:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2) In your element (be sure to use a fully-qualified [or relative] class name for your BroadcastReceiver):
<receiver android:name="com.example.MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
public class MyBroadcastreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, MyService.class);
context.startService(startServiceIntent);
}
}
for more elaboration : this

So by observer-observable design pattern, I meant making use of FileObserver class provided by Android.
For example, here is a snippet from WallPaperManagerService.java from android's source code:
So, in your case, you would create a file observer (see sample code below) on the config file, and each time this config file changes, you will read all the values from your (already running) service.
Hope you got the essence of the idea.
/**
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
* that the wallpaper has changed. The CREATE is triggered when there is no
* wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
* everytime the wallpaper is changed.
*/
private final FileObserver mWallpaperObserver = new FileObserver(
WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE | DELETE | DELETE_SELF) {
#Override
public void onEvent(int event, String path) {
if (path == null) {
return;
}
synchronized (mLock) {
// changing the wallpaper means we'll need to back up the new one
long origId = Binder.clearCallingIdentity();
BackupManager bm = new BackupManager(mContext);
bm.dataChanged();
Binder.restoreCallingIdentity(origId);
File changedFile = new File(WALLPAPER_DIR, path);
if (WALLPAPER_FILE.equals(changedFile)) {
notifyCallbacksLocked();
}
}
}
};

Related

how to set up an nfc reader app that won’t open on its own if the app is closed

I’m doing this application that should read some nfc tags.
It is a kind of treasure hunt and who scans all the tags wins.
I structured the application so that there is an initial login and a set of data is saved in a database so that you can keep track of the players who scanned the tags.
I followed a tutorial to create an activity that can read tags. (Only one line of text should be read from the tags)
This is the code I put in the manifest
<uses-permission android:name="android.permission.NFC"/>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter>
This is the activity code
public class scanActivity extends AppCompatActivity {
private TextView scanView;
private PendingIntent pendingIntent;
private IntentFilter[] readfilters;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
scanView=findViewById(R.id.scanView);
try {
Intent intent= new Intent(this,getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
pendingIntent=PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
IntentFilter intentFilter = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
IntentFilter textFilter = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED,"text/plain");
readfilters = new IntentFilter[] {intentFilter, textFilter};
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
readTag(getIntent());
}
private void enableRead(){
NfcAdapter.getDefaultAdapter(this).enableForegroundDispatch(this,pendingIntent,readfilters,null);
}
private void disableRead(){
NfcAdapter.getDefaultAdapter(this).disableForegroundDispatch(this);
}
#Override
protected void onResume() {
super.onResume();
enableRead();
}
#Override
protected void onPause() {
super.onPause();
disableRead();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
readTag(getIntent());
}
private void readTag(Intent intent) {
Parcelable[] messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
scanView.setText("");
if(messages != null){
for (Parcelable message:messages){
NdefMessage ndefMessage = (NdefMessage) message;
for (NdefRecord record : ndefMessage.getRecords()){
switch (record.getTnf()){
case NdefRecord.TNF_WELL_KNOWN:
scanView.append("WELL KNOWN ");
if (Arrays.equals(record.getType(),NdefRecord.RTD_TEXT)){
scanView.append("TEXT: ");
scanView.append(new String(record.getPayload()));
scanView.append("\n");
}
}
}
}
}
}
}
Currently when I approach a tag, the phone tries to open a task, but it ends up reopening the application and it does not even open the task with the textview on which the content of the tag should be written.
I would need to make sure that the application does not reopen again when I approach a tag, but simply switch to the next activity, keeping the previous ones.
Also, I would like to prevent the app from opening itself when approaching a tag.
If the above requests are impossible. I need at least to be able to create an activity that reads the tags without opening other activities.
I thank in advance for those who tried to help me <3.
To prevent the App from being automatically opened automatically when approaching the Tag then remove the intent-filter entries in your manifest
If you don't want the Activity paused and resumed when a Tag is detected then don't use the older NFC API of enableForegroundDispatch use the newer and better API of enabledReaderMode as this will deliver the Tag data to a new Thread in your current activity without pausing and resuming your current activity.
Java example of enableReaderMode

Broadcast receiver not working when app is closed

So I have two different apps made, one sends a broadcast and another receives it and displays a toast. However, when I close the receiver app the broadcast is no longer received by the second app even though I defined the receiver in the manifest file.
The broadcast sender in the MainActivity of app1.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button)findViewById(R.id.button2);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent();
i.setAction("com.example.ali.rrr");
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(i);
Log.e("Broadcast","sent");
}
});
}
App 2 broadcast receiver:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Toast.makeText(context, "Broadcast has been recieved!", Toast.LENGTH_SHORT).show();
Log.e("SUCCESS", "IN RECIEVER");
//throw new UnsupportedOperationException("Not yet implemented");
}
App 2s Manifest:
<?xml version="1.0" encoding="utf-8"?>
<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">
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.ali.rrr" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Main2Activity"
android:label="#string/title_activity_main2"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
After registering my BroadcastReceiver (BR) statically in the manifest, applying the proper intent filters, using JobIntentService (and registering it in the manifest) to handle the work that was called from my BR, I was still getting inconsistent results.
Once all of what I listed above has been done you should be able to send an ADB command to activate your broadcast and process the work in your service even if the app is closed. This was working for me some of the time, but not all of the time.
This article describes limitation to BRs.
"As of Android 3.1 the Android system excludes all receiver from receiving intents by default if the corresponding application has never been started by the user or if the user explicitly stopped the application via the Android menu" (AKA a user executes Force Stop)
When I start the app by debugging it, then swipe it closed on my device, my ADB command never activates my BR. However, after my debugging session is over, when I open up the app on my device and swipe it closed, I can activate my BR through ADB commands.
This occurs because when you debug an application, then manually swipe it closed on the device, Android considers this a Force Stop hence why my BR cannot be activated until I re-open the app on the device without debugging.
Scoured the internet for hours, and wasn't able to find my solution, so I thought I'd post it here just in case some poor unfortunate soul is encountering the same weird functionality I was.
Happy coding :)
First of all you need to use the Service for this functionality to work.
In the Activity you can start and stop the service by using the below codes.
// to start a service
Intent service = new Intent(context, MyBrodcastRecieverService.class);
context.startService(service);
// to Stop service
Intent service = new Intent(context, MyBrodcastRecieverService.class);
context.stopService(service);
Then you can use the below service
public class MyBrodcastRecieverService extends Service
{
private static BroadcastReceiver br_ScreenOffReceiver;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
registerScreenOffReceiver();
}
#Override
public void onDestroy()
{
unregisterReceiver(br__ScreenOffReceiver);
m_ScreenOffReceiver = null;
}
private void registerScreenOffReceiver()
{
br_ScreenOffReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d(TAG, "ACTION_SCREEN_OFF");
// do something, e.g. send Intent to main app
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(br_ScreenOffReceiver, filter);
}
}
I faced this issue recently. The BroadcastReceiver was working fine even if the app was removed from the background in the emulator and Samsung phones. But it failed to start my app in Chinese manufactured phones like Realme, Mi etc. While struggling to find a way to fix this I found that in the app details page there is battery optimisation settings where the Auto-launch feature was disabled. After I enabled it the app was working fine and BroadcastReceiver was able to start the app. I was unable ti find a way to enable this setting programmatically but I found this question which helped me direct the user to that setting page.
You can go through below solution;
Activity.java
Intent intent=new Intent(MainActivity.this,BroadcastService.class);
startService(intent);
BroadcastService.java
public class BroadcastService extends Service {
private static MusicIntentReceiver br_ScreenOffReceiver;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
registerScreenOffReceiver();
}
#Override
public void onDestroy()
{
}
private void registerScreenOffReceiver()
{
br_ScreenOffReceiver = new MusicIntentReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
Log.e("AAAAAAAAAA", "Headset is unplugged");
break;
case 1:
Log.e("AAAAAAAAA", "Headset is plugged");
break;
default:
Log.e("AAAAAAAAAAAA", "I have no idea what the headset state is");
}
}
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
registerReceiver(br_ScreenOffReceiver, filter);
}
}
Menifest
<service android:enabled="true" android:name=".BroadcastService" />
Try this way..
Intent i = new Intent();
i.setAction("com.example.ali.rrr");
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
i.setComponent(
new ComponentName("PackageNameApp2","PackageNameApp2.MainActivity"));
sendBroadcast(i);

Android BroadcastReceiver won't register

I'm trying to add a simple broadcast receiver to my audio application, so that I can mute everything when the user clicks their ACTION_MEDIA_BUTTON on their headset. I've read that you can either register it in the manifest, or dynamically in the code. I have gone down the path of registering it in the code, as I need to call methods within my main activity class to react to the media button press. For some reason however, my BroadcastReceiver just will not register, and I can't find anything that explains why (grey hairs increasing).
The following is what I have in MainActivity.java:
public class MainActivity extends Activity {
public IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
public BroadcastReceiver MediaButtonIntentReceiver =
new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
KeyEvent event = (KeyEvent) intent
.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
Log.e("INFO", "Media Button Pressed");
MuteAll();
}
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Register media button event receiver
intentFilter.addAction("android.intent.action.ACTION_MEDIA_BUTTON");
intentFilter.setPriority(10000);
this.registerReceiver(MediaButtonIntentReceiver, intentFilter);
}
#Override
protected void onDestroy() {
super.onDestroy();
// Unregister media button event receiver
unregisterReceiver(MediaButtonIntentReceiver);
}
};
I am certain that the BroadcastReceiver doesn't register, as wrapping the register as below gives me a toast confirming it is null:
if (registerReceiver(MediaButtonIntentReceiver, intentFilter) == null)
{
Toast.makeText(this, "Could not register receiver", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Receiver registered", Toast.LENGTH_LONG).show();
}
EDIT:
I've also tried the following based on suggestions so far:
Reading through - http://developer.android.com/training/managing-audio/volume-playback.html
I tried registering my receiver within the manifest like so...
<receiver android:name="com.mydomain.myapp.MainActivity$MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
And then added the following example code:
public AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Start listening for button presses
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
Eclipse complained that mContext didn't resolve to anything, so I added the following:
private Context mContext;
Then it complained about the "mContext.getSystemService(Context.AUDIO_SERVICE)" portion, saying "Type mismatch: cannot convert from Object to AudioManager"
So I added a cast to AudioManager:
public AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
And then added the suggested receiver registration code:
am.registerMediaButtonEventReceiver(MediaButtonIntentReceiver);
To which it complained about "registerMediaButtonEventReceiver" saying "The method registerMediaButtonEventReceiver(ComponentName) in the type AudioManager is not applicable for the arguments (BroadcastReceiver)"
Clearly I'm doing something wrong here. I've entered their example code as shown, yet it doesn't even compile.
--- END EDIT -----------------------------
Hoping someone out there can please help me. Please let me know if I need to supply anything further.
A Receiver for the ACTION_MEDIA_BUTTON action should be registered with AudioManager's registerMediaButtonEventReceiver() method, instead of the regular registerReceiver() method in the Activity. Unlike normal dynamic Receiver registration, however, this method takes the class as the parameter, instead of an instance of the class. The easiest way to this is to create a separate class file for it:
public class MediaButtonIntentReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
...
}
}
And we would need this Receiver listed in the manifest, as well:
<receiver android:name=".MediaButtonIntentReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
Now, the example in the link we've referred to is wrong, as the registerMediaButtonEventReceiver() method is expecting a ComponentName object, not just the name of the Receiver class itself. We need to change the example as follows:
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
am.registerMediaButtonEventReceiver(
new ComponentName(this, MediaButtonIntentReceiver.class));
And, as we've established, you don't need the mContext field, as you are in anActivity Context, and can just use getSystemService() without qualification. You can also do away with the IntentFilter object, as the listing in the manifest takes care of that already.

Shake Device to Launch App

I am using this to work with Shake, and that works fine for me, but i wanna launch application when user shake their device,
see my code below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
transcript=(TextView)findViewById(R.id.transcript);
scroll=(ScrollView)findViewById(R.id.scroll);
shaker=new Shaker(this, 1.25d, 500, this);
}
#Override
public void onDestroy() {
super.onDestroy();
shaker.close();
}
public void shakingStarted() {
Log.d("ShakerDemo", "Shaking started!");
transcript.setText(transcript.getText().toString()+"Shaking started\n");
scroll.fullScroll(View.FOCUS_DOWN);
}
public void shakingStopped() {
Log.d("ShakerDemo", "Shaking stopped!");
transcript.setText(transcript.getText().toString()+"Shaking stopped\n");
scroll.fullScroll(View.FOCUS_DOWN);
}
So here is my question, how can i launch an application by shaking my device ?
You should write Android Service that will start your activity during shake. That is all. Services run in the background even if Activity is not visible
Service can be started eg. during device boot. This can be achieved using BroadCastReceiver.
Manifest:
<application ...>
<activity android:name=".ActivityThatShouldBeLaunchedAfterShake" />
<service android:name=".ShakeService" />
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
BootReceiver:
public class BootReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent intent = new Intent(context, ShakeService.class);
context.startService(intent);
}
}
Service:
public class ShakeService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
... somewhere
if(shaked) {
Intent intent = new Intent(getApplicationContext(), ActivityThatShouldBeLaunchedAfterShake.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Write a separate app for Shake detection. On detection of shake, fire an intent with the package name of app, you want to launch:
Intent intent = new Intent (<PackageNameOfAppToBeLaunched>);
startActivity (intent);
Well What you need is Two different activity Where first One Detects your Shake which need to run all time in background and than call the new actual app you want to run on shake.
You can run your background activity you have to use class which will keep your activity run in background for long time(Continuously) you can use classes Like FutureTask or Executor (you can not use AsyncTask for this).
Whenever the thread passes command to Your Application open after Shake the Background process stops and command goes to app means you need to again immediately start background process after the actual app closed.
You need to write the code to launch the application to foreground from background while the shake started. This link will help you to do so.

Registering a headset button click with BroadcastReceiver in Android

I have a headset with single button and want to do a simple Toast when the button is pressed.
Right now I have the following code:
public class MediaButtonIntentReceiver extends BroadcastReceiver {
public MediaButtonIntentReceiver() {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
return;
}
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
// do something
Toast.makeText(context, "BUTTON PRESSED!", Toast.LENGTH_SHORT).show();
}
abortBroadcast();
}
}
And my main activity is the following:
public class mainActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
MediaButtonIntentReceiver r = new MediaButtonIntentReceiver();
registerReceiver(r, filter);
}
}
Nothing happens though when I push the button though.
I'm pretty sure something is wrong with my permissions/xml in the manifest. Here's the receiver XML so far:
<receiver android:name=".MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
....
and:
<uses-permission android:name="android.permission.BLUETOOTH" />
I notice in LogCat that when I press the button I get an error from "BluetoothIntentReceiver" saying "onReceive() Action : android.intent.action.MEDIA_BUTTON"
Just wanted to answer my own question in case others come across similar issues.
The code does work, just I wasn't seeing the Toast because I had another headset button controller app installed (and running in the background), so I guess it took priority over mine. However when I put
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);//"android.intent.action.MEDIA_BUTTON"
MediaButtonIntentReceiver r = new MediaButtonIntentReceiver();
filter.setPriority(1000); //this line sets receiver priority
registerReceiver(r, filter);
It was able to work even with the other app installed. Also, you don't need both the above AND the XML, one or the other is fine as ways of registering the intent receiver.
Here's what I've got that's working in Android 4.2.2
In my manifest.xml I do this:
<receiver android:name=".MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
NB: this is instead of calling registerReceiver.
In my Main Activity's onCreate I need to call the AudioManager:
((AudioManager)getSystemService(AUDIO_SERVICE)).registerMediaButtonEventReceiver(
new ComponentName(
getPackageName(),
MediaButtonIntentReceiever.class.getName()));
I have found it will work without the AudioManager call, but not for long!
You shouldn't use setPriority
You register your broadcast receiver in the manifest
You then register your broadcast receiver using:
AudioManager#registerMediaButtonEventReceiver
The argument to registerMediaButtonEventReceiver is a ComponentName that points your broadcast receiver.
For a fully documented answer for Android >4.0 have a look here:
BroadcastReceiver for ACTION_MEDIA_BUTTON not working
If you don't want to use BroadcastReceiver, you can do this for Android >5.0 (API level 21 LOLLIPOP) using the MediaSession described here: https://stackoverflow.com/a/39413753/1386969

Categories