Wifi scan results broadcast receiver not working - android

I have written a simple broadcast receiver to show a toast message when wifi scan is completed. Nothing is showing. Here is my code:
package com.wifi;
import java.util.List;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.widget.Toast;
public class wifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Scan completed", Toast.LENGTH_LONG).show();
}
}
Here is the manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wifi"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".wifi" 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=".wifiReceiver">
<intent-filter>
<action android:name="android.net.wifi.SCAN_RESULTS"></action>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
</manifest>

well, it's not that easy ;-)
there are couple of things missing...
here is an example of a wifi scan - the original source code is located here http://www.androidsnippets.com/scan-for-wireless-networks
package com.android.wifitester;
import java.util.List;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class WifiTester extends Activity {
TextView mainText;
WifiManager mainWifi;
WifiReceiver receiverWifi;
List<ScanResult> wifiList;
StringBuilder sb = new StringBuilder();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mainText = (TextView) findViewById(R.id.mainText);
mainWifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
receiverWifi = new WifiReceiver();
registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mainWifi.startScan();
mainText.setText("\\nStarting Scan...\\n");
}
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "Refresh");
return super.onCreateOptionsMenu(menu);
}
public boolean onMenuItemSelected(int featureId, MenuItem item) {
mainWifi.startScan();
mainText.setText("Starting Scan");
return super.onMenuItemSelected(featureId, item);
}
protected void onPause() {
unregisterReceiver(receiverWifi);
super.onPause();
}
protected void onResume() {
registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
super.onResume();
}
class WifiReceiver extends BroadcastReceiver {
public void onReceive(Context c, Intent intent) {
sb = new StringBuilder();
wifiList = mainWifi.getScanResults();
for(int i = 0; i < wifiList.size(); i++){
sb.append(new Integer(i+1).toString() + ".");
sb.append((wifiList.get(i)).toString());
sb.append("\\n");
}
mainText.setText(sb);
}
}
}

I spent some time on this, and depending on what version of Android you are running this might help. For Android M, it appears that you have to enable location services, so try to add this to your code if you fall under this criteria.
private static final int PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION = 1001;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// TODO: What you want to do when it works or maybe .PERMISSION_DENIED if it works better
}
}
Don't forget to add the following to your manifest:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Hopefully this helps.

I did what max and PVS did but also removed the uses-permissions and still go the scan action.
Removed from manifest
Looking at the docs if you have no uses-permissions then your receiver is unrestricted as to whom can send but seems if you us uses permissions then the broadcast must have similar permissions.
I tested this with a lot of actions (below) in a receiver and get them. But once I put in uses-permissions of any kind I get no broadcasts,weird.
<receiver android:name=".myReceiver" android:enabled="true">
<intent-filter android:priority="99999999999">
<action android:name="android.intent.action.FOUND" />
<action android:name="android.location.PROVIDERS_CHANGED" />
<action android:name="android.hardware.action.NEW_PICTURE" />
<action android:name="android.hardware.action.NEW_VIDEO" />
<action android:name="android.net.wifi.STATE_CHANGE" />
<action android:name="android.net.wifi.NETWORK_IDS_CHANGED" />
<action android:name="android.net.wifi.SCAN_RESULTS" />
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
<action android:name="android.net.wifi.supplicant.STATE_CHANGE" />
<action android:name="android.net.ConnectivityManager.CONNECTIVITY_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

I got the above code working with the following in my manifest:
<receiver android:name="com.mumfordmedia.trackify.WifiReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.net.wifi.SCAN_RESULTS"></action>
</intent-filter>
Notice both the android:enabled="true" attribute in the receiver element, and the full path to the class that should be executed when the message is received as opposed to ".classname".
All the best and thanks for a starting point,
Max.

I started with Max's answer above, and when that worked, I proceeded to remove android:enabled="true" and then changed the android:name=".MyReceiver" (not the full path). It continued to work (2.2, API 8)! By "work" I mean MyReceiver received broadcasts when I turned WiFi on and off (I didn't poke into the extras etc). I also have ACCESS_WIFI_STATE and CHANGE_WIFI_STATE permissions.
<receiver android:name=".MyReceiver">
<intent-filter>
<!--
<action android:name="android.net.wifi.STATE_CHANGED"/>
-->
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.SCAN_RESULTS"/>
</intent-filter>

