BLE Android to iOS chat - java

I am working on an app that allows Android and IOS devices to communicate to each other using Bluetooth. My IOS application is working fine, but I cannot get the android application to work. I am trying to make the android device my central. The problem I have encountered is that I am not able to scan for devices as when I do I get this message from the Android monitor:
08-07 15:09:30.983 27349-27364/uk.ac.york.androidtoios2
D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5.
Can someone tell me what is wrong with my code that is not allowing me to scan for the peripheral IOS device.
MainActivity.java
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter bluetoothAdapter;
private BluetoothGatt gatt;
private BluetoothGattCharacteristic inputCharacteristic;
private TextView outputView;
private EditText inputView;
private static final int REQUEST_ENABLE_BT = 1;
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void receiveMode(View v) {
int apiVersion = android.os.Build.VERSION.SDK_INT;
if (apiVersion >= Build.VERSION_CODES.LOLLIPOP) {
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
// scan for devices
scanner.startScan(new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
// get the discovered device as you wish
// this will trigger each time a new device is found
BluetoothDevice device = result.getDevice();
}
});
} else {
// targeting kitkat or bellow
bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
// get the discovered device as you wish
}
});
}
}
// rest of your code that will run **before** callback is triggered since it's asynchronous
public void sendMessage(View v) {
inputCharacteristic.setValue(inputView.getText().toString());
gatt.writeCharacteristic(inputCharacteristic);
}
BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
if (getString(R.string.outputUUID).equals(characteristic.getUuid().toString())) {
final String value = characteristic.getStringValue(0);
runOnUiThread(new Runnable() {
#Override
public void run() {
outputView.setText(value);
}
});
}
}
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
MainActivity.this.gatt = gatt;
if (newState == BluetoothProfile.STATE_CONNECTED) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
gatt.discoverServices();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
for (BluetoothGattService service : services) {
List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic : characteristics) {
if (getString(R.string.outputUUID).equals(characteristic.getUuid().toString())) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptors().get(0);
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
} else if (getString(R.string.inputUUID).equals(characteristic.getUuid().toString())) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
inputCharacteristic = characteristic;
}
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
outputView = (TextView) findViewById(R.id.outputText);
inputView = (EditText) findViewById(R.id.inputText);
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}

Related

onServicesDiscovered() callback doesn't get called

