I found a lot of information on stack about this, but no one has done this to the end.
At the beginning i add to android manifest this:
<receiver android:name=".gps.GpsLocationReceiver">
<intent-filter>
<action android:name="android.location.PROVIDERS_CHANGED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Next i trying to add a lot of code to my app.
At the beginning i implements to my activity LocationListner
According to the this: Detecting GPS on/off switch in Android phones
LocationListener should override this method:
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().matches("android.location.PROVIDERS_CHANGED"))
{
// react on GPS provider change action
}
}
But in my app, LocationListner override only this method:
#Override
public void onLocationChanged(Location location) {
}
What is wrong with this androidstudio ?
What i should do now ?
onReceive() is required for the BroadcastReceiver , onLocationChanged() is required and here you can get the changes of geo-location, determined by latitude and longitude:
#Override
public void onLocationChanged(Location location) {
Long myLongitude = location.getLongitude();
Long myLatitude = location.getLatitude();
}
if you don´t require this method in your class don´t implement LocationListener.
onReceive() method is from BroadcastReceiver class. You need to extend BroadcastReceiver first to override this method.
Follow the following steps:
1.Make your broadcast receiver class
public class NameOfYourBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final LocationManager lM = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (lM.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
// do something
} else {
// do something else
}
}
}
2. Register your BroadcastReceiver. For this add the following lines to your AndroidManifest.xml
<receiver android:name="com.yourpackage.NameOfYourBroadcastReceiver">
<intent-filter>
<action android:name="android.location.PROVIDERS_CHANGED" />
</intent-filter>
</receiver>
Related
I have my main activity that start a service (Location service) and I want that service to broadcast the new location each time a new location is found.
Thanks to the log I know the service is working and I have new locations every seconds or so, but I never get the broadcast.
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = "mainActivity";
private CMBroadcastReceiver mMessageReceiver = new CMBroadcastReceiver();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// Start Service
startService(new Intent(this, LocationService.class));
super.onCreate(savedInstanceState);
}
#Override
public void onResume()
{
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, new IntentFilter(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE));
super.onResume();
}
#Override
public void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
}
CMBroadcastReceiver.java
public class CMBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CMBroadcastReceiver";
public static final String RECEIVE_LOCATION_UPDATE = "LOCATION_UPDATES";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received broadcast");
String action = intent.getAction();
if (action.equals(RECEIVE_LOCATION_UPDATE))
{
Log.i(TAG, "Received location update from service!");
}
}
}
LocationService.java
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.i(TAG, "onLocationChanged " + location);
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Log.i(TAG, "Broadcast sent");
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyclemapapp.gpstracker">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar">
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LocationService" android:process=":location_service" />
</application>
I the log I can see that "Broadcast Sent" But I never get the "Broadcast Received"
Any help will would be greatly appreciated.
EDIT:
Edited how the intent was created in the location service as Shaishav suggested.
Still doesn't work.
LocalBroadcastManager does not work across processes. Your Service is running in a separate process.
You can either run your Service in the same process as the Activity - by removing the process attribute from the <service> element - or use some sort of IPC instead - e.g., by sending and receiving the broadcasts on a Context instead of LocalBroadcastManager.
In your LocationService, send local broadcast using:
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
<service android:name=".LocationService" android:process=":location_service" />
Your service is in a separate process from the activity. LocalBroadcastManager is only for use in one process. Either remove android:process from the <service>, or use some IPC mechanism (e.g., system broadcasts, properly secured).
I have an app with two activities: MainActivity, which contains a URL entry field where the user can enter a YouTube video URL and press a submit button, to start the second activity, VideoActivity, which displays some information about this video (fetched from another web server).
The app also has a feature to receive intent via the Youtube application. When user presses the share button within the Youtube app, my app appears in the share list. Upon pressing share from the Youtube app, MainActivity should be brought to the front, and the URL should be posted within the MainActivity's URL field.
However, this only happens correctly on the first share. If the app is in the background when user shares from Youtube app, they are taken to whatever the last visible activity was, whether it is MainActivity or VideoActivity, (and even if it is MainActivity, the URL is not posted into the URL field, but the field is left in whatever state it was in when the app was last visible).
Here is my current AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.youcmt.youdmcapp">
<uses-permission android:name="android.permission.INTERNET"/>
<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"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
<activity
android:name=".VideoActivity"
android:parentActivityName=".MainActivity"/>
<service
android:name=".FetchVideoService"
android:exported="false"/>
</application>
</manifest>
Here is my MainActivity.java code:
public class MainActivity extends AppCompatActivity {
private ResponseReceiver mReceiver;
private EditText mUrlEditText;
private Button mSearchButton;
private ProgressBar mProgressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
super.onCreate(savedInstanceState);
mUrlEditText = findViewById(R.id.url_search_et);
Intent intent = getIntent();
if (intent.getType()!=null &&
intent.getType().equals("text/plain")) {
Bundle extras = getIntent().getExtras();
String value = extras.getString(Intent.EXTRA_TEXT);
if(value!=null)
{
mUrlEditText.setText(value);
}
}
mProgressBar = findViewById(R.id.progress_bar);
mSearchButton = findViewById(R.id.search_button);
mSearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
askForVideo(mUrlEditText.getText().toString());
mSearchButton.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
} catch (Exception e) {
mUrlEditText.setText("");
mUrlEditText.setHint(e.getMessage());
e.printStackTrace();
}
}
});
}
#Override
protected void onResume() {
super.onResume();
//register the ResponseReceiver
mReceiver = new ResponseReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(FETCH_VIDEO_INFO);
registerReceiver(mReceiver, intentFilter);
}
private void askForVideo (String url) throws Exception {
try {
Intent intent = FetchVideoService.newIntent(this, url);
startService(intent);
} catch (Exception e) {
mUrlEditText.setText(e.getMessage());
}
}
public class ResponseReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(EXTRA_VIDEO_STATUS, FAIL);
mProgressBar.setVisibility(View.INVISIBLE);
mSearchButton.setVisibility(View.VISIBLE);
if(status==FAIL)
{
mUrlEditText.setText("");
mUrlEditText.setHint("Error retrieving video!");
}
else if(status==SUCCESS) {
Video video = intent.getParcelableExtra(EXTRA_VIDEO);
Intent videoActivityIntent =
VideoActivity.newIntent(getApplicationContext(), video);
startActivity(videoActivityIntent);
}
}
}
#Override
protected void onPause() {
unregisterReceiver(mReceiver);
super.onPause();
}
}
I do not think any of the other files will be useful in understanding the problem. Although this seems like something many app creators should have to deal with, I can find no answers to this problem. Please comment if you feel I should add any additional information and thank you in advance for any help!
Update: testing demonstrates that after the first use of "Share" from YouTube (and considering app remains in the background), the MainActivity no longer receives any new intent on further shares. However, my app is still brought to the foreground somehow. This is very confusing to me.
When you share from another app, your MainActivity is brought to the front and onNewIntent() is called on it. You don't override onNewIntent() so you never see the share Intent.
I have to receive system-sent implicit broadcasts (ACTION_PACKAGE_ADDED) to detect the installation of the application and perform some code. I used the code below:
public class Receiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// It will trigger when any app is installed
Uri data = intent.getData();
String packageAdv = data.getEncodedSchemeSpecificPart();
//some code...
}
}
In my Manifest file I declared my receiver:
<receiver android:name="com.myapp.Receiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
It works perfect before Version 8.0 Oreo. Now, I have to make my receiver explicit by using registerReceiver. How can I do this? Sample code would be appreciated.
I have decided to create a simple service for listening to PACKAGE_ADDED event.
public class MyService extends Service {
private BroadcastReceiver receiver;
public MyService() { }
#Override
public void onCreate() {
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addDataScheme("package");
receiver = new Receiver();
registerReceiver(receiver, intentFilter);
}
//ensure that we unregister the receiver once it's done.
#Override
public void onDestroy() {
unregisterReceiver(receiver);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Also, I needed to declare my service in manifest file:
<service
android:name="com.nolesh.myapp.MyService"
android:enabled="true">
</service>
I'm trying for well over 10 hours now and I can't seem to think about anyhting else. I tried every possible example on the internet, but to no avail.
I have NotificationMonitor class extending NotificationListenerService and I wanted to send message from this service to main activity(and possible other activities and services in the future) using Intent mechanism. I post code below:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testpackage.test">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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>
<service android:name=".NotificationMonitor"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
MainActivity.java
public class MainActivity extends Activity {
private TextView txtView;
private NotificationReceiver nReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtView = (TextView) findViewById(R.id.textView);
//create receiver
nReceiver = new NotificationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.testpackage.test.NOTIFICATION_MONITOR");
registerReceiver(nReceiver,filter);
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(nReceiver);
}
public void buttonClicked(View v){
if(v.getId() == R.id.btnTestBroadcast){
//send test intent without category
Log.d("ActivityMain","Button clicked");
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
sendBroadcast(i);
}
}
class NotificationReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.d("ActivityMain","Intent received: "+intent.getAction()+" has extra: "+intent.hasExtra("info"));
if (intent.hasCategory("com.testpackage.test.TEST_CATEGORY")) {
if (intent.hasExtra("info")) {
txtView.setText(intent.getStringExtra("info"));
}
}
}
}
}
NotificationMonitor.java
public class NotificationMonitor extends NotificationListenerService {
private NotificationMonitorReceiver receiver;
#Override
public void onCreate() {
super.onCreate();
receiver = new NotificationMonitorReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.testpackage.test.NOTIFICATION_MONITOR");
registerReceiver(receiver,filter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
//do something
sendInfo("notification posted");
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
//do something
sendInfo("notification removed");
}
#Override
public void onListenerConnected() {
//service created and listener connected
Log.d("NM","Listener connected!");
sendInfo("listener connected");
}
private void sendInfo(String info) {
Log.d("NM", "sendInfo called!");
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
i.addCategory("com.testpackage.test.TEST_CATEGORY");
i.putExtra("info", info);
sendBroadcast(i);
}
class NotificationMonitorReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//no categories intents get replied
Log.d("NM","Intent received: "+intent.getAction()+" has categories: "+(intent.getCategories()!=null));
if (intent.getCategories() == null) {
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
i.addCategory("com.testpackage.test.TEST_CATEGORY");
sendBroadcast(i);
}
}
}
}
After running this app in debug mode of course I need to re-enable notification permissions, so when I do I see in logcat:
10-10 16:22:46.428 7330-7381/com.testpackage.test D/NM: Listener connected!
10-10 16:22:46.428 7330-7381/com.testpackage.test D/NM: sendInfo called!
well, I should receive broadcast in my application, shouldn't I?
After I click button:
10-10 16:22:57.607 7330-7330/com.testpackage.test D/ActivityMain: Button clicked
10-10 16:22:57.612 7330-7330/com.testpackage.test D/ActivityMain: Intent received: com.testpackage.test.NOTIFICATION_MONITOR has extra: false
10-10 16:22:57.619 7330-7330/com.testpackage.test D/NM: Intent received: com.testpackage.test.NOTIFICATION_MONITOR has categories: false
so the Intent is properly created and send from main activity, received back by the same activity and NotificationListenerService, has no categories so should get replied but nothing happens like when sendInfo method is called.
Please help, I have no other ideas about what might be wrong.
edit: I tested with regular services and of course Broadcasts are working just fine. Is there by chance any possibility that you just can't sendBroadcast from this particular extended service class?
Oficially, I'm a moron. Answer is: I didn't set up Category filter in IntentFilter and this is why I received zero properly sent intents from my class. So, long story short, to "fix" this mistake all one needs to do is add:
filter.addCategory("com.testpackage.test.TEST_CATEGORY");
and that's it. Thank you for your attention.
I would like my app to detect if a new outgoing call happened
I want to do something like this :
if (there was a new outgoing call) {
do...
} else {
do...
}
You can use the android Broadcast Reciever. To use it all you have to do is first,
Create a new handler class to handle the broadcast receiver.
public class OutgoingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//You can do this to get the phone number, it is only optional
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
//Handle outgoing call event here
}
}
Then register it in the android manifest so it knows where this method is.
<receiver android:name=".OutgoingCallReceiver" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
Finally, create a permission in the android manifest.
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
And that should do it, hope I could help. :)
Create a broadcast receiver to catch the outgoing calls:
public class CallReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// your code
}
}
Then register it in the manifest:
<receiver android:name=".CallReceiver" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Lastly set the permissions:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
Detect outgoing phone call event
1)Create OutgoingCallBroadcastReceiver
public class OutgoingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(OutgoingCallReceiver.class.getSimpleName(), intent.toString());
Toast.makeText(context, "Outgoing call catched!", Toast.LENGTH_LONG).show();
//TODO: Handle outgoing call event here
}
}
Register OutgoingCallBroadcastReceiver in AndroidManifest.xml
Add permission in AndroidManifest.xml