Related

Android service does not start all the times after reboot

I want to start a service after reboot. The problem I have is that this does not happen every time (at least the first 20 minnutes). I have study many questions into stackoverflow and try a number of the provided solutions however sometimes the service does not automaticaly start after reboot.
Also I have to add another parameter this of the foreground service for android versions O and above.
Could someone give me any advice?
AndroidManifest.xml
.... <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".App"
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=".Activities.MainActivity"
....
</activity>
<activity
...
</activity>
<receiver android:name=".Helpers.BootCompletedIntentReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<!-- I think that this is also not necessery <category android:name="android.intent.category.DEFAULT" /> -->
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
<service
android:name=".Services.myService"
android:enabled="true"
android:exported="true"></service>
</application>
BroadcastReciever
package com.abc.Helpers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.abx.Activities.MainActivity;
import com.abc.Services.myService;
public class BootCompletedIntentReceiver extends BroadcastReceiver {
private static final String TAG = "MyBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent serviceIntent = new Intent(context, myService.class);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ContextCompat.startForegroundService(context,serviceIntent);
} else {
context.startService(serviceIntent);
}
}
}
I also found in a comment here that reciever should be registered into an activity of the application and this is the code in Mainactivity. Do you agree?
#Override
protected void onCreate(Bundle savedInstanceState) {
...
final ComponentName onBootReceiver = new ComponentName(getApplication().getPackageName(), BootCompletedIntentReceiver.class.getName());
if(getPackageManager().getComponentEnabledSetting(onBootReceiver) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
getPackageManager().setComponentEnabledSetting(onBootReceiver,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
..
}

can broadcast receiver handle ACTION_NDEF_DISCOVERED?

I am trying to write an app that would perform following operations:
once the user unlock the phone he has 10 seconds to scan an NFC tag in order to start camera app. and the NFC tag will have a mime type of
application/com.testformat.nfcdemo
To detect screen unlock, I used a broadcast receiver to detected User present.
And this works fine.
And I started a CountdownTimer inside the broadcast receiver for 10 seconds.
And the NFC detection part did not work, I could use some help here! thank you all!
My activity:
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
public class DisplayActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
}
Manifest xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-permission android:name="android.permission.NFC" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity
android:name=".DisplayActivity"
android:label="#string/activity_title" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".ScreenStateReceiver">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/com.testformat.nfcdemo" />
</intent-filter>
</receiver>
</application>
</manifest>
Receiver:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.os.CountDownTimer;
import android.widget.Toast;
public class ScreenStateReceiver extends BroadcastReceiver {
private boolean countdown_end = false;
NfcAdapter mNfcAdapter;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
CharSequence text = context.getResources().getString(R.string.unlock_message);
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
startCountdown(10000);
if (intent.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED)) {
if (!countdown_end) {
text = context.getResources().getString(R.string.nfc_detected);
Toast nfc_toast = Toast.makeText(context, text, duration);
toast.show();
}
}else if ( intent.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED)){
if (!countdown_end) {
text = context.getResources().getString(R.string.nfc_detected);
Toast nfc_toast = Toast.makeText(context, text, duration);
toast.show();
}
}
}
}
private void startCountdown(long milliseconds){
new CountDownTimer(milliseconds, 1000) {
#Override
public void onTick(long l) {
}
public void onFinish() {
countdown_end=true;
}
}.start();
}
}
can broadcast receiver handle ACTION_NDEF_DISCOVERED?
No. That is an activity action, used with startActivity(). It is not broadcast and therefore cannot be picked up by a BroadcastReceiver.

Android BroadcastReceiver, auto run service after reboot of device