I am building an android app to connect and read data from an Arduino-based BLE device. I was able to find and connect to the device, but for some reason the onServicesDiscovered() callback function never gets called no matter how hard I try. I have already tried waiting 600 milliseconds before discovering, and even 1.5 seconds, I made sure that the discoverServices() command is running on the UI thread, and have redone the Bluetooth code numerous times. I was able to do this successfully before, and the function would be called, but I wanted to put all of the Bluetooth code in its own separate class file to clean up my main activity file, and I did so without creating a backup and this was where my problem started. So then I tried to redo it again in my main file, but to no avail.
Edit: The original code that I published didn't work anyway, so this is the updated code but with the same error.
Here is my code (this is my main activity file):
package com.example.androidrf;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.UUID;
import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;
public class MainActivity extends AppCompatActivity {
public TabLayout tabLayout;
public ViewPager2 viewPager;
public TextView connectionWarning;
// Bluetooth Variables
BluetoothManager bluetoothManager;
BluetoothAdapter bluetoothAdapter;
private static final int REQUEST_ENABLE_BT = 1;
// UUID's
private String arduinoName;
private String serviceId;
private String ledCharacteristicId;
private String numberCharacteristicId;
private UUID serviceUUID;
private UUID ledCharUUID;
private UUID numCharUUID;
// Scan Settings
private ScanFilter scanFilter;
private ScanSettings scanSettings;
// GATT, Characteristics, and Services
private BluetoothGatt gatt;
private BluetoothGattService service;
private BluetoothGattCharacteristic ledChar;
private BluetoothGattCharacteristic numberChar;
// Scanning Related Code
private final BluetoothLeScanner bluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
private boolean mScanning;
private final Handler handler = new Handler();
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
private void scanDevices(boolean forceStop) {
if (forceStop) {
mScanning = false;
bluetoothLeScanner.stopScan(scanCallback);
}
}
private void scanDevices() {
if (!mScanning) {
// Stops scanning after a pre-defined scan period.
handler.postDelayed(() -> {
if (!mScanning) return;
mScanning = false;
bluetoothLeScanner.stopScan(scanCallback);
}, SCAN_PERIOD);
if (deviceFound) return;
mScanning = true;
bluetoothLeScanner.startScan(Collections.singletonList(scanFilter), scanSettings, scanCallback);
} else {
mScanning = false;
bluetoothLeScanner.stopScan(scanCallback);
}
}
// Scan Callback
private boolean deviceFound;
private final ScanCallback scanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
if (deviceFound) {
bluetoothLeScanner.flushPendingScanResults(this);
if (mScanning) scanDevices(true);
return;
}
if (result.getScanRecord().getDeviceName().equals(arduinoName)) {
deviceFound = true;
new Handler(Looper.getMainLooper()).postDelayed(() -> gatt = result.getDevice().connectGatt(getBaseContext(), false, gattCallback, TRANSPORT_LE), 600);
//gatt.connect();
}
}
};
// GATT Callback
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.d("Gatt Services", "Status: " + status + ", newState: " + newState);
if (status == BluetoothGatt.GATT_SUCCESS) {
if (newState == BluetoothGatt.STATE_CONNECTED) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
Log.d("Gatt Services", "Discovering Services");
runOnUiThread(gatt::discoverServices);
}, 600);
}
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
Log.d("Gatt Characteristics", "Success");
if (status == BluetoothGatt.GATT_SUCCESS) {
ledChar = gatt.getService(serviceUUID).getCharacteristic(ledCharUUID);
numberChar = gatt.getService(serviceUUID).getCharacteristic(numCharUUID);
gatt.setCharacteristicNotification(numberChar, true);
}
}
// #Override
// public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
// super.onCharacteristicRead(gatt, characteristic, status);
// }
//
// #Override
// public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
// super.onCharacteristicWrite(gatt, characteristic, status);
// }
//
// #Override
// public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
// super.onCharacteristicChanged(gatt, characteristic);
// }
//
// #Override
// public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// super.onReadRemoteRssi(gatt, rssi, status);
// }
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connectionWarning = findViewById(R.id.warningLabel);
//Bluetooth ------------------------------------------------------------------------------------------
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
arduinoName = getResources().getString(R.string.arduino_name);
serviceId = getResources().getString(R.string.service_id);
ledCharacteristicId = getResources().getString(R.string.led_char_id);
numberCharacteristicId = getResources().getString(R.string.num_char_id);
serviceUUID = UUID.fromString(serviceId);
ledCharUUID = UUID.fromString(ledCharacteristicId);
numCharUUID = UUID.fromString(numberCharacteristicId);
scanFilter = new ScanFilter.Builder().setDeviceName(arduinoName).build();
scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
//.setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
.build();
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
scanDevices();
//ViewPager ------------------------------------------------------------------------------------------
sectionsPagerAdapter SectionsPagerAdapter = new sectionsPagerAdapter(this);
viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(SectionsPagerAdapter);
// Tab Layout ----------------------------------------------------------------------------------------
tabLayout = findViewById(R.id.tabs);
new TabLayoutMediator(tabLayout, viewPager, true, true, (tab, position) -> {
String text = "";
switch(position) {
case 0:
text = getString(R.string.tab_text_1);
break;
case 1:
text = getString(R.string.tab_text_2);
break;
}
tab.setText(text);
}).attach();
}
private static class sectionsPagerAdapter extends FragmentStateAdapter {
public sectionsPagerAdapter(FragmentActivity fa) {
super(fa);
}
#NotNull
#Override
public Fragment createFragment(int position) {
Fragment fragment = null;
switch(position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new SettingsFragment();
break;
}
return fragment;
}
#Override
public int getItemCount() {
return 2;
}
}
#Override
public void onStop() {
super.onStop();
if (gatt == null) return;
gatt.close();
gatt = null;
}
}
Why you made sure discoverServices() method running on the UI thread? This is an asynchronous operation. Try it new thread .
I just had to delay the scan itself by 600 ms.

Can't connect two devices via Googles Nearby API

