I wrote an Android app to allow a device to discover nearby devices via Wi-Fi P2P discovery. I am following this doc.
The app works beautifully on my Samsung Tab E tablet -- I am able to scan and find other devices when the app is running on the tablet. But I am unable to even activate the peer discovery process when running the app on my Samsung Galaxy S10 Plus. My Samsung s10 Plus won't even appear on my tablet's list of available peers unless I manually go into my Galaxy S10 Plus's settings and enable Wi-Fi Discovery Mode. At that point, my Tab E tablet can "see" my Galaxy S10 Plus, but as soon as I exit the settings screen on the Galaxy s10 Plus, Wi-Fi discovery is turned back off and I am no longer able to see it as a potential p2p peer.
Is there a way to allow peer discovery on a Samsung s10 Plus? I am unable to test out my app without it and would rather not have to purchase another Tab E to test p2p connectivity.
Below is the code my app is running for reference:
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
Button btnOnOff, btnDiscover, btnSend;
ListView listView;
TextView read_msg_box, connectionStatus;
EditText writeMsg;
//For programmatically turning wifi on and off:
WifiManager wifiManager;
WifiP2pManager mManager;
WifiP2pManager.Channel mChannel;
BroadcastReceiver mReceiver;
IntentFilter mIntentFilter = new IntentFilter();
//For keeping track of available clients to connect to
List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
String[] deviceNameArray;
WifiP2pDevice[] deviceArray;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initialWork();
//initializeButtonOnClickListeners();
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
btnDiscover = (Button)findViewById(R.id.discover);
connectionStatus = (TextView) findViewById(R.id.connectionStatus);
// btnSend = (Button)findViewById(R.id.sendButton);
listView = (ListView)findViewById(R.id.peerListView);
// read_msg_box = (TextView) findViewById(R.id.readMsg);
// writeMsg = (EditText)findViewById(R.id.writeMsg);
wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
initializeOnClickListeners();
}
private void initializeOnClickListeners() {
//Set up functionality for when the discover button is clicked.
btnDiscover.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "looking for a new peer", Toast.LENGTH_SHORT).show();
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
connectionStatus.setText("Discovery Started");
}
#Override
public void onFailure(int reason) {
connectionStatus.setText("Discovery Failed to start");
}
});
}
});
}
//Define the logic for when a new peer is discovered
WifiP2pManager.PeerListListener peerListListener = new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
if(!peerList.getDeviceList().equals(peers)) {
//clear the peers
peers.clear();
//store device list
peers.addAll(peerList.getDeviceList());
deviceNameArray = new String[peerList.getDeviceList().size()];
deviceArray = new WifiP2pDevice[peerList.getDeviceList().size()];
int index = 0;
for(WifiP2pDevice device : peerList.getDeviceList()) {
deviceNameArray[index] = device.deviceName;
deviceArray[index] = device;
index++;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1,
deviceNameArray);
listView.setAdapter(adapter);
}
if(peers.size() == 0) {
Toast.makeText(getApplicationContext(), "No Devices Found :(", Toast.LENGTH_SHORT).show();
}
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.p2p.WifiP2pManager;
import android.widget.Toast;
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private WifiP2pManager mManager;
private WifiP2pManager.Channel mChannel;
private MainActivity mActivity;
WifiP2pManager.PeerListListener myPeerListListener;
public WiFiDirectBroadcastReceiver(WifiP2pManager mManager, WifiP2pManager.Channel mChannel, MainActivity mActivity) {
this.mManager = mManager;
this.mChannel = mChannel;
this.mActivity = mActivity;
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
System.out.println("The following action was received: " + action);
if(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)){
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
//if wifi is enabled
if(state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
Toast.makeText(context, "Wifi is ON", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Wifi is OFF", Toast.LENGTH_LONG).show();
}
} else if(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
Toast.makeText(context, "INSIDE THE P2P_PEERS_CHANGED_ACTION", Toast.LENGTH_LONG).show();
if(mManager != null) {
mManager.requestPeers(mChannel, mActivity.peerListListener);
Toast.makeText(context, "A new peer has been found!!!", Toast.LENGTH_LONG).show();
}
} else if(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
//do something
} else if(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
//do something
}
}
}
I don't code in Android for sometimes, but I think my experience might still valid, you can give it a try.
Correct me if I'm wrong, so, you have developed an app that allows your devices to discover and connect to each other, without the need to access to the phone's settings. For your S10, you have installed and opened the app, but you cannot discover it via your Tab, unless you manually switch it on in the settings?
First, ensure your app has all the required permission added and requested when using the app.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.nsdchat"
...
<uses-permission
android:required="true"
android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission
android:required="true"
android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission
android:required="true"
android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission
android:required="true"
android:name="android.permission.INTERNET"/>
Just to make sure your app has the permission, add the permission to the code below for the respective permission:
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.CHANGE_WIFI_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
}
...
Second, look at the code library version. Since s10 + is fairly new, Android has actually enhanced the privacy and security starting from Android 8.0. The code you wrote might be outdated due to the library version, and some APIs might be deprecated.
Related
In android 12 api 31
I run this app ,it doesn't work properly
I want to find the name of the nearby devices but the Bluetooth device doesn't start until I click on the Bluetooth button from the notification panel and in log it shows Discovery Started and Gave another Log which shows Discovery Finished without searching a device.
package com.aditya.bluetoothfinder;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
ListView listView;
TextView statusTextView;
Button searchButton;
BluetoothAdapter bluetoothAdapter;//The BluetoothAdapter is required for any and all Bluetooth activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listView);
statusTextView = findViewById(R.id.statusTextView);
searchButton = findViewById(R.id.searchButton);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
public void searchClicked(View view) {
if (bluetoothSupported()) {
openBluetooth();
} else {
statusTextView.setText("Bluetooth Not Supported");
}
}
//This function will check that the bluetooth is supported on the device or not
public boolean bluetoothSupported() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
}
//This function opens the bluetooth
public void openBluetooth() {
if (!bluetoothAdapter.isEnabled()) {
Intent enableBluetoothIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
requestThePermissons();
} else {
startActivityForResult(enableBluetoothIntent, 1);
}
} else {
searchBluetoothDevices();
}
}
//This function request the permission
private void requestThePermissons() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { //if we don't have any permission
requestPermissionLauncher.launch(Manifest.permission.BLUETOOTH_CONNECT);
} else { //if we already have permissionn of bluetooth connect
searchBluetoothDevices();
}
}
//This is a callback which give us the information that the user gave us the permission or not
private final ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
if (isGranted) {
// Permission is granted. Continue the action or workflow in your
searchBluetoothDevices();
} else { //If user declined the permission request
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
});
//This is the function for searching bluetooth devices
public void searchBluetoothDevices() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Unable to locate bluetooth device", Toast.LENGTH_SHORT).show();
requestPermissions(new String[]{Manifest.permission.BLUETOOTH_SCAN},1);
} else {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(receiver, filter);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Unable to locate", Toast.LENGTH_SHORT).show();
}
bluetoothAdapter.startDiscovery();
statusTextView.setText("Searching...");
searchButton.setEnabled(false);
}
}
When I call the bluetoothAdapter.startDiscovery();
It shows
D/BluetoothAdapter: startDiscovery(): called by: com.aditya.bluetoothfinder
but doesn't show the log Discovery started until I click on the Bluetooth button from the notification panel and after that it gives another Log Discovery Finished
//This function give us the details of the bluetooth device if found
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
Log.i("this", "Device Found");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
requestThePermissons();
Toast.makeText(MainActivity.this, "Unable to find", Toast.LENGTH_SHORT).show();
} else {
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
String text = (String) statusTextView.getText();
statusTextView.setText(text + "\n" +deviceName + "\n" + deviceHardwareAddress);
}
} else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.i("this", "Discovery Finished");
statusTextView.setText("Finished");
searchButton.setEnabled(true);
} else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.i("this", "Discovery started");
Toast.makeText(MainActivity.this, "Started", Toast.LENGTH_SHORT).show();
}
}
};
}
Permission used in AndroidManifest.xml
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
You also have to take location permission from the user and the user has to turn on location services in order to see other Bluetooth devices.
I am currently working on a simple Wi-fi scanner android application
with min API level 26 and target API level 28.
I want real time update in scan results so i have created a broadcast receiver but it is not working as intended.
Note: I have already tried
Wifi scan results broadcast receiver not working, Broadcast receiver with wifi scan not working
PLEASE NOTE THAT I WANT EXPLICIT BROADCAST RECEIVER NOT VIA MANIFEST FILE
I will be grateful to you.
Below is my java code:
package com.example.quickshare;
import androidx.appcompat.app.AppCompatActivity;
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.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class ActivitySend extends AppCompatActivity {
WifiManager wifiManager;
ListView ScanList;
List<ScanResult> results;
ListAdapter listAdapter;
WifiReceiver wifiReceiver;
IntentFilter intentFilter;
TextView msg;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send);
wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
CheckWifiStatus();
msg = findViewById(R.id.wifiStatus);
intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
intentFilter.addAction(WifiManager.EXTRA_RESULTS_UPDATED);
try {
getApplicationContext().registerReceiver(wifiReceiver, intentFilter);
}
catch(Exception e){
System.out.println(e);
}
boolean success = wifiManager.startScan();
if(success)
Toast.makeText(ActivitySend.this, "Scanning", Toast.LENGTH_SHORT).show();
}
#Override
protected void onResume() {
super.onResume();
CheckWifiStatus();
registerReceiver(wifiReceiver, intentFilter);
wifiManager.startScan();
results = wifiManager.getScanResults();
if (results.size() > 0)
Toast.makeText(ActivitySend.this, "Scan Successful", Toast.LENGTH_LONG).show();
else
Toast.makeText(ActivitySend.this, "No Device Available", Toast.LENGTH_LONG).show();
ScanList = findViewById(R.id.ScanList);
listAdapter = new ListAdapter(getApplicationContext(), results);
ScanList.setAdapter(listAdapter);
ScanList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(ActivitySend.this, "Selected" + results.get(position).SSID, Toast.LENGTH_LONG).show();
//TODO: Establish Connection with selected SSID
}
});
}
class WifiReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(ActivitySend.this,"Available Device list changed",Toast.LENGTH_LONG).show();
//TODO: Append SSID of new Available APs in ListView and arrange a callback to onResume().
}
}
public void CheckWifiStatus(){
if (!wifiManager.isWifiEnabled()){
wifiManager.setWifiEnabled(true);
Toast.makeText(ActivitySend.this, "Wifi turned 'On' Successfully", Toast.LENGTH_SHORT).show();
msg.setText("Wifi Status : ON");
}
}
#Override
protected void onPause() {
unregisterReceiver(wifiReceiver);
super.onPause();
}
}
Using Above java code i can scan available APs if they are available before launching the activity.
After Launching this activity nothing changes in scan result and it keep showing previously fetched results even if i turn off that AP.
In order to detect your AP being disconnected, your intentFilter is lacking the ConnectivityManager.CONNECTIVITY_ACTION.
You can listen
to these action with the following line:
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Also, you need to add brackets to your else code blocks, i.e.
if {
// ...
} else {
Toast.makeText(ActivitySend.this, "No Device Available", Toast.LENGTH_LONG).show();
ScanList = findViewById(R.id.ScanList);
// ...
}
I am developing an android app which needs to check available wifi list periodically even when the app is killed from background. So I am thinking about using a service to check it from back end. In this case I am facing some problem to get the available wifi list from service. I search over internet and found most of the solution for activity only. Though I tried them but not working.
Please note that. THIS SAME CODE WORKS WHEN I USE THEM IN DIRECT ACTIVITY. BUT IT DOESN'T WORK IN SERVICE CLASS.
Code of my service is.....
package com.example.sodrulaminshaon.ringmodecontroller;
import android.Manifest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.IBinder;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import java.util.List;
import java.util.Set;
/**
* Created by Sodrul Amin Shaon on 22-Jun-18.
*/
public class MyService extends Service {
WifiManager wifiManager;
WifiReceiver receiverWifi;
private static final String LIST_TESTING = "ListTest";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences preferences = getSharedPreferences(Constants.PREFERENCE_NAME,MODE_PRIVATE);
boolean auto = preferences.getBoolean(Constants.AUTO_CONTROL_STR,false);
//if(MainActivity.getAutoControl())
if(auto)
{
wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.isWifiEnabled())
{
wifiManager.setWifiEnabled(true);
}
Log.i(LIST_TESTING,"Wifi is enabled. Now going to check the available list.");
receiverWifi = new WifiReceiver();
registerReceiver(receiverWifi,
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
wifiManager.startScan();
}
stopSelf();
return START_STICKY;
}
class WifiReceiver extends BroadcastReceiver {
// This method call when number of wifi connections changed
public void onReceive(Context c, Intent intent) {
StringBuilder sb = new StringBuilder();
List<ScanResult> wifiList = wifiManager.getScanResults();
Log.i(LIST_TESTING,"Inside scan result receiver. Scan result size: "+wifiList.size());
sb.append("\n Number Of Wifi connections :"+wifiList.size()+"\n\n");
for(int i = 0; i < wifiList.size(); i++){
sb.append(new Integer(i+1).toString() + ". ");
sb.append(wifiList.get(i).SSID).toString();
sb.append("\n\n");
}
Log.i(LIST_TESTING,sb.toString());
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
// I want to restart this service again in one hour
SharedPreferences preferences = getSharedPreferences(Constants.PREFERENCE_NAME,MODE_PRIVATE);
boolean auto = preferences.getBoolean(Constants.AUTO_CONTROL_STR,false);
if(auto)
{
if(wifiManager.isWifiEnabled())unregisterReceiver(receiverWifi);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
alarm.set(
alarm.RTC_WAKEUP,
System.currentTimeMillis() + (1000 * 10),
PendingIntent.getService(this, 0, new Intent(this, MyService.class), 0)
);
}
}
}
No need to worry about permission. I have taken necessary permissions at the start of the app. Still I am sharing the permission taken part.
private void getPermission(){
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&&
ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
askForLocationPermissions();
}
}
private void askForLocationPermissions() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
new android.support.v7.app.AlertDialog.Builder(this)
.setTitle("Location permessions needed")
.setMessage("you need to allow this permission!")
.setPositiveButton("Sure", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
})
.setNegativeButton("Not now", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
switch (requestCode) {
case LOCATION_PERMISSION_REQUEST_CODE:
if (isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
Toast.makeText(this, "Can not proceed! i need permission" , Toast.LENGTH_SHORT).show();
}
break;
}
}
public static boolean isPermissionGranted(#NonNull String[] grantPermissions, #NonNull int[] grantResults,
#NonNull String permission) {
for (int i = 0; i < grantPermissions.length; i++) {
if (permission.equals(grantPermissions[i])) {
return grantResults[i] == PackageManager.PERMISSION_GRANTED;
}
}
return false;
}
I can assure that my service is running well. It tries to check available wifi list each 10 seconds interval.
What I want to know is that. This code can not print the available wifi list. Just for the information in MyService class
Log.i(LIST_TESTING,"Wifi is enabled. Now going to check the available list.");
this line is printing continuously. But the other two lines
Log.i(LIST_TESTING,"Inside scan result receiver. Scan result size: "+wifiList.size());
Log.i(LIST_TESTING,sb.toString());
are not being executed. Can anyone please help me....
As nobody is answering. I tried further and found the problem of my code. In my code I called
stopSelf();
inside
public int onStartCommand(Intent intent, int flags, int startId) method. Which was causing my service to stop just after it was started. Which means my registered broadCastReceiver was also being discarded. As a result wifi list was not being printed. I was dumb to write this code and finding the error.
You should create a broadcast receivers to get the list of available wifi networks.
private final BroadcastReceiver mWifiScanReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
List<ScanResult> mScanResults = mWifiManager.getScanResults();
}
}
}
also add these lines in the manifest.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
and in oncreate() method register the listners
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
registerReceiver(mWifiScanReceiver,
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
For more details this question related to this POST.
Right now I can check network status on a single activity and its really working fine. But suppose I want to check the internet on every single activity. How to modify this code? I tried many ways but failed.
package com.example.wohhi.nointernetsnackbar;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView status;
private static final String LOG_TAG = "CheckNetworkStatus";
private NetworkChangeReceiver receiver;
private boolean isConnected = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
status = (TextView) findViewById(R.id.status);
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
receiver = new NetworkChangeReceiver();
registerReceiver(receiver, filter);
}
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.v(LOG_TAG, "Receieved notification about network status");
isNetworkAvailable(context);
}
private boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo info = connectivity.getActiveNetworkInfo();
if (info != null) {
if (info.isConnectedOrConnecting()) {
if(!isConnected){
Log.v(LOG_TAG, "Now you are connected to Internet!");
String status = "Now you are connected to Internet!";
Snackbar.make(findViewById(R.id.activity_main), status, Snackbar.LENGTH_LONG).show();
isConnected = true;
//do your processing here ---
//if you need to post any data to the server or get status
//update from the server
}
return true;
}
}
}
Log.v(LOG_TAG, "You are not connected to Internet!");
String status = "You are not connected to Internet!";
Snackbar.make(findViewById(R.id.activity_main), status, Snackbar.LENGTH_LONG).show();
isConnected = false;
return false;
}
}
}
Instead of registering it in onCreate() Create a BroadcastReceiver class outside of activity and register it statically means in Manifest. But this will work for only API level 23 and below as it is given here.
Apps targeting Android 7.0 (API level 24) and higher do not receive this broadcast if they declare the broadcast receiver in their manifest. Apps will still receive broadcasts if they register their BroadcastReceiver with Context.registerReceiver() and that context is still valid.
I've been able to successfully create an app (thanks davidgyoung!) that monitors beacons in the background and then subsequently opens the app in the background.
Now I would like my app to first prompt with a notification in the status bar saying something like "I've detected a beacon! Would you like to open out app?". Then the user would click on the notification to open the app or dismiss it and ignore the notification.
I've searched on stack overflow for something like but haven't had much success in finding something relevant to beacons. I did find this page that talks about adding StatusBar notifications but I'm not having much success.
Particularly its in my BeaconReferenceApplication.java and MonitoringActivity.java file. I think I put the code in the correct place (after didEnterRegion) but I have unresolved classes for areas like notificationButton, setLatestEventInfo, etc. Can someone help? Thanks in advance!
BeaconReferenceApplication.java:
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
public class BeaconReferenceApplication extends Application implements BootstrapNotifier {
private static final String TAG = "BeaconReferenceApp";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private MonitoringActivity monitoringActivity = null;
public void onCreate() {
super.onCreate();
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb. To find the proper
// layout expression for other beacon types, do a web search for "setBeaconLayout"
// including the quotes.
//
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
Log.d(TAG, "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
Region region = new Region("backgroundRegion", Identifier.parse("2F234454F4911BA9FFA6"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
// simply constructing this class and holding a reference to it in your custom Application
// class will automatically cause the BeaconLibrary to save battery whenever the application
// is not visible. This reduces bluetooth power usage by about 60%
backgroundPowerSaver = new BackgroundPowerSaver(this);
// If you wish to test beacon detection in the Android Emulator, you can use code like this:
// BeaconManager.setBeaconSimulator(new TimedBeaconSimulator() );
// ((TimedBeaconSimulator) BeaconManager.getBeaconSimulator()).createTimedSimulatedBeacons();
}
#Override
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever a Beacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedBeaconsSinceBoot) {
Log.d(TAG, "sending notification to StatusBar");
#SuppressWarnings("deprecation")
private void Notify(String notificationTitle, String notificationMessage) {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
#SuppressWarnings("deprecation")
Notification notification = new Notification(R.mipmap.ic_launcher,
"New Message", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MonitoringActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(MonitoringActivity.this, notificationTitle,
notificationMessage, pendingIntent);
notificationManager.notify(9999, notification);
}
}
} else {
if (monitoringActivity != null) {
Log.d(TAG, "auto launching MainActivity");
// The very first time since boot that we detect an beacon, we launch the
// MainActivity
Intent intent = new Intent(this, MonitoringActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Important: make sure to add android:launchMode="singleInstance" in the manifest
// to keep multiple copies of this activity from getting created if the user has
// already manually launched the app.
this.startActivity(intent);
haveDetectedBeaconsSinceBoot = true;
}
}
}
#Override
public void didExitRegion(Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I no longer see a beacon.");
}
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I have just switched from seeing/not seeing beacons: " + state);
}
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("An beacon is nearby.")
.setSmallIcon(R.mipmap.ic_launcher);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, MonitoringActivity.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(MonitoringActivity activity) {
this.monitoringActivity = activity;
}
}
MonitoringActivity.java:
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import org.altbeacon.beacon.BeaconManager;
public class MonitoringActivity extends Activity {
protected static final String TAG = "MonitoringActivity";
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
private WebView mWebView;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monitoring);
// code for button notification
Button notificationButton = (Button) findViewById(R.id.notificationButton);
notificationButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Notify("Title: Meeting with Business",
"Msg:Pittsburg 10:00 AM EST ");
}
});
// code for button notification
mWebView = (WebView) findViewById(R.id.activity_main_webview);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("http://communionchapelefca.org/edy-home");
mWebView.setWebViewClient(new MyAppWebViewClient());
verifyBluetooth();
Log.d(TAG, "Application just launched");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android M Permission check
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect beacons in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#TargetApi(23)
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
}
private class HelloWebViewClient extends WebViewClient{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
webView.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(view.GONE);
}
}
#Override
public void onBackPressed() {
if(mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
public void onRangingClicked(View view) {
Intent myIntent = new Intent(this, RangingActivity.class);
this.startActivity(myIntent);
}
#Override
public void onResume() {
super.onResume();
((BeaconReferenceApplication) this.getApplicationContext()).setMonitoringActivity(this);
}
#Override
public void onPause() {
super.onPause();
((BeaconReferenceApplication) this.getApplicationContext()).setMonitoringActivity(null);
}
private void verifyBluetooth() {
try {
if (!BeaconManager.getInstanceForApplication(this).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
}
So I was able to fix my problem by using the example from the Android Developers website for Notifications. I used their sample code, adapted it to my use, and then even further used .bigText to make my notification look great. Credit goes to them and daviggyoung for getting my app working. Thanks!
I also didnt need to edit my MonitoringActivity.java like I posted earlier.
final BeaconReferenceApplication.java:
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
public class BeaconReferenceApplication extends Application implements BootstrapNotifier {
private static final String TAG = "BeaconReferenceApp";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private MonitoringActivity monitoringActivity = null;
public void onCreate() {
super.onCreate();
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb. To find the proper
// layout expression for other beacon types, do a web search for "setBeaconLayout"
// including the quotes.
//
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
Log.d(TAG, "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
Region region = new Region("backgroundRegion", Identifier.parse("2F234454F4911BA9FFA6"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
// simply constructing this class and holding a reference to it in your custom Application
// class will automatically cause the BeaconLibrary to save battery whenever the application
// is not visible. This reduces bluetooth power usage by about 60%
backgroundPowerSaver = new BackgroundPowerSaver(this);
// If you wish to test beacon detection in the Android Emulator, you can use code like this:
// BeaconManager.setBeaconSimulator(new TimedBeaconSimulator() );
// ((TimedBeaconSimulator) BeaconManager.getBeaconSimulator()).createTimedSimulatedBeacons();
}
#Override
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever a Beacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedBeaconsSinceBoot) {
Log.d(TAG, "sending notification to StatusBar");
//begin code for notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Message from Communion Chapel")
.setContentText("Welcome! Thanks for coming!")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("We noticed that you're here today, click here to open the app and get today's Sermon Notes and Bulletin."))
.setAutoCancel(true);
;
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, MonitoringActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MonitoringActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(123, mBuilder.build());
}
}
#Override
public void didExitRegion(Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I no longer see a beacon.");
}
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I have just switched from seeing/not seeing beacons: " + state);
}
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("A beacon is nearby.")
.setSmallIcon(R.drawable.app_icon);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, MonitoringActivity.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(MonitoringActivity activity) {
this.monitoringActivity = activity;
}
}