Hello i am writing an application, which is when the phone reboot, the service will auto start instead of click on the application.
Here is my code for
BootCompleteReceiver.java
package com.example.newbootservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, MsgPushService.class);
context.startService(service);
}
}
MsgPushService.java
package com.example.newbootservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MsgPushService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroy", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
MainActivity.java (not sure whether i need this)
package com.example.newbootservice;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(getBaseContext(), MsgPushService.class));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.newbootservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service android:name=".MsgPushService"/>
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I want the service to be started automatically after reboot instead of starting it manually.
You forgot about the permissions
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Though all the above answers were correct, however from Android Oreo they put some limitation on Background Services.
Check Background Execution Limits to know more about background limits in Android O.
You can't start a Service directly from BroadCastReceiver when the application is in the background.
However, you can start a foreground service from the receiver by calling startForegroundService() or use JobIntentService as there is no such limitation with JobIntentService.
Use this code on your Broadcast Receiver class:
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent service = new Intent(context, MsgPushService.class);
context.startService(service);
}
also try these permissions,it may help you .ifyou are using htc phones then these permissions are required
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>

start broadcastreceiver

Here I am trying to read the message and toast it I have seen various examples where there is a separate class that extends BroadcastReceiver but they have not mentioned how to start this class(do we use startactivity() or somthing else). I have posted the code that I dowladed through a link from O'Reilly's cookbook. I've tried to sms from ddms but it doesn't show toast of message. Any help is appreciated as this is my first time with BroadcastReceiver.
invitationSMSreciever.java
package com.SMS;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.sax.StartElementListener;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class invitationSMSreciever extends BroadcastReceiver {
final String TAG = "BombDefusalApp";
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String message = "";
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
message = msgs[i].getMessageBody();
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
if (msgs[i].getMessageBody().equalsIgnoreCase("Invite")) {
// Intent myIntent = new Intent(MainMenu.this,
// com.bombdefusal.ReceivedSMSActivity.class);
Intent myIntent = new Intent();
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
myIntent.setAction("com.example.helloandroid.INVITE");
context.startActivity(myIntent);
}
}
}
}
}
MainMenu
package com.SMS;
import com.SMS.R;
import android.app.Activity;
import android.os.Bundle;
public class MainMenu extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
ReceivedSMSActivity
package com.SMS;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import com.SMS.R;
public class ReceivedSMSActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent ("com.android.PLAY"));
setContentView(R.layout.invite);
}
public boolean onKeyDown(int keyCode, KeyEvent service) {
stopService(new Intent("com.bombdefusal.START_AUDIO_SERVICE"));
finish();
return true;
}
}
manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.SMS" android:versionCode="1" android:versionName="1.0">
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MainMenu" android:label="#string/app_name">
<intent-filter>
<action android:name="com.SMS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.SMS.ReceivedSMSActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="com.example.helloandroid.INVITE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<receiver android:name="com.SMS.invitationSMSreciever"
android:enabled="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
</application>
</manifest>
You have two options to do this:
Register you broadcast receiver statically in the AndroidManifest file. Thus, it will be called automatically.
Register you broadcast receiver dynamically in your code using registerReceiver() method. In this case, this method should be paired with unregisterReceiver() where you unregister your receiver.
Usually, if broadcast receiver is implemented as a separate class then it usually registered statically in AndroidManifest file. I guess in you case you should just add the following lines to your file:
<receiver android:name=".invitationSMSreciever" android:exported="true" >
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

Android checking Wifi on every onRestart

I want my app to check whether the device is connecting to a specific Wifi and auto connect to the Wifi whenever the app is navigated to. I know that I can do it in onRestart(). But it only handles one activity's state.
My question is if there any method to handle the state of the app instead of adding onRestart() on every activity to do what i want?
try the following code:
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
public class AutostartService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("in broad....");
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(context.CONNECTIVITY_SERVICE);
boolean is3g = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnectedOrConnecting();
boolean isWifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();
if(!is3g && !isWifi){
}else{
if ((intent.getAction() != null) && (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")))
{
System.out.println("in broadcast receiver.....");
Intent i = new Intent(context, Splash.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
}
dont forget to add this in your manifest file:
<receiver android:name=".AutostartService" android:enabled="true" android:exported="true">
- <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
and the following permissions in manifest file:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Categories

Resources