I'm developing an app which can share local music on your phone to other devices. To connect several devices I am using Googles Nearby API. After starting to advertise and to discover on two devices, the onEndpointFound calls a found device on both devices. To accept this connection the app should show up an AlertDialog. This happens in the onConnectionInitiated method. But for some reason the app won't get to the part where the AlertDialog is built.
Does anybody know how to fix this?
This is the code:
package com.shuzo.musicshare;
import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.google.android.gms.nearby.Nearby;
import com.google.android.gms.nearby.connection.AdvertisingOptions;
import com.google.android.gms.nearby.connection.ConnectionInfo;
import com.google.android.gms.nearby.connection.ConnectionLifecycleCallback;
import com.google.android.gms.nearby.connection.ConnectionResolution;
import com.google.android.gms.nearby.connection.ConnectionsClient;
import com.google.android.gms.nearby.connection.ConnectionsStatusCodes;
import com.google.android.gms.nearby.connection.DiscoveredEndpointInfo;
import com.google.android.gms.nearby.connection.DiscoveryOptions;
import com.google.android.gms.nearby.connection.EndpointDiscoveryCallback;
import com.google.android.gms.nearby.connection.Payload;
import com.google.android.gms.nearby.connection.PayloadCallback;
import com.google.android.gms.nearby.connection.PayloadTransferUpdate;
import com.google.android.gms.nearby.connection.Strategy;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MusicShare";
private static final String[] REQUIRED_PERMISSIONS =
new String[] {
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION,
};
private static final int REQUEST_CODE_REQUIRED_PERMISSIONS = 1;
private static final Strategy STRATEGY = Strategy.P2P_STAR;
EditText usernameEdit;
Button connectButton;
private ConnectionsClient connectionsClient;
// Callbacks for receiving payloads
private final PayloadCallback payloadCallback =
new PayloadCallback() {
#Override
public void onPayloadReceived(String endpointId, Payload payload) {
}
#Override
public void onPayloadTransferUpdate(String endpointId, PayloadTransferUpdate update) {
}
};
// Callbacks for connections to devices
private final ConnectionLifecycleCallback connectionLifecycleCallback =
new ConnectionLifecycleCallback() {
#Override
public void onConnectionInitiated(final String endpointId, ConnectionInfo connectionInfo) {
Log.i(TAG, "onConnectionInitiated: accepting connection");
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getApplicationContext());
alertDialog
.setTitle(R.string.accept_connection_title + " " + connectionInfo.getEndpointName())
.setMessage(R.string.confirm_codes + " " + connectionInfo.getAuthenticationToken())
.setPositiveButton(
R.string.accept_connection,
(DialogInterface dialog, int which) ->
connectionsClient.acceptConnection(endpointId, payloadCallback))
.setNegativeButton(
android.R.string.cancel,
(DialogInterface dialog, int which) ->
connectionsClient.rejectConnection(endpointId))
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
#Override
public void onConnectionResult(String endpointId, ConnectionResolution result) {
switch (result.getStatus().getStatusCode()) {
case ConnectionsStatusCodes.STATUS_OK:
Log.i(TAG, "onConnectionResult: status ok");
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show();
break;
case ConnectionsStatusCodes.STATUS_CONNECTION_REJECTED:
Log.i(TAG, "onConnectionResult: connection rejected");
Toast.makeText(getApplicationContext(), "Connection rejected", Toast.LENGTH_SHORT).show();
break;
case ConnectionsStatusCodes.STATUS_ERROR:
Log.i(TAG, "onConnectionResult: error");
Toast.makeText(getApplicationContext(), "Connection error", Toast.LENGTH_SHORT).show();
break;
default:
// Unknown status code
}
}
#Override
public void onDisconnected(String endpointId) {
Log.i(TAG, "Device disconnected");
}
};
private final EndpointDiscoveryCallback endpointDiscoveryCallback =
new EndpointDiscoveryCallback() {
#Override
public void onEndpointFound(String endpointId, DiscoveredEndpointInfo info) {
Log.i(TAG, "onEndpointFound: endpoint found, connecting");
connectionsClient
.requestConnection(getUserNickname(), endpointId, connectionLifecycleCallback)
.addOnSuccessListener(
(Void unused) -> {
Log.i(TAG, "onEndpointFound: successful");
})
.addOnFailureListener(
(Exception e) -> {
Log.i(TAG, "onEndpointFound: failed");
});
}
#Override
public void onEndpointLost(String endpointId) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connectionsClient = Nearby.getConnectionsClient(this);
connectButton = findViewById(R.id.connectButton);
connectButton.setOnClickListener(view -> {
startAdvertising();
startDiscovery();
connectButton.setEnabled(false);
});
}
#Override
protected void onStart() {
super.onStart();
if (!hasPermissions(this, REQUIRED_PERMISSIONS)) {
requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_REQUIRED_PERMISSIONS);
}
}
private static boolean hasPermissions(Context context, String... permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
private void startAdvertising() {
AdvertisingOptions advertisingOptions =
new AdvertisingOptions.Builder().setStrategy(STRATEGY).build();
connectionsClient
.startAdvertising(getUserNickname(), getPackageName(), connectionLifecycleCallback, advertisingOptions)
.addOnSuccessListener(
(Void unused) -> {
Toast.makeText(getApplicationContext(), R.string.advertising_success, Toast.LENGTH_SHORT).show();
})
.addOnFailureListener(
(Exception e) -> {
Toast.makeText(getApplicationContext(), R.string.advertising_fail, Toast.LENGTH_SHORT).show();
});
}
private void startDiscovery() {
DiscoveryOptions discoveryOptions =
new DiscoveryOptions.Builder().setStrategy(STRATEGY).build();
connectionsClient
.startDiscovery(getPackageName(), endpointDiscoveryCallback, discoveryOptions)
.addOnSuccessListener(
(Void unused) -> {
Toast.makeText(getApplicationContext(), R.string.discovery_success, Toast.LENGTH_SHORT).show();
})
.addOnFailureListener(
(Exception e) -> {
Toast.makeText(getApplicationContext(), R.string.discovery_failed, Toast.LENGTH_SHORT).show();
});
}
private String getUserNickname() {
usernameEdit = findViewById(R.id.usernameEdit);
return usernameEdit.getText().toString();
}
}
Given the additional detail in the comments, this appears to be a Bluetooth Classic issue. I looked in our records, and we have both reported devices so we'll try to reproduce on our end.
Some steps you can do:
1) Try rebooting the devices and see if the issue is reproducible.
2) Collect logs (adb logcat) or a bugreport (adb bugreport) from both devices and attach them to this post or email them to me directly at {my username}#google.com. These contain sensitive data, so only send it if you have test accounts on both devices. If you have a personal account, then filter the logs first (adb logcat NearbyConnections:* NearbyMediums:* *:S)
Disclaimer: I work on Nearby Connections

