Why Wifi direct discovery getting failed on Android 10? - java

at the start of this year I had developed an app Wifi Direct is working fine with all other devices i.e Discovery staring and searching other devices but on Android 10 I am getting Discovery Failed error.
Here my class
public class NotificationsFragment extends Fragment implements View.OnClickListener{
private NotificationsViewModel notificationsViewModel;
private static final int MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1;
private static final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 2;
private static final int MY_PERMISSIONS_REQUEST_REQUIRED_PERMISSION = 3;
private static final int SEPRATION_DIST_THRESHOLD = 50;
private static int device_count = 0;
public RippleBackground rippleBackground;
ImageView centerDeviceIcon;
ArrayList<Point> device_points = new ArrayList<>();
public TextView connectionStatus;
WifiManager wifiManager;
WifiP2pManager mManager;
WifiP2pManager.Channel mChannel;
public static final int PORT_USED = 9584;
BroadcastReceiver mReceiver;
IntentFilter mIntentFilter;
ArrayList<CustomDevice> custom_peers = new ArrayList<>();
ServerClass serverClass;
ClientClass clientClass;
private Menu menu;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
notificationsViewModel =
ViewModelProviders.of(this).get(NotificationsViewModel.class);
View root = inflater.inflate(R.layout.fragment_notifications, container, false);
getPermissions();
initialSetup();
connectionStatus = root.findViewById(R.id.connectionStatus);
rippleBackground = root.findViewById(R.id.content);
centerDeviceIcon = root.findViewById(R.id.centerImage);
centerDeviceIcon.setOnClickListener(this);
return root;
}
private boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menu_inflater = getActivity().getMenuInflater();
menu_inflater.inflate(R.menu.main_menu3, menu);
this.menu = menu;
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.wifi_toggle) {
toggleWifiState();
}
return super.onOptionsItemSelected(item);
}
public class ServerClass extends Thread{
Socket socket;
ServerSocket serverSocket;
#Override
public void run() {
try {
serverSocket = new ServerSocket(PORT_USED);
socket = serverSocket.accept();
com.vikaskonaparthi.origin.SocketHandler.setSocket(socket);
startActivity(new Intent(getActivity().getApplicationContext(), com.vikaskonaparthi.origin.ChatWindow.class));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ClientClass extends Thread{
Socket socket;
String hostAddress;
ClientClass(InetAddress address){
this.socket = new Socket();
this.hostAddress = address.getHostAddress();
}
#Override
public void run() {
try {
socket.connect(new InetSocketAddress(hostAddress, PORT_USED), 500);
com.vikaskonaparthi.origin.SocketHandler.setSocket(socket);
startActivity(new Intent(getActivity().getApplicationContext(), com.vikaskonaparthi.origin.ChatWindow.class));
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mReceiver);
}
#Override
public void onResume() {
super.onResume();
getActivity().registerReceiver(mReceiver, mIntentFilter);
}
private void initialSetup() {
// layout files
// add onClick Listeners
// center button position
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
device_points.add(new Point(size.x / 2, size.y / 2));
Log.d("Tab1", size.x + " " + size.y);
wifiManager = (WifiManager) getActivity().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
mManager = (WifiP2pManager) getActivity().getSystemService(WIFI_P2P_SERVICE);
mChannel = mManager.initialize(getActivity(), getMainLooper(), null);
mReceiver = new com.vikaskonaparthi.origin.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);
}
void checkLocationEnabled(){
LocationManager lm = (LocationManager)NotificationsFragment.this.getActivity().getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {}
if(!gps_enabled && !network_enabled) {
// notify user
new AlertDialog.Builder(getActivity())
.setTitle(R.string.gps_network_not_enabled_title)
.setMessage(R.string.gps_network_not_enabled)
.setPositiveButton(R.string.open_location_settings, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
NotificationsFragment.this.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
})
.setNegativeButton(R.string.Cancel,null)
.show();
}
}
#Override
public void onClick(View v) {
int view_id = v.getId();
if(getIndexFromIdPeerList(view_id) != -1){
int idx = getIndexFromIdPeerList(view_id);
final WifiP2pDevice device = custom_peers.get(idx).device;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(getActivity().getApplicationContext(), "Connected to "+device.deviceName, Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int reason) {
Toast.makeText(getActivity().getApplicationContext(), "Error in connecting to "+device.deviceName, Toast.LENGTH_SHORT).show();
}
});
}else{
switch (v.getId()){
case R.id.centerImage:
rippleBackground.startRippleAnimation();
checkLocationEnabled();
discoverDevices();
break;
default:
break;
}
}
}
private int getIndexFromIdPeerList(int id){
for(CustomDevice d : custom_peers){
if(d.id == id){
return custom_peers.indexOf(d);
}
}
return -1;
}
private int checkPeersListByName(String deviceName){
for(CustomDevice d :custom_peers) {
if (d.deviceName.equals(deviceName)) {
return custom_peers.indexOf(d);
}
}
return -1;
}
private void discoverDevices() {
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
connectionStatus.setText("Discovery Started");
}
#Override
public void onFailure(int reason) {
connectionStatus.setText("Discovery start Failed");
}
});
}
public WifiP2pManager.PeerListListener peerListListener = new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peersList) {
Log.d("DEVICE_NAME", "Listener called"+peersList.getDeviceList().size());
if(peersList.getDeviceList().size() != 0){
// first make a list of all devices already present
ArrayList<CustomDevice> device_already_present = new ArrayList<>();
for(WifiP2pDevice device : peersList.getDeviceList()){
int idx = checkPeersListByName(device.deviceName);
if(idx != -1){
// device already in list
device_already_present.add(custom_peers.get(idx));
}
}
if(device_already_present.size() == peersList.getDeviceList().size()){
// all discovered devices already present
return;
}
// clear previous views
clear_all_device_icons();
// this will remove all devices no longer in range
custom_peers.clear();
// add all devices in range
custom_peers.addAll(device_already_present);
// add all already present devices to the view
for(CustomDevice d : device_already_present){
rippleBackground.addView(d.icon_view);
}
for(WifiP2pDevice device : peersList.getDeviceList()) {
if (checkPeersListByName(device.deviceName) == -1) {
// device not already present
View tmp_device = createNewDevice(device.deviceName);
rippleBackground.addView(tmp_device);
foundDevice(tmp_device);
CustomDevice tmp_device_obj = new CustomDevice();
tmp_device_obj.deviceName = device.deviceName;
tmp_device_obj.id = tmp_device.getId();
tmp_device_obj.device = device;
tmp_device_obj.icon_view = tmp_device;
custom_peers.add(tmp_device_obj);
}
}
}
if(peersList.getDeviceList().size() == 0){
Toast.makeText(getActivity().getApplicationContext(), "No Peers Found", Toast.LENGTH_SHORT).show();
}
}
};
public void clear_all_device_icons(){
if(!custom_peers.isEmpty()){
for(CustomDevice d : custom_peers){
rippleBackground.removeView(getActivity().findViewById(d.id));
}
}
}
public WifiP2pManager.ConnectionInfoListener connectionInfoListener = new WifiP2pManager.ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
final InetAddress groupOwnerAddress = info.groupOwnerAddress;
if(info.groupFormed && info.isGroupOwner){
connectionStatus.setText("HOST");
serverClass = new ServerClass();
serverClass.start();
}else if(info.groupFormed){
connectionStatus.setText("CLIENT");
clientClass = new ClientClass(groupOwnerAddress);
clientClass.start();
}
}
};
Point generateRandomPosition(){
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int SCREEN_WIDTH = size.x;
int SCREEN_HEIGHT = size.y;
int height_start = SCREEN_HEIGHT / 2 - 300;
int x = 0;
int y = 0;
do{
x = (int)(Math.random() * SCREEN_WIDTH);
y = (int)(Math.random() * height_start);
}while(checkPositionOverlap(new Point(x, y)));
Point new_point = new Point(x, y);
device_points.add(new_point);
return new_point;
}
boolean checkPositionOverlap(Point new_p){
// if overlap, then return true, else return false
if(!device_points.isEmpty()){
for(Point p:device_points){
int distance = (int)Math.sqrt(Math.pow(new_p.x - p.x, 2) + Math.pow(new_p.y - p.y, 2));
Log.d(TAG, distance+"");
if(distance < SEPRATION_DIST_THRESHOLD){
return true;
}
}
}
return false;
}
public View createNewDevice(String device_name){
View device1 = LayoutInflater.from(getActivity()).inflate(R.layout.device_icon, null);
Point new_point = generateRandomPosition();
RippleBackground.LayoutParams params = new RippleBackground.LayoutParams(350,350);
params.setMargins(new_point.x, new_point.y, 0, 0);
device1.setLayoutParams(params);
TextView txt_device1 = device1.findViewById(R.id.myImageViewText);
int device_id = (int)System.currentTimeMillis() + device_count++;
txt_device1.setText(device_name);
device1.setId(device_id);
device1.setOnClickListener(this);
device1.setVisibility(View.INVISIBLE);
return device1;
}
private void foundDevice(View foundDevice){
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(400);
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
ArrayList<Animator> animatorList=new ArrayList<Animator>();
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(foundDevice, "ScaleX", 0f, 1.2f, 1f);
animatorList.add(scaleXAnimator);
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(foundDevice, "ScaleY", 0f, 1.2f, 1f);
animatorList.add(scaleYAnimator);
animatorSet.playTogether(animatorList);
foundDevice.setVisibility(View.VISIBLE);
animatorSet.start();
}
private void toggleWifiState() {
if(wifiManager.isWifiEnabled()){
wifiManager.setWifiEnabled(false);
menu.findItem(R.id.wifi_toggle).setTitle("Turn Wifi On");
}else{
wifiManager.setWifiEnabled(true);
menu.findItem(R.id.wifi_toggle).setTitle("Turn Wifi Off");
}
}
public void getPermissions() {
if ((ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED)
|| (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.RECORD_AUDIO,
Manifest.permission.ACCESS_COARSE_LOCATION
},
MY_PERMISSIONS_REQUEST_REQUIRED_PERMISSION);
}
}
}
class CustomDevice{
int id;
String deviceName;
WifiP2pDevice device;
View icon_view;
CustomDevice(){
}
}
Discovery is getting failed only on Android 10 whereas everything and logic is fine from myside.
Here are the included permissions
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <!-- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> -->
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
Thanks in advance
Nooooooo one in this world to help me

