Как определить, сопряжено ли устройство Android с часами Android Wear

Я создаю приложение для Android, которое расширяет push-уведомления. Мое приложение загружает с сервера примерно 10 изображений, когда приходит push-уведомление, и отображает эти дополнительные изображения на часах. Эти изображения относятся к приложению Android Wear и не отображаются на портативном устройстве.

Как узнать, сопряжено ли портативное устройство с устройством износа Android, чтобы я мог определить, нужно ли загружать дополнительные изображения, необходимые для приложения износа?

Спасибо!


person TWilly    schedule 22.07.2014    source источник
comment
Я просто проверял, установлен ли Android Wear, а затем загружал эти ресурсы. Если Android Wear установлен, но часы не сопряжены, есть большая вероятность, что они будут сопряжены в будущем.   -  person 323go    schedule 22.07.2014
comment
@ 323go Как узнать установлен android wear или нет?   -  person TWilly    schedule 12.08.2014
comment
Через PackageManager, как и все другие приложения.   -  person 323go    schedule 12.08.2014
comment
Вот полный пример того, как это проверить: stackoverflow.com/a/39513489/878126   -  person android developer    schedule 16.09.2016


Ответы (5)


Вам необходимо использовать NodeApi, в частности _ 2_.

Например (из фонового потока - иначе используйте setResultCallback(), а не await()):

List<Node> connectedNodes =
    Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await().getNodes();

Если список возвращаемых узлов содержит хотя бы один элемент, значит, имеется подключенное устройство Android Wear, в противном случае его нет.


Обновление: с выпуском Google Play Services 7.3, добавлена ​​поддержка нескольких одновременно подключенных устройств Android Wear. Вы можете использовать CapabilityApi для запроса узлов с конкретные возможности.

person matiash    schedule 22.07.2014
comment
В настоящее время будет ли когда-либо более одного узла? - person Nathan Schwermann; 25.07.2014
comment
@schwiz Я не уверен, я думаю, если бы вы могли соединить более одного устройства, тогда было бы несколько узлов (?) Однако я не тестировал это, так как у меня только один. :) - person matiash; 25.07.2014
comment
В настоящее время вы не можете подключить более одного устройства. Я узнал об этом, когда заменил плохо спроектированный Gear Live на часы G Watch. - person 323go; 12.08.2014
comment
Google Glass считается узлом, поэтому вы можете одновременно подключить устройство Wear и Glass. - person Jarett Millard; 20.10.2014
comment
getConnectedNodes обнаруживает подключенные узлы, а не спаренные узлы, не так ли? - person Christine; 05.05.2015
comment
@matiash Спасибо, что указали на NodeApi и CapabilityApi. NodeApi работает отлично, но у меня проблемы с CapabilityApi. Я открыл отдельный вопрос и был бы очень признателен за любую помощь: stackoverflow.com/q/31328971/1204377 - person Anton Cherkashyn; 10.07.2015

Здесь уже было 2 варианта. Оба они действительны в зависимости от вашего варианта использования. Я хотел бы добавить третий вариант, хотя и неполный.

Вариант 1: найти подключенные узлы с помощью NodeApi

Класс NodeApi имеет метод для получения подключенных узлов. При этом вы уверены, что у пользователя не было часов в прошлом или когда-то они были протестированы. У него действительно есть часы поблизости и он подключен.

Недостатком этого подхода является то, что вы не получите результатов, если bluetooth не включен или часы не подключены в данный момент.

Метод такой:

List<Node> connectedNodes =
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await().getNodes();

Более полный пример кода выглядит так:

private GoogleApiClient client;
private static final long CONNECTION_TIME_OUT_MS = 1000;