I'm trying to implement Bluetooth functionality in Android Studio, need some help in connecting problem

I used Bluetooth API and following code is for on/off, show paired devices list, and connect paired devices.
other functions work well, but connecting devices doesn't work .
I try to use thread bidirectional, when bluetooth turns on, serverthread(acceptthread) generated and started. And when I choose device on the list, clientthread(connectthread) generated and started. This is my intent, but when I try to connect on the phone, app is turned off(almost at the client, occasionally at the server).
I thought maybe it's UUID problem so I checked UUID 00enter code here001101-0000-1000-8000-00805F9B34FB, but it didn't help.enter code here
sorry for the import code chunks, I would really appreciate your help.
'''
package com.practice.bluetoothmodule;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
public class MainActivity extends AppCompatActivity {
TextView bthStatus;
Button bthOn;
Button bthOff;
Button bthCon;
BluetoothAdapter bthAdapter;
Set<BluetoothDevice> pairedDevices;
List<String> listofPairedDevices;
private String btAddress=null;
BluetoothDevice bthDevice;
AcceptThread acceptThread;
ConnectThread connectThread;
private Handler mHandler = null;
final static int BT_REQUEST_ENABLE=1;
final static UUID BT_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bthStatus = (TextView)findViewById(R.id.text_check);
bthOn = (Button)findViewById(R.id.bth_on);
bthOff=(Button)findViewById(R.id.bth_off);
bthCon=(Button)findViewById(R.id.dev_con);
bthAdapter=BluetoothAdapter.getDefaultAdapter();
bthOn.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View view){
bluetoothOn();
}
});
bthOff.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View view){
bluetoothOff();
}
});
bthCon.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View view){
listPairedDevices();
}
});
}
#Override
public void onStart(){
super.onStart();
}
#Override
public void onDestroy(){
super.onDestroy();
if(acceptThread != null){
acceptThread.cancel();
acceptThread=null;
}
if(connectThread != null){
connectThread.cancel();
connectThread=null;
}
}
void bluetoothOn(){
if(bthAdapter == null){
Toast.makeText(getApplicationContext(),"블루투스를 지원하지 않는 기기입니다",Toast.LENGTH_SHORT).show();
}
else{
if(bthAdapter.isEnabled()){
Toast.makeText(getApplicationContext(),"블루투스가 이미 활성화된 상태입니다",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(),"블루투스가 활성화 되어 있지 않습니다",Toast.LENGTH_SHORT).show();
Intent intentBthEnable = new Intent(bthAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intentBthEnable,BT_REQUEST_ENABLE);
}
}
}
void bluetoothOff(){
if(bthAdapter.isEnabled()){
bthAdapter.disable();
Toast.makeText(getApplicationContext(),"블루투스가 비활성화 되었습니다.",Toast.LENGTH_SHORT).show();
bthStatus.setText("비활성화");
}
else{
Toast.makeText(getApplicationContext(),"블루투스가 이미 비활성화 상태입니다",Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
switch(requestCode){
case BT_REQUEST_ENABLE:
if(resultCode == RESULT_OK){
Toast.makeText(getApplicationContext(),"블루투스 활성화",Toast.LENGTH_LONG).show();
bthStatus.setText("활성화");
start();
} else if(resultCode == RESULT_CANCELED){
Toast.makeText(getApplicationContext(),"취소",Toast.LENGTH_LONG).show();
bthStatus.setText("비활성화");
}
break;
}
super.onActivityResult(requestCode,resultCode,data);
}
void listPairedDevices(){
if(bthAdapter.isEnabled()){
pairedDevices = bthAdapter.getBondedDevices();
if(pairedDevices.size()>0){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("장치 선택");
listofPairedDevices = new ArrayList();
for(BluetoothDevice device: pairedDevices){
listofPairedDevices.add(device.getName());
}
final CharSequence[] items= listofPairedDevices.toArray(new CharSequence[listofPairedDevices.size()]);
listofPairedDevices.toArray(new CharSequence[listofPairedDevices.size()]);
builder.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
connectSelectedDevice(items[item].toString());
}
});
AlertDialog alert=builder.create();
alert.show();
}
else{
Toast.makeText(getApplicationContext(),"페어링된 장치가 없습니다",Toast.LENGTH_LONG).show();
}
}
else{
Toast.makeText(getApplicationContext(),"블루투스가 비활성화 되어 있습니다.",Toast.LENGTH_LONG).show();
}
}
void connectSelectedDevice(String selectedDeviceName){
for(BluetoothDevice tempDevice: pairedDevices){
if(selectedDeviceName.equals(tempDevice.getName())){
bthDevice=tempDevice;
btAddress=bthDevice.getAddress();
break;
}
}
connect(bthDevice);
//Toast.makeText(getApplicationContext(),"연결 시도"+bthDevice.getName(),Toast.LENGTH_LONG).show();
}
public synchronized void start(){
acceptThread = new AcceptThread();
acceptThread.start();
}
public synchronized void connect(BluetoothDevice device){
connectThread=new ConnectThread(device);
connectThread.start();
}
private class AcceptThread extends Thread{
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp=null;
try{
tmp=bthAdapter.listenUsingRfcommWithServiceRecord("Listen",BT_UUID);
Toast.makeText(getApplicationContext(),"서버 열림",Toast.LENGTH_LONG).show();
}catch(IOException e){
Toast.makeText(getApplicationContext(),"서버 안열림",Toast.LENGTH_LONG).show();
}
mmServerSocket=tmp;
}
public void run(){
BluetoothSocket socket=null;
while(true){
try{
socket=mmServerSocket.accept();
} catch(IOException e){
break;
}
if(socket != null){
Toast.makeText(getApplicationContext(),"연결됨",Toast.LENGTH_SHORT).show();
try{
sleep(3000);
} catch (Exception e){}
}
}
}
public void cancel(){
try{
mmServerSocket.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
private class ConnectThread extends Thread{
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device){
BluetoothSocket tmp=null;
mmDevice=device;
try{
tmp=device.createRfcommSocketToServiceRecord(BT_UUID);
//Toast.makeText(getApplicationContext(),"클라 초기화 됨.",Toast.LENGTH_LONG).show();
}catch (IOException e){
//Toast.makeText(getApplicationContext(),"클라 초기화 실패.",Toast.LENGTH_LONG).show();
}
mmSocket=tmp;
//Toast.makeText(getApplicationContext(),"클라 초기화",Toast.LENGTH_LONG).show();
}
public void run() {
try {
bthAdapter.cancelDiscovery();
mmSocket.connect();
Toast.makeText(getApplicationContext(), "클라이언트 연결", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "연결실패", Toast.LENGTH_LONG).show();
}
}
public void cancel(){
try{
mmSocket.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
'''
With Android device, Enable BluetoothHCISnoop log to know , what is happening . It will give the sequential flow on what is happening with Bluetooth communication.
https://www.androidcentral.com/all-about-your-phones-developer-options
The following reasons may be the cause:
1. In your code the device address may be wrong
2. The service UUID which you are trying to connect should be present in the service discovery database of remote bluetooth device
3. The app should wait for connect to happen How to programmatically tell if a Bluetooth device is connected?