Wifi-Direct alliance in android is evolving, We need to understand How the discovery works.
Wifi-Direct discovery will never work if the location services are disabled.
How to check?
LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Toast.makeText(this, "please enable location services", Toast.LENGTH_LONG).show();
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
IF still, the discovery is not working then it comes from the OS, check from the Wifi-Preferences in Wifi-Direct discovery, is your device visible? If not then restart your phone.
About Android 10 and Wifi-Direct
Simply, If it was working on Android 9, it should work for Android 10 out of the box.
NOTE:
Keep this in mind that the Wifi-direct works best when the Location is High Accuracy.
Please uncomment the FINE_LOCATION permission in manifest and ask it on runtime from code.

I was facing the same problem when I upgraded to Android 10.
However, I solved the problem by activing the GPS location service.

Related

Connect to wifi programmatically on android Q(android10) to transfer files

I'm building a file sharing app like (SHAREit, xender,...). My code is working fine on api level 28 and below. But I'm not able to make it work on android 10. I tried wifisuggestion and WifiNetworkSpecifier api but still not able to share files. (how could apps like SHARE it connect to wifi programmatically on android 10 without even using WifiNetworkSpecifier )?
Here' my code
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.android.share">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Connection Utils
public class ConnectionUtils{ ....initialization...
mWifiManager = (WifiManager) getContext().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
mConnectivityManager = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
}public static ConnectionUtils getInstance(Context context) {
return new ConnectionUtils(context);
}
public static String getCleanNetworkName(String networkName) {
if (networkName == null)
return "";
return networkName.replace("\"", "");
}
public boolean canAccessLocation() {
return hasLocationPermission(getContext()) && isLocationServiceEnabled();
}
public boolean canReadScanResults() {
return getWifiManager().isWifiEnabled() && (Build.VERSION.SDK_INT < 23 || canAccessLocation());
}
public boolean disableCurrentNetwork() {
return isConnectedToAnyNetwork()
&& getWifiManager().disconnect()
&& getWifiManager().disableNetwork(getWifiManager().getConnectionInfo().getNetworkId());
}
#WorkerThread
public String establishHotspotConnection(final Interrupter interrupter,
final NetworkDeviceListAdapter.HotspotNetwork hotspotNetwork,
final ConnectionCallback connectionCallback) {
final int pingTimeout = 1000; // ms
final long startTime = System.currentTimeMillis();
String remoteAddress = null;
boolean connectionToggled = false;
boolean secondAttempt = false;
boolean thirdAttempt = false;
while (true) {
int passedTime = (int) (System.currentTimeMillis() - startTime);
if (passedTime >= 10000 && !secondAttempt) {
secondAttempt = true;
disableCurrentNetwork();
connectionToggled = false;
}
if (passedTime >= 20000 && !thirdAttempt) {
thirdAttempt = true;
disableCurrentNetwork();
connectionToggled = false;
}
if (!getWifiManager().isWifiEnabled()) {
Log.d(TAG, "establishHotspotConnection(): Wifi is off. Making a request to turn it on");
if (!getWifiManager().setWifiEnabled(true)) {
Log.d(TAG, "establishHotspotConnection(): Wifi was off. The request has failed. Exiting.");
break;
}
}
else if (!isConnectedToNetwork(hotspotNetwork) && !connectionToggled) {
Log.d(TAG, "establishHotspotConnection(): Requested network toggle");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
toggleConnection(hotspotNetwork);
}
else{
connect(hotspotNetwork.SSID,hotspotNetwork.password);
}
connectionToggled = true;
} else {
Log.d(TAG, "establishHotspotConnection(): Waiting to connect to the server");
final DhcpInfo routeInfo = getWifiManager().getDhcpInfo();
//Log.w(TAG, String.format("establishHotspotConnection(): DHCP: %s", routeInfo));
if (routeInfo != null && routeInfo.gateway != 0) {
final String testedRemoteAddress = NetworkUtils.convertInet4Address(routeInfo.gateway);
Log.d(TAG, String.format("establishHotspotConnection(): DhcpInfo: gateway: %s dns1: %s dns2: %s ipAddr: %s serverAddr: %s netMask: %s",
testedRemoteAddress,
NetworkUtils.convertInet4Address(routeInfo.dns1),
NetworkUtils.convertInet4Address(routeInfo.dns2),
NetworkUtils.convertInet4Address(routeInfo.ipAddress),
NetworkUtils.convertInet4Address(routeInfo.serverAddress),
NetworkUtils.convertInet4Address(routeInfo.netmask)));
Log.d(TAG, "establishHotspotConnection(): There is DHCP info provided waiting to reach the address " + testedRemoteAddress);
if (UIConnectionUtils.isOSAbove(Build.VERSION_CODES.P)
? NetworkUtils.ping(testedRemoteAddress, pingTimeout)
: NetworkUtils.ping(testedRemoteAddress)) {
Log.d(TAG, "establishHotspotConnection(): AP has been reached. Returning OK state.");
remoteAddress = testedRemoteAddress;
break;
} else
Log.d(TAG, "establishHotspotConnection(): Connection check ping failed");
} else
Log.d(TAG, "establishHotspotConnection(): No DHCP provided. Looping...");
}
if (connectionCallback.onTimePassed(1000, passedTime) || interrupter.interrupted()) {
Log.d(TAG, "establishHotspotConnection(): Timed out or onTimePassed returned true. Exiting...");
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
return remoteAddress;
}
public boolean hasLocationPermission(Context context) {
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
public Context getContext() {
return mContext;
}
public ConnectivityManager getConnectivityManager() {
return mConnectivityManager;
}
public HotspotUtils getHotspotUtils() {
return mHotspotUtils;
}
public LocationManager getLocationManager() {
return mLocationManager;
}
public WifiManager getWifiManager() {
return mWifiManager;
}
public boolean isConnectionSelfNetwork() {
WifiInfo wifiInfo = getWifiManager().getConnectionInfo();
return wifiInfo != null
&& getCleanNetworkName(wifiInfo.getSSID()).startsWith(AppConfig.PREFIX_ACCESS_POINT);
}
public boolean isConnectedToAnyNetwork() {
NetworkInfo info = getConnectivityManager().getActiveNetworkInfo();
return info != null
&& info.getType() == ConnectivityManager.TYPE_WIFI
&& info.isConnected();
}
public boolean isConnectedToNetwork(NetworkDeviceListAdapter.HotspotNetwork hotspotNetwork) {
if (!isConnectedToAnyNetwork())
return false;
if (hotspotNetwork.BSSID != null)
return hotspotNetwork.BSSID.equals(getWifiManager().getConnectionInfo().getBSSID());
return hotspotNetwork.SSID.equals(getCleanNetworkName(getWifiManager().getConnectionInfo().getSSID()));
}
public boolean isLocationServiceEnabled() {
return mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
public boolean isMobileDataActive() {
return mConnectivityManager.getActiveNetworkInfo() != null
&& mConnectivityManager.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_MOBILE;
}
public boolean toggleConnection(NetworkDeviceListAdapter.HotspotNetwork hotspotNetwork) {
if (!isConnectedToNetwork(hotspotNetwork)) {
if (isConnectedToAnyNetwork())
disableCurrentNetwork();
WifiConfiguration config = new WifiConfiguration();
config.SSID = String.format("\"%s\"", hotspotNetwork.SSID);
...........(configuation)
try {
int netId = getWifiManager().addNetwork(config);
if (/*Build.VERSION.SDK_INT >= */UIConnectionUtils.isOSAbove(Build.VERSION_CODES.M)) {
#SuppressLint("MissingPermission") List<WifiConfiguration> list = getWifiManager().getConfiguredNetworks();
for (WifiConfiguration hotspotWifi : list) {
if (hotspotWifi.SSID != null && hotspotWifi.SSID.equalsIgnoreCase(config.SSID)) {
getWifiManager().disconnect();
getWifiManager().enableNetwork(hotspotWifi.networkId, true);
return getWifiManager().reconnect();
}
}
} else {
getWifiManager().disconnect();
getWifiManager().enableNetwork(netId, true);
return getWifiManager().reconnect();
}
} catch (Exception exp) {
disableCurrentNetwork();
return false;
}
}
disableCurrentNetwork();
return false;
}
public interface ConnectionCallback {
boolean onTimePassed(int delimiter, long timePassed);
}
#RequiresApi(api = Build.VERSION_CODES.Q)
public boolean connect(String ssid, String password){
if (mConnectivityManager == null) {
return false;
}
NetworkSpecifier networkSpecifier;
networkSpecifier = new WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(password)
.build();
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(networkSpecifier)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
mConnectivityManager.requestNetwork(networkRequest, mNetworkCallback);
return true;
}
#RequiresApi(api = Build.VERSION_CODES.Q)
private ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager.NetworkCallback(){
#Override
public void onAvailable(#NonNull Network network) {
super.onAvailable(network);
//phone is connected to wifi network
mConnectivityManager.bindProcessToNetwork(network);
}
...implement members}
UiConnectionUtil
public class UIConnectionUtils{ initialize .... public void makeAcquaintance(final Activity activity, final UITask task, final Object object, final int accessPin,
final NetworkDeviceLoader.OnDeviceRegisteredListener registerListener)
{
WorkerService.RunningTask runningTask = new WorkerService.RunningTask()
{
private boolean mConnected = false;
private String mRemoteAddress;
#Override
public void onRun()
{
final DialogInterface.OnClickListener retryButtonListener = new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
makeAcquaintance(activity, task, object, accessPin, registerListener);
}
};
try {
if (object instanceof NetworkDeviceListAdapter.HotspotNetwork) {
mRemoteAddress = getConnectionUtils().establishHotspotConnection(getInterrupter(),
(NetworkDeviceListAdapter.HotspotNetwork) object,
new ConnectionUtils.ConnectionCallback()
{
#Override
public boolean onTimePassed(int delimiter, long timePassed)
{
return timePassed >= 30000;
}
});
} else if (object instanceof String)
mRemoteAddress = (String) object;
if (mRemoteAddress != null) {
mConnected = setupConnection(activity, mRemoteAddress, accessPin, new NetworkDeviceLoader.OnDeviceRegisteredListener()
{
#Override
public void onDeviceRegistered(final AccessDatabase database, final NetworkDevice device, final NetworkDevice.Connection connection)
{
// we may be working with direct IP scan
new Handler(Looper.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
if (registerListener != null)
registerListener.onDeviceRegistered(database, device, connection);
}
});
}
}, retryButtonListener) != null;
}
if (!mConnected && !getInterrupter().interruptedByUser())
new Handler(Looper.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
if (!activity.isFinishing()) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity)
.setMessage(R.string.mesg_connectionFailure)
.setNegativeButton(R.string.butn_close, null)
.setPositiveButton(R.string.butn_retry, retryButtonListener);
if (object instanceof NetworkDevice)
dialogBuilder.setTitle(((NetworkDevice) object).nickname);
dialogBuilder.show();
}
}
});
} catch (Exception e) {
} finally {
new Handler(Looper.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
if (task != null && !activity.isFinishing())
task.updateTaskStopped();
}
});
}
// We can't add dialog outside of the else statement as it may close other dialogs as well
}
}.setTitle(activity.getString(R.string.mesg_completing))
.setIconRes(R.drawable.ic_compare_arrows_white_24dp_static);
runningTask.run(activity);
if (task != null)
task.updateTaskStarted(runningTask.getInterrupter());
}
public boolean notifyWirelessRequestHandled()
{
boolean returnedState = mWirelessEnableRequested;
mWirelessEnableRequested = false;
return returnedState;
}
#WorkerThread
public NetworkDevice setupConnection(final Activity activity,
final String ipAddress,
final int accessPin,
final NetworkDeviceLoader.OnDeviceRegisteredListener listener,
final DialogInterface.OnClickListener retryButtonListener)
{
return CommunicationBridge.connect(AppUtils.getDatabase(activity), NetworkDevice.class, new CommunicationBridge.Client.ConnectionHandler()
{
#Override
public void onConnect(CommunicationBridge.Client client)
{
try {
client.setSecureKey(accessPin);
CoolSocket.ActiveConnection activeConnection = client.connectWithHandshake(ipAddress, false);
NetworkDevice device = client.loadDevice(activeConnection);
activeConnection.reply(new JSONObject()
.put(Keyword.REQUEST, Keyword.REQUEST_ACQUAINTANCE)
.toString());
JSONObject receivedReply = new JSONObject(activeConnection.receive().response);
if (receivedReply.has(Keyword.RESULT)
&& receivedReply.getBoolean(Keyword.RESULT)
&& device.deviceId != null) {
final NetworkDevice.Connection connection = NetworkDeviceLoader.processConnection(AppUtils.getDatabase(activity), device, ipAddress);
device.lastUsageTime = System.currentTimeMillis();
device.tmpSecureKey = accessPin;
device.isRestricted = false;
device.isTrusted = true;
AppUtils.getDatabase(activity).publish(device);
if (listener != null)
listener.onDeviceRegistered(AppUtils.getDatabase(activity), device, connection);
} else
showConnectionRejectionInformation(activity, device, receivedReply, retryButtonListener);
client.setReturn(device);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public interface RequestWatcher
{
void onResultReturned(boolean result, boolean shouldWait);
}}

How to auto play first video in recyclerview in ExoPlayer

I have a problem in my code. I want to autoplay first video from recyclerview in ExoPlayer, The player is working good on scroll but the first video does not play automatically
public class VideoPlayerRecyclerView extends RecyclerView {
private static final String TAG = "VideoPlayerRecyclerView";
private enum VolumeState {ON, OFF};
// ui
private ImageView thumbnail, volumeControl;
private ProgressBar progressBar;
private View viewHolderParent;
private FrameLayout frameLayout;
private PlayerView videoSurfaceView;
private SimpleExoPlayer videoPlayer;
// vars
private ArrayList<Status_Bakend> mediaObjects = new ArrayList<>();
private int videoSurfaceDefaultHeight = 0;
private int screenDefaultHeight = 0;
private Context context;
private int playPosition = -1;
private boolean isVideoViewAdded;
private RequestManager requestManager;
// controlling playback state
private VolumeState volumeState;
public VideoPlayerRecyclerView(#NonNull Context context) {
super(context);
init(context);
}
public VideoPlayerRecyclerView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(final Context context){
this.context = context.getApplicationContext();
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Point point = new Point();
display.getSize(point);
videoSurfaceDefaultHeight = point.x;
screenDefaultHeight = point.y;
videoSurfaceView = new PlayerView(this.context);
videoSurfaceView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
// 2. Create the player
videoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
// Bind the player to the view.
videoSurfaceView.setUseController(false);
videoSurfaceView.setPlayer(videoPlayer);
setVolumeControl(VolumeState.ON);
playVideo(true);
videoPlayer.setPlayWhenReady(true);
addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
Log.d(TAG, "onScrollStateChanged: called.");
if(thumbnail != null){ // show the old thumbnail
thumbnail.setVisibility(VISIBLE);
}
// There's a special case when the end of the list has been reached.
// Need to handle that with this bit of logic
if(!recyclerView.canScrollVertically(1)){
playVideo(true);
}
else{
playVideo(false);
}
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
addOnChildAttachStateChangeListener(new OnChildAttachStateChangeListener() {
#Override
public void onChildViewAttachedToWindow(View view) {
}
#Override
public void onChildViewDetachedFromWindow(View view) {
if (viewHolderParent != null && viewHolderParent.equals(view)) {
resetVideoView();
}
}
});
videoPlayer.addListener(new Player.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, #Nullable Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_BUFFERING:
Log.e(TAG, "onPlayerStateChanged: Buffering video.");
if (progressBar != null) {
progressBar.setVisibility(VISIBLE);
}
break;
case Player.STATE_ENDED:
Log.d(TAG, "onPlayerStateChanged: Video ended.");
videoPlayer.seekTo(0);
break;
case Player.STATE_IDLE:
break;
case Player.STATE_READY:
Log.e(TAG, "onPlayerStateChanged: Ready to play.");
if (progressBar != null) {
progressBar.setVisibility(GONE);
}
if(!isVideoViewAdded){
addVideoView();
}
break;
default:
break;
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
}
public void playVideo(boolean isEndOfList) {
int targetPosition;
if(!isEndOfList){
int startPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
int endPosition = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
// if there is more than 2 list-items on the screen, set the difference to be 1
if (endPosition - startPosition > 1) {
endPosition = startPosition + 1;
}
// something is wrong. return.
if (startPosition < 0 || endPosition < 0) {
return;
}
// if there is more than 1 list-item on the screen
if (startPosition != endPosition) {
int startPositionVideoHeight = getVisibleVideoSurfaceHeight(startPosition);
int endPositionVideoHeight = getVisibleVideoSurfaceHeight(endPosition);
targetPosition = startPositionVideoHeight > endPositionVideoHeight ? startPosition : endPosition;
}
else {
targetPosition = startPosition;
}
}
else{
targetPosition = mediaObjects.size() - 1;
}
Toast.makeText(context, "playVideo: target position: " + targetPosition, Toast.LENGTH_SHORT).show();
// video is already playing so return
if (targetPosition == playPosition) {
return;
}
// set the position of the list-item that is to be played
playPosition = targetPosition;
if (videoSurfaceView == null) {
return;
}
// remove any old surface views from previously playing videos
videoSurfaceView.setVisibility(INVISIBLE);
removeVideoView(videoSurfaceView);
int currentPosition = targetPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
View child = getChildAt(currentPosition);
if (child == null) {
return;
}
VideoPlayerViewHolder holder = (VideoPlayerViewHolder) child.getTag();
if (holder == null) {
playPosition = -1;
return;
}
thumbnail = holder.thumbnail;
progressBar = holder.progressBar;
volumeControl = holder.volumeControl;
viewHolderParent = holder.itemView;
requestManager = holder.requestManager;
frameLayout = holder.itemView.findViewById(R.id.media_container);
videoSurfaceView.setPlayer(videoPlayer);
videoPlayer.addVideoListener(new VideoListener() {
#Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
frameLayout.getLayoutParams().height = (height * 2);
}
#Override
public void onRenderedFirstFrame() {
}
});
viewHolderParent.setOnClickListener(videoViewClickListener);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(
context, Util.getUserAgent(context, "RecyclerView VideoPlayer"));
String mediaUrl = mediaObjects.get(targetPosition).getStatus_link();
if (mediaUrl != null) {
MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(mediaUrl));
videoPlayer.prepare(videoSource);
videoPlayer.setPlayWhenReady(true);
}
}
private OnClickListener videoViewClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
toggleVolume();
}
};
/**
* Returns the visible region of the video surface on the screen.
* if some are cut off, it will return less than the #videoSurfaceDefaultHeight
* #param playPosition
* #return
*/
private int getVisibleVideoSurfaceHeight(int playPosition) {
int at = playPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
Log.d(TAG, "getVisibleVideoSurfaceHeight: at: " + at);
View child = getChildAt(at);
if (child == null) {
return 0;
}
int[] location = new int[2];
child.getLocationInWindow(location);
if (location[1] < 0) {
return location[1] + videoSurfaceDefaultHeight;
} else {
return screenDefaultHeight - location[1];
}
}
// Remove the old player
private void removeVideoView(PlayerView videoView) {
ViewGroup parent = (ViewGroup) videoView.getParent();
if (parent == null) {
return;
}
int index = parent.indexOfChild(videoView);
if (index >= 0) {
parent.removeViewAt(index);
isVideoViewAdded = false;
viewHolderParent.setOnClickListener(null);
}
}
private void addVideoView(){
frameLayout.addView(videoSurfaceView);
isVideoViewAdded = true;
videoSurfaceView.requestFocus();
videoSurfaceView.setVisibility(VISIBLE);
videoSurfaceView.setAlpha(1);
}
private void resetVideoView(){
if(isVideoViewAdded){
removeVideoView(videoSurfaceView);
playPosition = -1;
videoSurfaceView.setVisibility(INVISIBLE);
}
}
public void releasePlayer() {
if (videoPlayer != null) {
videoPlayer.release();
videoPlayer = null;
}
viewHolderParent = null;
}
private void toggleVolume() {
if (videoPlayer != null) {
if (volumeState == VolumeState.OFF) {
Log.d(TAG, "togglePlaybackState: enabling volume.");
setVolumeControl(VolumeState.ON);
} else if(volumeState == VolumeState.ON) {
Log.d(TAG, "togglePlaybackState: disabling volume.");
setVolumeControl(VolumeState.OFF);
}
}
}
private void setVolumeControl(VolumeState state){
volumeState = state;
if(state == VolumeState.OFF){
videoPlayer.setVolume(0f);
animateVolumeControl();
}
else if(state == VolumeState.ON){
videoPlayer.setVolume(1f);
animateVolumeControl();
}
}
private void animateVolumeControl(){
if(volumeControl != null){
volumeControl.bringToFront();
if(volumeState == VolumeState.OFF){
requestManager.load(R.drawable.ic_favorite_border_black_24dp)
.into(volumeControl);
}
else if(volumeState == VolumeState.ON){
requestManager.load(R.drawable.ic_favorite_border_black_24dp)
.into(volumeControl);
}
volumeControl.animate().cancel();
volumeControl.setAlpha(1f);
volumeControl.animate()
.alpha(0f)
.setDuration(600).setStartDelay(1000);
}
}
public void setMediaObjects(ArrayList<Status_Bakend> mediaObjects){
this.mediaObjects = mediaObjects;
}
}
This is my code on recyclerview scroll working fine on scroll but I want to autoplay my first video in recyclerview without scrolling.
Just add this line after setAdapter to the recycler view.
recyclerView.smoothScrollBy(0, -1);
OR
recyclerView.smoothScrollBy(0, 1);
This will solve your problem.
You only need to make the first video play using postDelayed().
I think the reason is that the views of the RecyclerView items are all drawn on the layout and the video play process are duplicated.

How to take screenshot of activity with camera feed in it?

I'm currently developing an android application which detect objects using camera using tensorflow detection API. I want to take screenshot of the camera activity where the detection is happening.
How can I take screenshot of the camera activity including the camera preview itself?
This code came from tensorflow demo application. I just want to add a screenshot functionality using a button. That's why I added a button and an Image View. The Image View is where the screenshot preview will show but I dont have any idea on how to implement this :(
This is the code for the camera activity:
CameraActivity.java
public abstract class CameraActivity extends Activity
implements OnImageAvailableListener, Camera.PreviewCallback {
private static final Logger LOGGER = new Logger();
private static final int PERMISSIONS_REQUEST = 1;
private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
private static final String PERMISSION_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
private boolean debug = false;
private Handler handler;
private HandlerThread handlerThread;
private boolean useCamera2API;
private boolean isProcessingFrame = false;
private byte[][] yuvBytes = new byte[3][];
private int[] rgbBytes = null;
private int yRowStride;
protected int previewWidth = 0;
protected int previewHeight = 0;
private Runnable postInferenceCallback;
private Runnable imageConverter;
#Override
protected void onCreate(final Bundle savedInstanceState) {
LOGGER.d("onCreate " + this);
super.onCreate(null);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_camera);
if (hasPermission()) {
setFragment();
} else {
requestPermission();
}
}
private byte[] lastPreviewFrame;
protected int[] getRgbBytes() {
imageConverter.run();
return rgbBytes;
}
protected int getLuminanceStride() {
return yRowStride;
}
protected byte[] getLuminance() {
return yuvBytes[0];
}
/**
* Callback for android.hardware.Camera API
*/
#Override
public void onPreviewFrame(final byte[] bytes, final Camera camera) {
if (isProcessingFrame) {
LOGGER.w("Dropping frame!");
return;
}
try {
// Initialize the storage bitmaps once when the resolution is known.
if (rgbBytes == null) {
Camera.Size previewSize = camera.getParameters().getPreviewSize();
previewHeight = previewSize.height;
previewWidth = previewSize.width;
rgbBytes = new int[previewWidth * previewHeight];
onPreviewSizeChosen(new Size(previewSize.width, previewSize.height), 90);
}
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
return;
}
isProcessingFrame = true;
lastPreviewFrame = bytes;
yuvBytes[0] = bytes;
yRowStride = previewWidth;
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420SPToARGB8888(bytes, previewWidth, previewHeight, rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
camera.addCallbackBuffer(bytes);
isProcessingFrame = false;
}
};
processImage();
}
/**
* Callback for Camera2 API
*/
#Override
public void onImageAvailable(final ImageReader reader) {
//We need wait until we have some size from onPreviewSizeChosen
if (previewWidth == 0 || previewHeight == 0) {
return;
}
if (rgbBytes == null) {
rgbBytes = new int[previewWidth * previewHeight];
}
try {
final Image image = reader.acquireLatestImage();
if (image == null) {
return;
}
if (isProcessingFrame) {
image.close();
return;
}
isProcessingFrame = true;
Trace.beginSection("imageAvailable");
final Plane[] planes = image.getPlanes();
fillBytes(planes, yuvBytes);
yRowStride = planes[0].getRowStride();
final int uvRowStride = planes[1].getRowStride();
final int uvPixelStride = planes[1].getPixelStride();
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420ToARGB8888(
yuvBytes[0],
yuvBytes[1],
yuvBytes[2],
previewWidth,
previewHeight,
yRowStride,
uvRowStride,
uvPixelStride,
rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
image.close();
isProcessingFrame = false;
}
};
processImage();
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
Trace.endSection();
return;
}
Trace.endSection();
}
#Override
public synchronized void onStart() {
LOGGER.d("onStart " + this);
super.onStart();
}
#Override
public synchronized void onResume() {
LOGGER.d("onResume " + this);
super.onResume();
handlerThread = new HandlerThread("inference");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
#Override
public synchronized void onPause() {
LOGGER.d("onPause " + this);
if (!isFinishing()) {
LOGGER.d("Requesting finish");
finish();
}
handlerThread.quitSafely();
try {
handlerThread.join();
handlerThread = null;
handler = null;
} catch (final InterruptedException e) {
LOGGER.e(e, "Exception!");
}
super.onPause();
}
#Override
public synchronized void onStop() {
LOGGER.d("onStop " + this);
super.onStop();
}
#Override
public synchronized void onDestroy() {
LOGGER.d("onDestroy " + this);
super.onDestroy();
}
protected synchronized void runInBackground(final Runnable r) {
if (handler != null) {
handler.post(r);
}
}
#Override
public void onRequestPermissionsResult(
final int requestCode, final String[] permissions, final int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
setFragment();
} else {
requestPermission();
}
}
}
private boolean hasPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return checkSelfPermission(PERMISSION_CAMERA) == PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(PERMISSION_STORAGE) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(PERMISSION_CAMERA) ||
shouldShowRequestPermissionRationale(PERMISSION_STORAGE)) {
Toast.makeText(CameraActivity.this,
"Camera AND storage permission are required for this demo", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE}, PERMISSIONS_REQUEST);
}
}
// Returns true if the device supports the required hardware level, or better.
private boolean isHardwareLevelSupported(
CameraCharacteristics characteristics, int requiredLevel) {
int deviceLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
return requiredLevel == deviceLevel;
}
// deviceLevel is not LEGACY, can use numerical sort
return requiredLevel <= deviceLevel;
}
private String chooseCamera() {
final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for (final String cameraId : manager.getCameraIdList()) {
final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
final StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
continue;
}
// Fallback to camera1 API for internal cameras that don't have full support.
// This should help with legacy situations where using the camera2 API causes
// distorted or otherwise broken previews.
useCamera2API = (facing == CameraCharacteristics.LENS_FACING_EXTERNAL)
|| isHardwareLevelSupported(characteristics,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
LOGGER.i("Camera API lv2?: %s", useCamera2API);
return cameraId;
}
} catch (CameraAccessException e) {
LOGGER.e(e, "Not allowed to access camera");
}
return null;
}
protected void setFragment() {
String cameraId = chooseCamera();
Fragment fragment;
if (useCamera2API) {
CameraConnectionFragment camera2Fragment =
CameraConnectionFragment.newInstance(
new CameraConnectionFragment.ConnectionCallback() {
#Override
public void onPreviewSizeChosen(final Size size, final int rotation) {
previewHeight = size.getHeight();
previewWidth = size.getWidth();
CameraActivity.this.onPreviewSizeChosen(size, rotation);
}
},
this,
getLayoutId(),
getDesiredPreviewFrameSize());
camera2Fragment.setCamera(cameraId);
fragment = camera2Fragment;
} else {
fragment =
new LegacyCameraConnectionFragment(this, getLayoutId(), getDesiredPreviewFrameSize());
}
getFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
protected void fillBytes(final Plane[] planes, final byte[][] yuvBytes) {
// Because of the variable row stride it's not possible to know in
// advance the actual necessary dimensions of the yuv planes.
for (int i = 0; i < planes.length; ++i) {
final ByteBuffer buffer = planes[i].getBuffer();
if (yuvBytes[i] == null) {
LOGGER.d("Initializing buffer %d at size %d", i, buffer.capacity());
yuvBytes[i] = new byte[buffer.capacity()];
}
buffer.get(yuvBytes[i]);
}
}
public boolean isDebug() {
return debug;
}
public void requestRender() {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.postInvalidate();
}
}
public void addCallback(final OverlayView.DrawCallback callback) {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.addCallback(callback);
}
}
public void onSetDebug(final boolean debug) {}
#Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
debug = !debug;
requestRender();
onSetDebug(debug);
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void readyForNextImage() {
if (postInferenceCallback != null) {
postInferenceCallback.run();
}
}
protected int getScreenOrientation() {
switch (getWindowManager().getDefaultDisplay().getRotation()) {
case Surface.ROTATION_270:
return 270;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_90:
return 90;
default:
return 0;
}
}
protected abstract void processImage();
protected abstract void onPreviewSizeChosen(final Size size, final int rotation);
protected abstract int getLayoutId();
protected abstract Size getDesiredPreviewFrameSize();
}
And this is the layout file
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="500dp"
tools:context="org.tensorflow.demo.CameraActivity">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Screenshot" />
</FrameLayout>
<ImageView
android:id="#+id/imageView"
android:layout_width="140dp"
android:layout_height="160dp"
android:layout_marginStart="205dp"
android:layout_marginTop="0dp" />
I just want to take screenshot of the activity including the camera where the detection is happening. I tried some tutorials on how to take screenshot. It captures all the parts of the screen but doesnt capture the camera part. It only shows black screen. HELP!