public void checkIfWearableConnected() {

    retrieveDeviceNode(new Callback() {
        @Override
        public void success(String nodeId) {
            Toast.makeText(this, "There was at least one wearable found", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void failed(String message) {
            Toast.makeText(this, "There are no wearables found", Toast.LENGTH_SHORT).show();
        }
    });

}

private GoogleApiClient getGoogleApiClient(Context context) {
        if (client == null)
            client = new GoogleApiClient.Builder(context)
                    .addApi(Wearable.API)
                    .build();
        return client;
    }

private interface Callback {
        public void success(final String nodeId);
        public void failed(final String message);
    }

private void retrieveDeviceNode(final Callback callback) {
        final GoogleApiClient client = getGoogleApiClient(this);
        new Thread(new Runnable() {

            @Override
            public void run() {
                client.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
                NodeApi.GetConnectedNodesResult result =
                        Wearable.NodeApi.getConnectedNodes(client).await();
                List<Node> nodes = result.getNodes();
                if (nodes.size() > 0) {
                    String nodeId = nodes.get(0).getId();
                    callback.success(nodeId);
                } else {
                    callback.failed("no wearables found");
                }
                client.disconnect();
            }
        }).start();
    }

Вариант 2. Проверьте приложение Android Wear

И в этом преимущество второго варианта. Если у вас есть часы, первое, что вам нужно сделать, чтобы подключить их, - это установить приложение Android Wear на свой КПК. Таким образом, вы можете использовать PackageManager, чтобы проверить, установлено ли это приложение Android Wear.

Недостатком является то, что вы можете установить приложение Wear без часов.

Пример кода:

try {
    getPackageManager().getPackageInfo("com.google.android.wearable.app", PackageManager.GET_META_DATA);

    Toast.makeText(this, "The Android Wear App is installed", Toast.LENGTH_SHORT).show();
} catch (PackageManager.NameNotFoundException e) {
    //android wear app is not installed
    Toast.makeText(this, "The Android Wear App is NOT installed", Toast.LENGTH_SHORT).show();
}

Вариант 3. Проверьте сопряженные устройства

Не уверен, возможно ли это, но в некоторых случаях это было бы идеальным решением, поскольку вы можете проверить, что у пользователя есть часы, сопряженные с его устройством, хотя в то время его не нужно подключать.

Ниже приведен пример кода, однако он не включает проверку того, являются ли сопряженные устройства носимыми или нет. Это только отправная точка.

Пример кода из: getbondeddevices () не возвращает сопряженные устройства Bluetooth

BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();

Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
     Toast.makeText(this, "At least one paired bluetooth device found", Toast.LENGTH_SHORT).show();
    // TODO at this point you'd have to iterate these devices and check if any of them is a wearable (HOW?)
    for (BluetoothDevice device : pairedDevices) {
        Log.d("YOUR_TAG", "Paired device: "+ device.getName() + ", with address: " + device.getAddress());
    }
} else {
    Toast.makeText(this, "No paired bluetooth devices found", Toast.LENGTH_SHORT).show();
}

Обратите внимание, что для этого кода требуются разрешения Bluetooth в вашем манифесте.

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
person hcpl    schedule 23.01.2015
comment
Вариант 4: Спросите у Google, что они сделали это так сложно обнаружить? - person worked; 30.03.2015
comment
Думаю, вариант 3 - это то, что искала TWilly. Так что это должен быть принятый ответ. - person Christine; 06.05.2015
comment
Недостатком этого подхода является то, что вы не получите результатов, если bluetooth не включен или часы не подключены в данный момент. - Почему это недостаток? Разве это не то, что вам действительно нужно? Чтобы проверить, действительно ли умные часы подключены? В каком случае это неправильно использовать? - person android developer; 18.09.2016
comment
@androiddeveloper правда, это действительно зависит от вашего варианта использования - person hcpl; 23.09.2016
comment
Вариант 2: проверьте приложение Android Wear. Не учитываются устройства Samsung Gear, использующие com.samsung.android.app.watchmanager. - person Niels; 25.02.2019

Прежде всего, все ответы верны, если карманное устройство подключено только к Android Watch. Что делать, если портативное устройство подключено к нескольким устройствам (многопользовательским), таким как Android Watch, HealthBand, Beacon и т. Д., Тогда приведенные выше ответы могут не работать.

В следующих разделах показано, как рекламировать узлы устройств, которые могут обрабатывать запросы активности, обнаруживать узлы, способные удовлетворить запрошенную потребность, и отправлять сообщения этим узлам.

Рекламируйте возможности

Чтобы запустить действие на портативном устройстве с носимого устройства, используйте класс MessageApi для отправки запроса. Поскольку к портативному устройству может быть подключено несколько носимых устройств, носимое приложение должно определять, может ли подключенный узел запускать действие. В своем портативном приложении объявите, что узел, на котором оно работает, предоставляет определенные возможности.

Чтобы рекламировать возможности своего портативного приложения:

  1. Создайте файл конфигурации XML в каталоге res / values ​​/ вашего проекта и назовите его wear.xml.
  2. Добавьте ресурс с именем android_wear_capabilities в wear.xml.
  3. Определите возможности, которые предоставляет устройство.

<resources>
    <string-array name="android_wear_capabilities">
        <item>android_wear</item>
    </string-array> 
</resources>

Получите узлы с необходимыми возможностями

Первоначально вы можете определить соответствующие узлы, вызвав метод CapabilityApi.getCapability (). В следующем примере показано, как вручную получить результаты доступных узлов с помощью возможности android_wear. Используйте следующий код в модуле износа:

public abstract class BaseActivity extends Activity implements MessageApi.MessageListener, NodeApi.NodeListener,
    DataApi.DataListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

private static final String
        SMART_WEAR_CAPABILITY_NAME = "android_wear";

protected GoogleApiClient mGoogleApiClient;
protected ArrayList<String> results;
private String TAG = "BaseActivity::Wear";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
}

private Collection<String> getNodes() {
    results = new ArrayList<>();
    NodeApi.GetConnectedNodesResult nodes =
            Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();

    for (Node node : nodes.getNodes()) {
        Log.d(TAG, node.getId());
        results.add(node.getId());
    }

    return results;
}

@Override
protected void onResume() {
    super.onResume();
    mGoogleApiClient.connect();
}

@Override
protected void onPause() {
    super.onPause();
    Wearable.MessageApi.removeListener(mGoogleApiClient, this);
    Wearable.NodeApi.removeListener(mGoogleApiClient, this);
    Wearable.DataApi.removeListener(mGoogleApiClient, this);
    mGoogleApiClient.disconnect();
}

