Освой программирование играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Sphero - интерактивная игрушка, управляемая с телефона.
Статья устарела. Я баловался игрушкой в 2015 году. Там многое поменялось, да и сами производители забросили развитие библиотеки.
На сайте производителя есть специальный раздел для разработчиков, в котором можно найти SDK для разных платформ. На текущий момент (май 2015) для Android используется код, написанный под Eclipse. Мне не удалось нормально подружить код с Android Studio, постоянно вылезали косяки. Также на Гитхабе имеется ветка бета-версии SDK. Я использовал бету-версию, которая у меня заработала.
Я покажу базовый пример для первого знакомства.
Сначала скачиваем файл библиотеки RobotLibrary.jar. Напоминаю, что речь идёт о бета-версии номер 3. Текущая версия 2.0 у меня не работала.
Файл библиотеки копируем в папку libs проекта и прописываем зависимость в Gradle:
compile files('libs/RobotLibrary.jar')
В манифесте пропишем разрешения для работы с Bluetooth:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
В макет экрана активности добавим три кнопки. Две из них будут менять цвет, а третья будет двигать шарик.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/entire_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Button
android:id="@+id/buttonGreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:onClick="onClick"
android:text="Green" />
<Button
android:id="@+id/buttonBlue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/buttonGreen"
android:layout_below="@+id/buttonGreen"
android:layout_marginTop="57dp"
android:onClick="onClick"
android:text="Blue" />
<Button
android:id="@+id/buttonMove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:onClick="onClick"
android:text="Move" />
</RelativeLayout>
Осталось написать код. Код состоит из двух частей. Первая часть - обнаружить устройство и спариться с ним. Вторая часть - отдавать команды. У разработчика есть два типа роботов - Sphero и Ollie, которые можно использовать в одной программе. Но они имеют разных набор команд и методов. Поэтому, если вы пишите универсальную программу, то нужно отдельно определить каждого робота и работать с нужным типом. Я убрал все проверки if, которые попадались в документации.
package ru.alexanderklimov.sphero;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.orbotix.ConvenienceRobot;
import com.orbotix.Sphero;
import com.orbotix.classic.DiscoveryAgentClassic;
import com.orbotix.classic.RobotClassic;
import com.orbotix.common.DiscoveryAgent;
import com.orbotix.common.DiscoveryAgentEventListener;
import com.orbotix.common.DiscoveryException;
import com.orbotix.common.Robot;
import com.orbotix.common.RobotChangedStateListener;
import java.util.List;
public class MainActivity extends ActionBarActivity implements
DiscoveryAgentEventListener,
RobotChangedStateListener{
private static final String TAG = "Sphero";
private DiscoveryAgent mCurrentDiscoveryAgent;
private ConvenienceRobot mRobot;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
mCurrentDiscoveryAgent = DiscoveryAgentClassic.getInstance();
mCurrentDiscoveryAgent.addRobotStateListener(this);
startDiscovery();
}
@Override
public void onStop() {
super.onStop();
mRobot.disconnect();
}
/**
* Invoked when the discovery agent finds a new available robot, or updates and already available robot
* @param robots The list of all robots, connected or not, known to the discovery agent currently
*/
@Override
public void handleRobotsAvailable(List<Robot> robots) {
// Here we need to know which version of the discovery agent we are using, if we are to use Sphero, we need to
// treat Spheros a little bit differently.
if (mCurrentDiscoveryAgent instanceof DiscoveryAgentClassic) {
// If we are using the classic discovery agent, and therefore using Sphero, we'll just connect to the first
// one available that we get. Note that "available" in classic means paired to the phone and turned on.
mCurrentDiscoveryAgent.connect(robots.get(0));
}
}
@Override
public void changedState(Robot robot, RobotChangedStateNotificationType type) {
switch (type) {
case Connecting:
Log.i(TAG, "Connecting");
break;
case FailedConnect:
Log.i(TAG, "FailedConnect");
break;
case Online:
// Bluetooth Classic (Sphero)
Log.i(TAG, "Online");
if (robot instanceof RobotClassic) {
mRobot = new Sphero(robot);
mRobot.setLed(0f, 0f, 1f);
}
break;
case Disconnected:
Log.i(TAG, "Disconnecting");
break;
}
}
/**
* Starts discovery on the set discovery agent and look for robots
*/
private void startDiscovery() {
try {
// You first need to set up so that the discovery agent will notify you when it finds robots.
// To do this, you need to implement the DiscoveryAgentEventListener interface (or declare
// it anonymously) and then register it on the discovery agent with DiscoveryAgent#addDiscoveryListener()
mCurrentDiscoveryAgent.addDiscoveryListener(this);
// Second, you need to make sure that you are notified when a robot changes state. To do this,
// implement RobotChangedStateListener (or declare it anonymously) and use
// DiscoveryAgent#addRobotStateListener()
mCurrentDiscoveryAgent.addRobotStateListener(this);
// Then to start looking for a Sphero, you use DiscoveryAgent#startDiscovery()
// You do need to handle the discovery exception. This can occur in cases where the user has
// Bluetooth off, or when the discovery cannot be started for some other reason.
mCurrentDiscoveryAgent.startDiscovery(this);
} catch (DiscoveryException e) {
Log.e(TAG, "Could not start discovery. Reason: " + e.getMessage());
e.printStackTrace();
}
}
public void onClick(View view) {
switch (view.getId()){
case R.id.buttonBlue:
mRobot.setLed(0f, 0f, 1f);
break;
case R.id.buttonGreen:
mRobot.setLed(0f, 1f, 0f);
break;
case R.id.buttonMove:
mRobot.drive((float) 5, (float) 5);
break;
}
}
}
Два слушателя DiscoveryAgentEventListener и RobotChangedStateListener помогают обнаружить и управлять шариком. За обнаружение отвечает класс DiscoveryAgent, который связан с Bluetooth. После успешного обнаружения в методе changedState() срабатывает тип Online, в котором мы можем посветить шарик нужным цветом, чтобы стало понятно, что мы соединились с шариком и можем отдавать ему команды.
По щелчку кнопок мы меняем цвета с синего на зелёный, используя формат RGB. Есть и другие методы управления цветом.
Третья кнопка заставляет шарик двигаться при помощи метода drive().
Остальные возможности изучайте самостоятельно.