Notif user of his favourite match

I want to create app of hockey results. On home page, user select his favorite team and than he can see in fragment Future Matches - matches of his favorite team.
After this, he can select his favorite match (by click on match) and than, If score is changed in this match, user get notification about changed score.
But I have problem, because when I see future matches, after click on match, application drop.
I don´t have any idea about solve this problem.
I need help with this.
public class Future_matches extends Fragment {
private static Future_matches fragment;
private int favorite_team_id;
private SharedPreferences sp;
private RecyclerView rv_futureMatches;
// private FutureMatchesAdapter adapter;
private List<FutureMatchModel> teams;
private SharedPreferences.Editor ed;
List<Thread> listOfActiveThreads;
private RecyclerView.Adapter<FutureMatchesHolder> adapter;
private RecyclerView.LayoutManager layoutManager;
public Future_matches() {
}
public static Future_matches newInstance() {
if (fragment == null)
fragment = new Future_matches();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listOfActiveThreads = new ArrayList<>();
sp = getActivity().getSharedPreferences(Tools.PACKAGE_NAME, Context.MODE_PRIVATE);
favorite_team_id = sp.getInt(Tools.FAVORITE_TEAM_ID, -1);
ed = sp.edit();
}
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.future_matches, container, false);
rv_futureMatches = rootview.findViewById(R.id.rv_future_matches);
RecyclerView.LayoutManager lm = new LinearLayoutManager(getActivity());
// rv_futureMatches.setLayoutManager(lm);
// rv_futureMatches.setHasFixedSize(true);
if (favorite_team_id == -1) {
Toast.makeText(getActivity(), R.string.warning_future_matches_choose_favorite_team, Toast.LENGTH_SHORT).show();
} else {
Tools.getApi().getFutureMatches(favorite_team_id, "2018-12-27", "2019-05-12").enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.code() == 200) {
teams = JsonTools.convertJsonToFutureMatches(response.body());
// JsonObject data = response.body();
layoutManager = new LinearLayoutManager(getActivity());
layoutManager = new LinearLayoutManager(getContext());
// adapter = new FutureMatchesAdapter(JsonTools.convertJsonToFutureMatches(data), new WeakReference<Context>(getActivity()));
adapter = new FutureMatchesAdapter(teams, new WeakReference<Context>(getActivity()), new FutureMatchesAdapter.TeamClickHandler() {
#Override
public void onClick(int id) {
takeCareOfChanges(id);
}
});
rv_futureMatches.setHasFixedSize(true);
rv_futureMatches.setLayoutManager(layoutManager);
rv_futureMatches.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
return rootview;
}
private boolean isItemInList(int id) {
if (sp.contains(Tools.PREFS_PICKED_GAMES)) {
Set<String> result = sp.getStringSet(Tools.PREFS_PICKED_GAMES, null);
if (result.contains(Integer.toString(id))) {
return true;
} else {
return false;
}
} else
return false;
}
private void takeCareOfChanges(int id) {
if (sp.contains(Tools.PREFS_PICKED_GAMES)) {
Set<String> result = sp.getStringSet(Tools.PREFS_PICKED_GAMES, null);
if (isItemInList(id)) {
result.remove(Integer.toString(id));
ed.putStringSet(Tools.PREFS_PICKED_GAMES, result);
quitService(id);
} else {
result.add(Integer.toString(id));
ed.putStringSet(Tools.PREFS_PICKED_GAMES, result);
launchService(id);
}
} else {
Set<String> result = new HashSet<>();
result.add(Integer.toString(id));
ed.putStringSet(Tools.PREFS_PICKED_GAMES, result);
launchService(id);
}
ed.apply();
}
private void launchService(final int id){
getActivity().startService(new Intent().putExtra(Tools.INTENT_EXTRA_ID,id));
}
private void quitService(int id){
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(new Intent().setAction(Tools.INTENT_ACTION_STOP_SERVICE).putExtra(Tools.INTENT_EXTRA_ID,id));
}
}
public class GameChangeService extends Service {
private final static String TAG = "GameChangeService";
private BroadcastReceiver broadcastReceiver;
private Handler h;
private SharedPreferences sp;
Notification notif;
NotificationManager notifManager;
private SharedPreferences.Editor ed;
private Runnable r;
private int id;
private String CHANNEL_ID = "ID";
private int notifId = 1000;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
sp = getSharedPreferences(Tools.PACKAGE_NAME, Context.MODE_PRIVATE);
ed = sp.edit();
notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
h = new Handler();
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
stopSelf();
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, new IntentFilter(Tools.INTENT_ACTION_STOP_SERVICE));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
id = intent.getIntExtra(Tools.INTENT_EXTRA_ID, -1);
if (id == -1) {
stopSelf();
} else {
r = new Runnable() {
#Override
public void run() {
doStuff(id);
h.postDelayed(r, 15000);
}
};
h.post(r);
return Service.START_STICKY;
}
//TOTO TU JE VELMI DISKUTABILNE
return Service.START_STICKY;
}
private void doStuff(final int id) {
//TODO: Checkni pls ci je boxscore updatovany live alebo nie. Ak je tak ho mozes pouzit v IApiDefinition namiesto live feed
// JA> V schedule je s gamepk aj online zapas s golmi - staci to pouzit
ApiTools.getApi().getGame(id).enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (sp.contains(Integer.toString(id))) {
int povodnyPocetGolovVZapase = sp.getInt(Integer.toString(id), 0);
//Z responsu zistit kolko eventov je teraz v zapase, t.j. ci uz zapas zacal.
//Dalej zistit ci su tam nejake eventy, ktore maju typ goal alebo ENDGAME (asi).
//AK sa zmenil pocet golov, tak posli notifikaciu ze padol gol aj s novym stavom
JsonObject data = response.body();
//pouzijem lastmatchmodel, aj ked to nie je pre toto robene, ale data mi stacia aj z neho
//List<LastMatchModel> livezapasy = new ArrayList<>();
//vytiahnem si zoznam
JsonArray zoznamZapasovZJsonu = data.get("dates").getAsJsonArray();
for (int i = 0; i < zoznamZapasovZJsonu.size(); i++) {
//pouzijem lastmatchmodel, aj ked to nie je pre toto robene, ale data mi stacia aj z neho
LastMatchModel novyZapas = new LastMatchModel();
JsonObject zapasDate = zoznamZapasovZJsonu.get(i).getAsJsonObject();
JsonArray games = zapasDate.get("games").getAsJsonArray();
if (games.size() >= 1) {
JsonObject teams = games.get(0).getAsJsonObject().get("teams").getAsJsonObject();
int golyHostia = teams.get("away").getAsJsonObject().get("score").getAsInt();
String timHostia = teams.get("away").getAsJsonObject().get("team").getAsJsonObject().get("name").getAsString();
int golyDomaci = teams.get("home").getAsJsonObject().get("score").getAsInt();
String timDomaci = teams.get("home").getAsJsonObject().get("team").getAsJsonObject().get("name").getAsString();
if (golyDomaci + golyHostia != povodnyPocetGolovVZapase) {
Intent intent = new Intent(GameChangeService.this, MatchNotification.class);
PendingIntent pendingIntent = PendingIntent.getActivity(GameChangeService.this, 0, intent, 0);
createNotificationChannel();
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(GameChangeService.this, CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("GOAL")
.setContentText(timDomaci + golyDomaci + " vs " + golyHostia + timHostia)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManagerCompat nm = NotificationManagerCompat.from(GameChangeService.this);
nm.notify(notifId, mBuilder.build());
}
}
}
} else {
int povodnyPocetEventovVZapase = 0;
//Z responsu zistit kolko eventov je teraz v zapase, t.j. ci uz zapas zacal.
//Dalej zistit ci su tam nejake eventy, ktore maju typ goal alebo ENDGAME (asi).
//AK sa zmenil pocet golov, tak posli notifikaciu ze padol gol aj s novym stavom
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(GameChangeService.TAG, "Nebavi to ");
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
if (h != null)
h.removeCallbacks(r);
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Name of the channel";
String description = "Description of the channel";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
Run in Android Studio inform about errors:
https://ctrlv.cz/shots/2019/01/03/Y6RS.png
or
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.luky.nhlvysledky, PID: 23251
java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { (has extras) }
at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1519)
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1560)
at android.app.ContextImpl.startService(ContextImpl.java:1532)
at android.content.ContextWrapper.startService(ContextWrapper.java:664)
at com.example.luky.nhlvysledky.Future_matches.launchService(Future_matches.java:148)
at com.example.luky.nhlvysledky.Future_matches.takeCareOfChanges(Future_matches.java:142)
at com.example.luky.nhlvysledky.Future_matches.access$300(Future_matches.java:33)
at com.example.luky.nhlvysledky.Future_matches$1$1.onClick(Future_matches.java:93)
at com.example.luky.nhlvysledky.RecycleView.FutureMatchesHolder$1.onClick(FutureMatchesHolder.java:46)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
You need to explicitly define which service you are starting in your intent.
getActivity().startService(new Intent(getActivity(), GameChangeService.class).putExtra(Tools.INTENT_EXTRA_ID,id));
You will also need to define your service in your AndroidManifest.xml.
<service android:enabled="true" android:name=".GameChangeService" />

Android app crash on Bluetooth LE write

I am developing an Android app to control stepper motors via a Android Due and a Bluetooth HM-10 BLE module.
So far everything works, but there seems to be a problem on some devices, which cause the app to crash. On my Nexus 5 and 7 it is working fine, but for example on a Samsung Galaxy S5 it keeps crashing. All devices have Andoird 6.0.1, so they should be equal.
I am getting this error report from the user:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattCharacteristic.setValue(byte[])' on a null object reference
at pm.puremoco.BluetoothLeService.WriteValue(BluetoothLeService.java:70)
at pm.puremoco.frag_moviesetlinear$3.onFinish(frag_moviesetlinear.java:266)
at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:127)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
So the error is occuring, when opening, at "onCreateView". There is the command to transmit a value:
mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
Here is almost the full fragment:
public class frag_moviesetlinear extends Fragment {
public static final String methodtocall = "ooo";
private final static String TAG = DeviceControlFragment.class.getSimpleName();
public AlertDialog alertTransmitData;
public BluetoothLeService mBluetoothLeService; //TODO evtl. private
public String methodcalled = "aaa";
public String dataLineReceived;
public long countDownTimerDelay = 200;
public AlertDialog alertTimeTooShort;
NumberPicker noPick1 = null;
NumberPicker noPick2 = null;
NumberPicker noPick3 = null;
long alertTransmitDataLength = 21000;
DeviceControlFragment devConFrag;
double minTimeFactor = 0;
TextView vid_maxSpeedU;
TextView vid_maxSpeedV;
TextView vid_maxSpeedW;
TextView vid_maxSpeedX;
TextView vid_maxSpeedY;
TextView vid_maxSpeedZ;
TextView vid_maxSpeedUspline;
TextView vid_maxSpeedVspline;
TextView vid_maxSpeedWspline;
TextView vid_maxSpeedXspline;
TextView vid_maxSpeedYspline;
TextView vid_maxSpeedZspline;
TextView txt_vidDuration;
TextView txt_vidUpdateIntervall;
TextView txt_minTime;
int timeForCalculation = 0;
int calculatedSpeedU = 0;
int calculatedSpeedV = 0;
int calculatedSpeedW = 0;
int calculatedSpeedX = 0;
int calculatedSpeedY = 0;
int calculatedSpeedZ = 0;
boolean movingHome = false;
private String mDeviceAddress;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
getActivity().finish();
}
Log.e(TAG, "mBluetoothLeService is okay");
// Log.e(TAG, mDeviceAddress);
// Automatically connects to the device upon successful start-up initialization.
if (mDeviceAddress == "---") {
Toast.makeText(getActivity(), "Bluetooth-Device not selected!", Toast.LENGTH_SHORT).show();
} else {
mBluetoothLeService.connect(mDeviceAddress);
}
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private String mDeviceName;
private TextView mDataField;
private Button btn_vidSplineStart;
private Button btn_vidUpdateIntervalNeg;
private Button btn_vidUpdateIntervalPos;
private boolean mConnected = false;
// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read
// or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { //���ӳɹ�
Log.e(TAG, "Only gatt, just wait");
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { //�Ͽ�����
mConnected = false;
getActivity().invalidateOptionsMenu();
// btnSend.setEnabled(false);
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) //���Կ�ʼ�ɻ���
{
mConnected = true;
// mDataField.setText("");
// ShowDialog();
//btnSend.setEnabled(true);
Log.e(TAG, "In what we need");
getActivity().invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { //�յ�����
Log.e(TAG, "RECV DATA");
final String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
Log.e(TAG, data);
if (data != null && data.substring(0, 1).equals("#") && data.substring(data.length() - 1).equals("$")) {
// if (mDataField.length() > 500)
// mDataField.setText("");
// mDataField.append(data);
dataLineReceived = data.substring(1, data.length() - 1);
ActionHandlerDataReceived();
}
}
}
};
private static IntentFilter makeGattUpdateIntentFilter() { //ע����յ��¼�
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(BluetoothDevice.ACTION_UUID);
return intentFilter;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
final Intent intent = getActivity().getIntent();
// mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
// mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
mDeviceAddress = variables.BluetoothAddress;
mDeviceName = variables.BluetoothName;
methodcalled = intent.getStringExtra(methodtocall);
Intent gattServiceIntent = new Intent(getActivity(), BluetoothLeService.class);
Log.d(TAG, "Try to bindService=" + getActivity().bindService(gattServiceIntent, mServiceConnection, getActivity().BIND_AUTO_CREATE));
getActivity().registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#Override
public void onPause() {
super.onPause();
try {
getActivity().unregisterReceiver(mGattUpdateReceiver);
}
catch(Exception e){
}
try {
getActivity().unbindService(mServiceConnection);
}
catch(Exception e){
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "We are in destroy");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.setmovie, null);
vid_maxSpeedU = (TextView) layout.findViewById(R.id.vid_maxSpeedU);
vid_maxSpeedU.setText(String.valueOf(variables.speedU));
vid_maxSpeedV = (TextView) layout.findViewById(R.id.vid_maxSpeedV);
vid_maxSpeedV.setText(String.valueOf(variables.speedV));
vid_maxSpeedW = (TextView) layout.findViewById(R.id.vid_maxSpeedW);
vid_maxSpeedW.setText(String.valueOf(variables.speedW));
vid_maxSpeedX = (TextView) layout.findViewById(R.id.vid_maxSpeedX);
vid_maxSpeedX.setText(String.valueOf(variables.speedX));
vid_maxSpeedY = (TextView) layout.findViewById(R.id.vid_maxSpeedY);
vid_maxSpeedY.setText(String.valueOf(variables.speedY));
vid_maxSpeedZ = (TextView) layout.findViewById(R.id.vid_maxSpeedZ);
vid_maxSpeedZ.setText(String.valueOf(variables.speedZ));
double duration = 3700 * (double) variables.vidUpdateIntervall / 1000;
txt_vidUpdateIntervall = (TextView) layout.findViewById(R.id.txt_vidUpdateIntervall);
txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));
txt_vidDuration = (TextView) layout.findViewById(R.id.txt_vidDuration);
txt_vidDuration.setText(String.format("%.2f", duration) + " s");
vid_maxSpeedUspline = (TextView) layout.findViewById(R.id.vid_maxSpeedUspline);
vid_maxSpeedVspline = (TextView) layout.findViewById(R.id.vid_maxSpeedVspline);
vid_maxSpeedWspline = (TextView) layout.findViewById(R.id.vid_maxSpeedWspline);
vid_maxSpeedXspline = (TextView) layout.findViewById(R.id.vid_maxSpeedXspline);
vid_maxSpeedYspline = (TextView) layout.findViewById(R.id.vid_maxSpeedYspline);
vid_maxSpeedZspline = (TextView) layout.findViewById(R.id.vid_maxSpeedZspline);
txt_minTime = (TextView) layout.findViewById(R.id.txt_minTime);
btn_vidSplineStart = (Button) layout.findViewById(R.id.btn_vidSplineStart);
btn_vidSplineStart.setOnClickListener(new event_btn_vidSplineStart());
btn_vidUpdateIntervalPos = (Button) layout.findViewById(R.id.btn_vidUpdateIntervalPos);
btn_vidUpdateIntervalPos.setOnClickListener(new event_btn_vidUpdateIntervalPos());
btn_vidUpdateIntervalNeg = (Button) layout.findViewById(R.id.btn_vidUpdateIntervalNeg);
btn_vidUpdateIntervalNeg.setOnClickListener(new event_btn_vidUpdateIntervalNeg());
//-----start-button------
minTimeFactor = 0;
timeForCalculation = variables.vidUpdateIntervall;
new CountDownTimer(countDownTimerDelay * 1, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
}
}.start();
new CountDownTimer(countDownTimerDelay * 2, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
mBluetoothLeService.WriteValue("2000_" + String.valueOf(variables.linearWithFade) + "#");
}
}.start();
//-----start-button------
transmitDataAlert("calculation");
return layout;
}
private void ActionHandlerDataReceived() {
String variable;
String value;
String[] parts = dataLineReceived.split("_"); // escape .
variable = parts[0];
value = parts[1];
switch (variable) {
case "vidMaxSpeedU":
vid_maxSpeedUspline.setText(String.valueOf(value));
variables.vid_maxSpeedUspline = Integer.parseInt(value);
calculatedSpeedU = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedU) {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorU = Double.valueOf(value) / variables.speedU;
if (minTimeFactor < FactorU) {
minTimeFactor = FactorU;
}
break;
case "vidMaxSpeedV":
vid_maxSpeedVspline.setText(String.valueOf(value));
variables.vid_maxSpeedVspline = Integer.parseInt(value);
calculatedSpeedV = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedV) {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorV = Double.valueOf(value) / variables.speedV;
if (minTimeFactor < FactorV) {
minTimeFactor = FactorV;
}
break;
case "vidMaxSpeedW":
vid_maxSpeedWspline.setText(String.valueOf(value));
variables.vid_maxSpeedWspline = Integer.parseInt(value);
calculatedSpeedW = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedW) {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorW = Double.valueOf(value) / variables.speedW;
if (minTimeFactor < FactorW) {
minTimeFactor = FactorW;
}
break;
case "vidMaxSpeedX":
vid_maxSpeedXspline.setText(String.valueOf(value));
variables.vid_maxSpeedXspline = Integer.parseInt(value);
calculatedSpeedX = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedX) {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorX = Double.valueOf(value) / variables.speedX;
if (minTimeFactor < FactorX) {
minTimeFactor = FactorX;
}
break;
case "vidMaxSpeedY":
vid_maxSpeedYspline.setText(String.valueOf(value));
variables.vid_maxSpeedYspline = Integer.parseInt(value);
calculatedSpeedY = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedY) {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorY = Double.valueOf(value) / variables.speedY;
if (minTimeFactor < FactorY) {
minTimeFactor = FactorY;
}
break;
case "vidMaxSpeedZ":
vid_maxSpeedZspline.setText(String.valueOf(value));
variables.vid_maxSpeedZspline = Integer.parseInt(value);
calculatedSpeedZ = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedZ) {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorZ = Double.valueOf(value) / variables.speedZ;
if (minTimeFactor < FactorZ) {
minTimeFactor = FactorZ;
}
alertTransmitData.dismiss();
double vidMin = Math.ceil(minTimeFactor * timeForCalculation);
variables.vidMinIntervall = (int) vidMin;
//txt_minTime.setText(String.valueOf(variables.vidMinIntervall));
double duration = (3700 * (double) variables.vidMinIntervall) / 1000;
txt_minTime.setText(String.format("%.2f", duration) + " s");
if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
btn_vidSplineStart.setEnabled(true);
}
break;
case "movieFinished":
btn_vidSplineStart.setText("Move home");
btn_vidSplineStart.setEnabled(true);
movingHome = true;
alertTransmitData.dismiss();
break;
case "movieHome":
btn_vidSplineStart.setText("Start");
btn_vidSplineStart.setEnabled(true);
alertTransmitData.dismiss();
break;
}
}
void calculateNewSpeeds() {
//--------------U-Axis-----------------
if (variables.vid_maxSpeedUspline != 0) {
variables.vid_maxSpeedUspline = (timeForCalculation * calculatedSpeedU) / variables.vidUpdateIntervall;
vid_maxSpeedUspline.setText(String.valueOf(variables.vid_maxSpeedUspline));
if (variables.vid_maxSpeedUspline > variables.speedU) {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------V-Axis-----------------
if (variables.vid_maxSpeedVspline != 0) {
variables.vid_maxSpeedVspline = (timeForCalculation * calculatedSpeedV) / variables.vidUpdateIntervall;
vid_maxSpeedVspline.setText(String.valueOf(variables.vid_maxSpeedVspline));
if (variables.vid_maxSpeedVspline > variables.speedV) {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------W-Axis-----------------
if (variables.vid_maxSpeedWspline != 0) {
variables.vid_maxSpeedWspline = (timeForCalculation * calculatedSpeedW) / variables.vidUpdateIntervall;
vid_maxSpeedWspline.setText(String.valueOf(variables.vid_maxSpeedWspline));
if (variables.vid_maxSpeedWspline > variables.speedW) {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------X-Axis-----------------
if (variables.vid_maxSpeedXspline != 0) {
variables.vid_maxSpeedXspline = (timeForCalculation * calculatedSpeedX) / variables.vidUpdateIntervall;
vid_maxSpeedXspline.setText(String.valueOf(variables.vid_maxSpeedXspline));
if (variables.vid_maxSpeedXspline > variables.speedX) {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------Y-Axis-----------------
if (variables.vid_maxSpeedYspline != 0) {
variables.vid_maxSpeedYspline = (timeForCalculation * calculatedSpeedY) / variables.vidUpdateIntervall;
vid_maxSpeedYspline.setText(String.valueOf(variables.vid_maxSpeedYspline));
if (variables.vid_maxSpeedYspline > variables.speedY) {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------Z-Axis-----------------
if (variables.vid_maxSpeedZspline != 0) {
variables.vid_maxSpeedZspline = (timeForCalculation * calculatedSpeedZ) / variables.vidUpdateIntervall;
vid_maxSpeedZspline.setText(String.valueOf(variables.vid_maxSpeedZspline));
if (variables.vid_maxSpeedZspline > variables.speedZ) {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
}
public void alert_TimeTooShort(int errorCase, int movieLengthSecondsNEW) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
getActivity());
// set title
alertDialogBuilder.setTitle("Error");
String errorMessage = "error";
// set dialog message
alertDialogBuilder
.setMessage(errorMessage)
.setCancelable(false);
alertDialogBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
}
});
// create alert dialog
alertTimeTooShort = alertDialogBuilder.create();
// show it
alertTimeTooShort.show();
}
public void transmitDataAlert(String type) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View promptView = layoutInflater.inflate(R.layout.alert_transmitdata, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setView(promptView);
final ProgressBar progressbar = (ProgressBar) promptView.findViewById(R.id.progressBar_transmitData);
final TextView txt_PleaseWait = (TextView) promptView.findViewById(R.id.txt_PleaseWait);
final TextView txt_timeRemainVideo = (TextView) promptView.findViewById(R.id.txt_timeRemainVideo);
final TextView txt_timeRemainVideoTXT = (TextView) promptView.findViewById(R.id.txt_timeRemainVideoTXT);
new CountDownTimer(alertTransmitDataLength, 1) {
public void onTick(long millisUntilFinished) {
int longtointRemain = (int) millisUntilFinished;
int longtointFull = (int) alertTransmitDataLength;
int percentprogress = 100 - ((100 * longtointRemain) / longtointFull);
progressbar.setProgress(percentprogress);
float duration = (float) millisUntilFinished/1000;
txt_timeRemainVideo.setText(String.format("%.1f", duration) + " s");
}
public void onFinish() {
}
}.start();
}
alertDialogBuilder.setCancelable(false);
alertTransmitData = alertDialogBuilder.create();
alertTransmitData.show();
}
class event_btn_vidSplineStart implements View.OnClickListener {
#Override
public void onClick(View v) {
btn_vidSplineStart.setEnabled(false);
btn_vidSplineStart.setText("Moving...");
new CountDownTimer(countDownTimerDelay * 1, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//MotionMode
mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
}
}.start();
new CountDownTimer(countDownTimerDelay * 2, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//MotionMode
mBluetoothLeService.WriteValue("1110_0#");
}
}.start();
alertTransmitDataLength = (long) variables.vidUpdateIntervall*3700;
if(movingHome==true){
transmitDataAlert("moveHome");
movingHome=false;
}
else {
transmitDataAlert("videomove");
}
}
}
class event_btn_vidUpdateIntervalPos implements View.OnClickListener {
#Override
public void onClick(View v) {
variables.vidUpdateIntervall++;
double duration = (3700 * (double) variables.vidUpdateIntervall) / 1000;
txt_vidDuration.setText(String.format("%.2f", duration) + " s");
txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));
calculateNewSpeeds();
if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
btn_vidSplineStart.setEnabled(true);
}
else{
btn_vidSplineStart.setEnabled(false);
}
}
}
class event_btn_vidUpdateIntervalNeg implements View.OnClickListener {
#Override
public void onClick(View v) {
if (variables.vidUpdateIntervall > 1) {
variables.vidUpdateIntervall--;
}
double duration = (3700 * (double) variables.vidUpdateIntervall) / 1000;
txt_vidDuration.setText(String.format("%.2f", duration) + " s");
txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));
calculateNewSpeeds();
if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
btn_vidSplineStart.setEnabled(true);
}
else{
btn_vidSplineStart.setEnabled(false);
}
}
}
}
And here is the full BluetoothLeService, which I got from the website of the HM-10 Bluetooth manufacturer:
import android.app.Service;
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.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import java.util.List;
import java.util.UUID;
/**
* Service for managing connection and data communication with a GATT server hosted on a
* given Bluetooth LE device.
*/
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
public final static UUID UUID_NOTIFY =
UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb");
public final static UUID UUID_SERVICE =
UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb");
public BluetoothGattCharacteristic mNotifyCharacteristic;
public void WriteValue(String strValue)
{
mNotifyCharacteristic.setValue(strValue.getBytes());
mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic);
}
public void findService(List<BluetoothGattService> gattServices)
{
Log.i(TAG, "Count is:" + gattServices.size());
for (BluetoothGattService gattService : gattServices)
{
Log.i(TAG, gattService.getUuid().toString());
Log.i(TAG, UUID_SERVICE.toString());
if(gattService.getUuid().toString().equalsIgnoreCase(UUID_SERVICE.toString()))
{
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
Log.i(TAG, "Count is:" + gattCharacteristics.size());
for (BluetoothGattCharacteristic gattCharacteristic :
gattCharacteristics)
{
if(gattCharacteristic.getUuid().toString().equalsIgnoreCase(UUID_NOTIFY.toString()))
{
Log.i(TAG, gattCharacteristic.getUuid().toString());
Log.i(TAG, UUID_NOTIFY.toString());
mNotifyCharacteristic = gattCharacteristic;
setCharacteristicNotification(gattCharacteristic, true);
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
return;
}
}
}
}
}
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
Log.i(TAG, "oldStatus=" + status + " NewStates=" + newState);
if(status == BluetoothGatt.GATT_SUCCESS)
{
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mBluetoothGatt.close();
mBluetoothGatt = null;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.w(TAG, "onServicesDiscovered received: " + status);
findService(gatt.getServices());
} else {
if(mBluetoothGatt.getDevice().getUuids() == null)
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
Log.e(TAG, "OnCharacteristicWrite");
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status)
{
Log.e(TAG, "OnCharacteristicWrite");
}
#Override
public void onDescriptorRead(BluetoothGatt gatt,
BluetoothGattDescriptor bd,
int status) {
Log.e(TAG, "onDescriptorRead");
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor bd,
int status) {
Log.e(TAG, "onDescriptorWrite");
}
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int a, int b)
{
Log.e(TAG, "onReadRemoteRssi");
}
#Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int a)
{
Log.e(TAG, "onReliableWriteCompleted");
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile. Data parsing is
// carried out as per profile specifications:
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
//final StringBuilder stringBuilder = new StringBuilder(data.length);
//for(byte byteChar : data)
// stringBuilder.append(String.format("%02X ", byteChar));
//intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
intent.putExtra(EXTRA_DATA, new String(data));
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* #return Return true if the initialization is successful.
*/
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* #param address The device address of the destination device.
*
* #return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
/*
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
*/
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
if(mBluetoothGatt != null)
{
mBluetoothGatt.close();
mBluetoothGatt = null;
}
mBluetoothGatt = device.connectGatt(this.getApplication(), false, mGattCallback);
//mBluetoothGatt.connect();
Log.d(TAG, "Trying to create a new connection.");
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
/*
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
*/
}
/**
* Request a read on a given {#code BluetoothGattCharacteristic}. The read result is reported
* asynchronously through the {#code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
* callback.
*
* #param characteristic The characteristic to read from.
*/
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
/**
* Enables or disables notification on a give characteristic.
*
* #param characteristic Characteristic to act on.
* #param enabled If true, enable notification. False otherwise.
*/
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
/*
// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
*/
}
/**
* Retrieves a list of supported GATT services on the connected device. This should be
* invoked only after {#code BluetoothGatt#discoverServices()} completes successfully.
*
* #return A {#code List} of supported services.
*/
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null;
return mBluetoothGatt.getServices();
}
}

Categories

Resources