@Override
public void onConnected(Bundle bundle) {
    Log.d(TAG, "onConnected(): Successfully connected to Google API client");
    Wearable.MessageApi.addListener(mGoogleApiClient, this);
    Wearable.DataApi.addListener(mGoogleApiClient, this);
    Wearable.NodeApi.addListener(mGoogleApiClient, this);
    results = new ArrayList<>();

    getNodeIdOfHandheldDevice();
}

@Override
public void onConnectionSuspended(int i) {
    Log.d(TAG, "onConnectionSuspended(): Connection to Google API client was suspended");
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Log.e(TAG, "onConnectionFailed(): Failed to connect, with result: " + connectionResult);
}

@Override
public void onPeerConnected(Node node) {
    Log.e(TAG, "onPeerConnected():");
}

@Override
public void onPeerDisconnected(Node node) {
    Log.e(TAG, "onPeerDisconnected():");
}

private void getNodeIdOfHandheldDevice() {
    Wearable.CapabilityApi.getCapability(
            mGoogleApiClient, SMART_WEAR_CAPABILITY_NAME,
            CapabilityApi.FILTER_REACHABLE).setResultCallback(
            new ResultCallback<CapabilityApi.GetCapabilityResult>() {
                @Override
                public void onResult(CapabilityApi.GetCapabilityResult result) {
                    if (result.getStatus().isSuccess()) {
                        updateFindMeCapability(result.getCapability());
                    } else {
                        Log.e(TAG,
                                "setOrUpdateNotification() Failed to get capabilities, "
                                        + "status: "
                                        + result.getStatus().getStatusMessage());
                    }
                }
            });
}

private void updateFindMeCapability(CapabilityInfo capabilityInfo) {
    Set<Node> connectedNodes = capabilityInfo.getNodes();
    if (connectedNodes.isEmpty()) {
        results.clear();
    } else {
        for (Node node : connectedNodes) {
            // we are only considering those nodes that are directly connected
            if (node.isNearby()) {
                results.add(node.getId());
            }
        }
    }
}

}

Для получения дополнительных сведений см. Android Dev.

person Umang Kothari    schedule 03.08.2015
comment
Я пытался это сделать, но кое-что я не понимаю: когда я вызываю метод getCapability (), я всегда получаю результат, даже если я изменяю имя возможности. Разве я не должен ничего обнаруживать, если имя неправильное? - person krakig; 22.10.2015
comment
Если у вашего телефона только одно соединение (скажем, Watch), тогда возможность работает нормально, но если у него более двух соединений (Watch + Health band + Beacons), тогда система проверит подходящее имя, и вы получите этот узел. Пожалуйста, проверьте developer.android.com/training/wearables/data-layer/ - person Umang Kothari; 23.10.2015
comment
Это должно было быть отмечено как правильный ответ, так как это фактически проверяет, изношен ли подключенный узел, стекло или проблесковый маячок. - person Milan; 10.01.2016

Я использую гораздо более простой метод, который подходит для моего случая использования, проверьте, установлено ли приложение для Android Wear:

    try {
        getPackageManager().getPackageInfo("com.google.android.wearable.app", PackageManager.GET_META_DATA);
    } catch (PackageManager.NameNotFoundException e) {
        //android wear app is not installed
    }
person Oded Breiner    schedule 28.11.2014
comment
Это на самом деле более полезно, чем использование bluetoothmanager, и избавляет вас от необходимости использовать Bluetooth. - person Christine; 06.05.2015
comment
Простая проверка, установлено ли другое приложение, не означает, что они связаны с носимым устройством. Проверка подключенных узлов (в приведенных выше примерах) и долгий путь проверки сопряженных устройств bluetooth - единственный способ быть абсолютно уверенным. - person Nlinscott; 28.05.2015
comment
@Nlinscott - как уже отмечалось, у меня гораздо более простой метод, который подходит для конкретного случая использования. Новый ответ, который был добавлен, который включает мое решение, и за который проголосовали 6 раз во время этого комментария, является еще одним доказательством. - person Oded Breiner; 29.05.2015
comment
Он также не отвечает на вопрос ОП. Я уверен, что в некоторых случаях это работает, но не помогает другим, которые ищут решение этой проблемы. - person Nlinscott; 29.05.2015

Проверить сопряженные устройства

Вы можете проверить, что у пользователя есть часы, сопряженные с его устройством, хотя в данный момент его не нужно подключать. Это лучше, так как таким образом часы не нужно подключать во время обнаружения.

BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();

Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
    for (BluetoothDevice device : pairedDevices) {
        if(device.getDeviceClass()==BluetoothClass.Device.WEARABLE_WRIST_WATCH){
            Log.d("Found", "Paired wearable: "+ device.getName() + ", with address: " + device.getAddress());
        {
    {
} else {
    Toast.makeText(this, "No paired wearables found", Toast.LENGTH_SHORT).show();
}

Обратите внимание, что для этого кода требуются разрешения Bluetooth в вашем манифесте.

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
person Alan Zhu - Alpha Zeta    schedule 27.07.2015