How to connect multiple clients to one host via Wifi P2P

I'm trying to create a WiFiP2P to communicate with 2 android phones and one Raspberry Pi. I want one phone as host and the second phone + Raspberry Pi as clients.
Until know i could create a test APP to connect the 2 phones via Wifi direct (tested successful). I was following a great tutorial on Youtube Wifi P2P. Unfortunately the tutorial just show how to connect one host with one client and not multiple clients.
I was trying to follow the Android developer guide, but I have not enough experience to understand everything.
I hope you guys can help me to understand what I have to change in my code and explain me why.
The following code is the exact copy from the mentioned tutorial.
Here my MainActivity:
package com.example.wifip2p;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
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.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
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;
WifiManager wifiManager;
WifiP2pManager mManager;
WifiP2pManager.Channel mChannel;
BroadcastReceiver mReceiver;
IntentFilter mIntentFilter;
List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
String[] deviceNameArray;
WifiP2pDevice[] deviceArray;
static final int MESSAGE_READ=1;
ServerClass serverClass;
ClientClass clientClass;
SendReceive sendReceive;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
1);
}
initialWork();
exqListener();
}
Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
switch (msg.what){
case MESSAGE_READ:
byte[] readBuff = (byte[])msg.obj;
String tempMsg = new String(readBuff,0,msg.arg1);
read_msg_box.setText(tempMsg);
break;
}
return true;
}
});
private void exqListener() {
btnOnOff.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(wifiManager.isWifiEnabled()){
wifiManager.setWifiEnabled(false);
btnOnOff.setText("ON");
if(mManager!=null) {
mManager.removeGroup(mChannel, null);
}
}else{
wifiManager.setWifiEnabled(true);
btnOnOff.setText("OFF");
}
}
});
btnDiscover.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
connectionStatus.setText("Discovery Started");
}
#Override
public void onFailure(int reason) {
connectionStatus.setText("Discovery Starting Failed");
}
});
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int i, long l) {
final WifiP2pDevice device = deviceArray[i];
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(getApplicationContext(),"Connected to " + device.deviceName, Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(int reason) {
Toast.makeText(getApplicationContext(),"Not Connected",Toast.LENGTH_SHORT).show();
}
});
}
});
btnSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msg = writeMsg.getText().toString();
Toast.makeText(getApplicationContext(),"MSG: " + msg,Toast.LENGTH_SHORT).show();
sendReceive.write(msg.getBytes());
}
});
}
private void initialWork() {
btnOnOff= findViewById(R.id.onOff);
btnDiscover = findViewById(R.id.discover);
btnSend = findViewById(R.id.sendButton);
listView = findViewById(R.id.peerListView);
read_msg_box = findViewById(R.id.readMsg);
connectionStatus = findViewById(R.id.connectionStatus);
writeMsg = findViewById(R.id.writeMsg);
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
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);
}
WifiP2pManager.PeerListListener peerListListener = new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
if(!peerList.getDeviceList().equals(peers)){
peers.clear();
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.deviceAddress;
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();
}
}
};
WifiP2pManager.ConnectionInfoListener connectionInfoListener = new WifiP2pManager.ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo) {
final InetAddress groupOwnerAddress = wifiP2pInfo.groupOwnerAddress;
if(wifiP2pInfo.groupFormed && wifiP2pInfo.isGroupOwner){
connectionStatus.setText("Host");
serverClass=new ServerClass();
serverClass.start();
}else if(wifiP2pInfo.groupFormed){
connectionStatus.setText("Client");
clientClass = new ClientClass(groupOwnerAddress);
clientClass.start();
}
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver,mIntentFilter);
}
#Override
protected void onPause() {
super.onPause();
registerReceiver(mReceiver,mIntentFilter);
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
clientClass.socket.close();
serverClass.serverSocket.close();
serverClass.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void finalize() throws Throwable {
super.finalize();
try {
clientClass.socket.close();
serverClass.serverSocket.close();
serverClass.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public class ServerClass extends Thread{
Socket socket;
ServerSocket serverSocket;
#Override
public void run() {
// serverSocket= null;
// socket = null;
try {
Log.i("ServerSocket is called", "Called");
serverSocket = new ServerSocket(8888);
socket = serverSocket.accept();
sendReceive = new SendReceive(socket);
sendReceive.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class SendReceive extends Thread{
private Socket socket;
private InputStream inputStream;
private OutputStream outputStream;
public SendReceive(Socket skt){
socket = skt;
try {
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while(socket!=null){
try {
bytes = inputStream.read(buffer);
if(bytes > 0){
handler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void write (byte[] bytes){
try {
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ClientClass extends Thread{
Socket socket;
String hostAdd;
public ClientClass(InetAddress hostAddress){
hostAdd = hostAddress.getHostAddress();
// socket = null;
socket = new Socket();
}
#Override
public void run() {
try {
socket.connect(new InetSocketAddress(hostAdd,8888),500);
sendReceive = new SendReceive(socket);
sendReceive.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Here my BroadcastReceiver Class:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pManager;
import android.nfc.Tag;
import android.util.Log;
import android.widget.Toast;
import static android.content.ContentValues.TAG;
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private WifiP2pManager mManager;
private WifiP2pManager.Channel mChannel;
private MainActivity mActivity;
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();
if(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)){
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,-1);
if(state==WifiP2pManager.WIFI_P2P_STATE_ENABLED){
Toast.makeText(context,"Wifi is ON",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context,"Wifi is OFF",Toast.LENGTH_SHORT).show();
}
}else if(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)){
if(mManager!=null){
mManager.requestPeers(mChannel,mActivity.peerListListener);
}
Log.d(TAG, "onReceive: P2P peers changed");
}else if(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)){
if(mManager==null){
return;
}
NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
if(networkInfo.isConnected()){
mManager.requestConnectionInfo(mChannel,mActivity.connectionInfoListener);
}else{
mActivity.connectionStatus.setText("Device Disconnected");
}
}else if(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)){
//do something
}
}
}

I'm trying to add GPS functionality to my android app, gps coordinates come out to 0.0, 0.0 every time

I'd like to check GPS both when the app is started and when the refresh button is hit, and use those data points, in the form of mLatitude and mLongitude to call the weather api. Eventually I'm going to geocode the city but right now for debugging purposes I'm outputting the GPS coordinates to the locationLabel textview.
my MainActivity.java:
package com.example.paxie.stormy.ui;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.paxie.stormy.GPS_Service;
import com.example.paxie.stormy.R;
import com.example.paxie.stormy.weather.Current;
import com.example.paxie.stormy.weather.Day;
import com.example.paxie.stormy.weather.Forecast;
import com.example.paxie.stormy.weather.Hour;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
public static final String DAILY_FORECAST = "DAILY_FORECAST";
public static final String HOURLY_FORECAST = "HOURLY_FORECAST";
private Forecast mForecast;
private double mLatitude;
private double mLongitude;
private BroadcastReceiver broadcastReceiver;
#Bind(R.id.timeLabel)
TextView mTimeLabel;
#Bind(R.id.temperatureLabel)
TextView mTemperatureLabel;
#Bind(R.id.humidityValue)
TextView mHumidityValue;
#Bind(R.id.precipValue)
TextView mPrecipValue;
#Bind(R.id.summaryLabel)
TextView mSummaryLabel;
#Bind(R.id.iconImageView)
ImageView mIconImageView;
#Bind(R.id.refreshImageView)
ImageView mRefreshImageView;
#Bind(R.id.progressBar)
ProgressBar mProgressBar;
#Bind(R.id.locationLabel)
TextView mLocationlabel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mProgressBar.setVisibility(View.INVISIBLE);
mRefreshImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getForecast();
}
});
getForecast();
Log.d(TAG, "Main UI code is running!");
}
private void getForecast() {
if(!runtime_permissions())
checkGPS();
String apiKey = "1621390f8c36997cb1904914b726df52";
String forecastUrl = "https://api.forecast.io/forecast/" + apiKey +
"/" + mLatitude + "," + mLongitude;
if (isNetworkAvailable()) {
toggleRefresh();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecastUrl)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleRefresh();
}
});
alertUserAboutError();
}
#Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleRefresh();
}
});
try {
String jsonData = response.body().string();
Log.v(TAG, jsonData);
if (response.isSuccessful()) {
mForecast = parseForecastDetails(jsonData);
runOnUiThread(new Runnable() {
#Override
public void run() {
updateDisplay();
}
});
} else {
alertUserAboutError();
}
} catch (IOException e)
{
Log.e(TAG, "Exception caught: ", e);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
} else {
Toast.makeText(this, "Network is currently unavailable!", Toast.LENGTH_LONG).show();
}
}
private void toggleRefresh() {
if (mProgressBar.getVisibility() == View.INVISIBLE) {
mProgressBar.setVisibility(View.VISIBLE);
mRefreshImageView.setVisibility(View.INVISIBLE);
} else {
mProgressBar.setVisibility(View.INVISIBLE);
mRefreshImageView.setVisibility(View.VISIBLE);
}
}
private void updateDisplay() {
mLocationlabel.setText(mLatitude + " " + mLongitude);
Current current = mForecast.getCurrent();
mTemperatureLabel.setText(current.getTemperature() + "");
mTimeLabel.setText("At " + current.getFormattedTime() + " it will be:");
mHumidityValue.setText(current.getHumidity() + "");
mPrecipValue.setText(current.getPrecipChance() + "%");
mSummaryLabel.setText(current.getSummary());
Drawable drawable = ContextCompat.getDrawable(this, current.getIconId());
mIconImageView.setImageDrawable(drawable);
}
private Forecast parseForecastDetails(String jsonData) throws JSONException {
Forecast forecast = new Forecast();
forecast.setCurrent(getCurrentDetails(jsonData));
forecast.setHourlyForecast(getHourlyForecast(jsonData));
forecast.setDailyForecast(getDailyForecast(jsonData));
return forecast;
}
private Day[] getDailyForecast(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
JSONObject daily = forecast.getJSONObject("daily");
JSONArray data = daily.getJSONArray("data");
Day[] days = new Day[data.length()];
for (int i = 0; i < data.length(); i++) {
JSONObject jsonDay = data.getJSONObject(i);
Day day = new Day();
day.setSummary(jsonDay.getString("summary"));
day.setIcon(jsonDay.getString("icon"));
day.setTemperatureMax(jsonDay.getDouble("temperatureMax"));
day.setTime(jsonDay.getLong("time"));
day.setTimeZone(timezone);
days[i] = day;
}
return days;
}
private Hour[] getHourlyForecast(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
JSONObject hourly = forecast.getJSONObject("hourly");
JSONArray data = hourly.getJSONArray("data");
Hour[] hours = new Hour[data.length()];
for (int i = 0; i < data.length(); i++) {
JSONObject jsonHour = data.getJSONObject(i);
Hour hour = new Hour();
hour.setSummary(jsonHour.getString("summary"));
hour.setTemperature(jsonHour.getDouble("temperature"));
hour.setIcon(jsonHour.getString("icon"));
hour.setTime(jsonHour.getLong("time"));
hour.setTimeZone(timezone);
hours[i] = hour;
}
return hours;
}
private Current getCurrentDetails(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
Log.i(TAG, "From JSON: " + timezone);
JSONObject currently = forecast.getJSONObject("currently");
Current current = new Current();
current.setHumidity(currently.getDouble("humidity"));
current.setTime(currently.getLong("time"));
current.setIcon(currently.getString("icon"));
current.setPrecipChance(currently.getDouble("precipProbability"));
current.setSummary(currently.getString("summary"));
current.setTemperature(currently.getDouble("temperature"));
current.setTimeZone(timezone);
Log.d(TAG, current.getFormattedTime());
return current;
}
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected()) {
isAvailable = true;
}
return isAvailable;
}
private void alertUserAboutError() {
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.show(getFragmentManager(), "error_dialog");
}
#OnClick(R.id.dailyButton)
public void startDailyActivity(View view) {
Intent intent = new Intent(this, DailyForecastActivity.class);
intent.putExtra(DAILY_FORECAST, mForecast.getDailyForecast());
startActivity(intent);
}
#OnClick(R.id.hourlyButton)
public void startHourlyActivity(View view) {
Intent intent = new Intent(this, HourlyForecastActivity.class);
intent.putExtra(HOURLY_FORECAST, mForecast.getHourlyForecast());
startActivity(intent);
}
private void checkGPS() {
if (broadcastReceiver == null) {
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
mLatitude = (double) intent.getExtras().get("latitude");
mLongitude = (double) intent.getExtras().get("longitude");
}
};
}
registerReceiver(broadcastReceiver, new IntentFilter("location_update"));
}
private boolean runtime_permissions() {
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
return true;
}
return false;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 100) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
getForecast();
} else {
runtime_permissions();
}
}
}
#Override
protected void onResume() {
super.onResume();
checkGPS();
}
}
my GPSservice.java:
package com.example.paxie.stormy;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.support.annotation.Nullable;
/**
* Created by paxie on 10/27/16.
*/
public class GPS_Service extends Service {
private LocationListener listener;
private LocationManager locationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Intent i = new Intent("location_update");
i.putExtra("coordinates",location.getLongitude()+" "+location.getLatitude());
i.putExtra("longitude", location.getLongitude());
i.putExtra("latitude", location.getLatitude());
sendBroadcast(i);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener);
}
#Override
public void onDestroy() {
super.onDestroy();
if(locationManager != null){
//noinspection MissingPermission
locationManager.removeUpdates(listener);
}
}
}
Here are two things you can try:
1. Please ensure you have included the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in your manifest. If your app targets Android API 23 and above, you will need to include runtime permission handling.
2. Instead of having a LocationListener object as a class member, you should have your Service implement it as an interface and implement its onLocationChanged() method.
Apart from this, you really should consider using the location APIs' in Google Play Services, rather than those in AOSP (i.e. android.location).
See Making Your App Location-Aware

Categories

Resources