New version of android-sample appication. Added AR.Drone settings configuration to android. Improved d main UI
@@ -4,46 +4,42 @@
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||
<uses-permission android:name="android.permission.DUMP" />
|
||||
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
|
||||
<uses-permission android:name="android.permission.REORDER_TASKS" />
|
||||
<uses-permission android:name="android.permission.SET_ALWAYS_FINISH" />
|
||||
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
|
||||
<uses-permission android:name="android.permission.SET_DEBUG_APP" />
|
||||
<uses-permission android:name="android.permission.SET_PROCESS_LIMIT" />
|
||||
<uses-permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<uses-feature android:name="android.hardware.usb.host" />
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="12"
|
||||
android:minSdkVersion="8"
|
||||
android:targetSdkVersion="12" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:icon="@drawable/ardron_icon"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/title_activity_main" >
|
||||
android:label="@string/title_activity_main"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ConfigurationActivity"
|
||||
android:label="@string/title_activity_settings"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".SettingsPrefs"
|
||||
android:label="@string/title_settings"
|
||||
android:theme="@android:style/Theme.Black">
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -76,13 +76,19 @@ limitations under the License.
|
||||
<dependency>
|
||||
<groupId>com.google.android</groupId>
|
||||
<artifactId>android</artifactId>
|
||||
<version>4.0.1.2</version>
|
||||
<version>4.1.1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.codeminders</groupId>
|
||||
<artifactId>javadrone-api</artifactId>
|
||||
<version>${currentVersion}</version>
|
||||
<groupId>com.google.android</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>4.1.1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.codeminders</groupId>
|
||||
<artifactId>javadrone-api</artifactId>
|
||||
<version>${currentVersion}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
|
Depois Largura: | Altura: | Tamanho: 7.8 KiB |
|
Depois Largura: | Altura: | Tamanho: 18 KiB |
|
Antes Largura: | Altura: | Tamanho: 2.9 KiB |
|
Depois Largura: | Altura: | Tamanho: 7.8 KiB |
|
Depois Largura: | Altura: | Tamanho: 7.8 KiB |
|
Depois Largura: | Altura: | Tamanho: 18 KiB |
|
Antes Largura: | Altura: | Tamanho: 1.9 KiB |
|
Depois Largura: | Altura: | Tamanho: 7.8 KiB |
|
Antes Largura: | Altura: | Tamanho: 3.9 KiB |
@@ -1,72 +1,104 @@
|
||||
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/ps3"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/display"
|
||||
android:layout_width="249dp"
|
||||
android:layout_height="206dp"
|
||||
android:layout_x="37dp"
|
||||
android:layout_y="46dp"
|
||||
android:src="@drawable/ic_action_search" />
|
||||
<TableLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
android:layout_width="172dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="70dp"
|
||||
android:layout_y="5dp"
|
||||
android:text="AR.Drone Connection State:"
|
||||
android:textStyle="bold" />
|
||||
<TextView
|
||||
android:id="@+id/state_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="10dp"
|
||||
android:text="@string/drone_state"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="118dp"
|
||||
android:layout_y="22dp"
|
||||
android:text="DISCONNECTED"
|
||||
android:textColor="#FF0000"
|
||||
android:textStyle="bold" />
|
||||
<TextView
|
||||
android:id="@+id/state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/default_state"
|
||||
android:textColor="#FF0000"
|
||||
android:textStyle="bold" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/usb_joystick_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="10dp"
|
||||
android:text="@string/usb_joystick_state"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/joystick_state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/default_state"
|
||||
android:textColor="#FF0000"
|
||||
android:textStyle="bold" />
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="top"
|
||||
android:layout_weight=".8"
|
||||
android:paddingBottom="5dp" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/display"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/display_desc"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ardrone_front" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/land"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/takeOffOrland"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="22dp"
|
||||
android:layout_y="301dp"
|
||||
android:clickable="false"
|
||||
android:text="Land"
|
||||
android:text="@string/btn_take_off"
|
||||
android:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/takeOff"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="234dp"
|
||||
android:layout_y="301dp"
|
||||
android:clickable="false"
|
||||
android:longClickable="false"
|
||||
android:text="TakeOff"
|
||||
android:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/connect"
|
||||
style="?android:attr/buttonStyleSmall"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="25dp"
|
||||
android:layout_y="250dp"
|
||||
android:text="Connect" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/ps3Button"
|
||||
android:layout_width="116dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="128dp"
|
||||
android:layout_y="251dp"
|
||||
android:text="Connect PS3" />
|
||||
|
||||
</AbsoluteLayout>
|
||||
android:baselineAligned="false"
|
||||
android:gravity="bottom"
|
||||
android:weightSum="1.0">
|
||||
|
||||
<Button
|
||||
android:id="@+id/connect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight=".5"
|
||||
android:text="@string/btn_connect" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/ps3Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight=".5"
|
||||
android:text="@string/btn_connect_ps3" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/widget_frame"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<TextView android:id="@android:id/title"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="22dp"
|
||||
android:typeface="sans"
|
||||
android:textStyle="normal"
|
||||
android:textColor="#ffffff"/>
|
||||
|
||||
<TextView android:id="@+id/seekBarPrefUnitsRight"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView android:id="@+id/seekBarPrefValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@id/seekBarPrefUnitsRight"
|
||||
android:layout_below="@android:id/title"
|
||||
android:gravity="right"/>
|
||||
|
||||
<TextView android:id="@+id/seekBarPrefUnitsLeft"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_toLeftOf="@id/seekBarPrefValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView android:id="@android:id/summary"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@id/seekBarPrefUnitsLeft"
|
||||
android:layout_below="@android:id/title"/>
|
||||
|
||||
<LinearLayout android:id="@+id/seekBarPrefBarContainer"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/summary"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -2,4 +2,7 @@
|
||||
<item android:id="@+id/menu_settings"
|
||||
android:title="@string/menu_settings"
|
||||
android:orderInCategory="100" />
|
||||
<item android:id="@+id/menu_exit"
|
||||
android:title="@string/str_exit"
|
||||
android:orderInCategory="101" />
|
||||
</menu>
|
||||
|
||||
@@ -3,6 +3,32 @@
|
||||
<string name="app_name">ControlTower</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
<string name="title_activity_main">ControlTower</string>
|
||||
<string name="title_activity_settings">Settings</string>
|
||||
<string name="str_exit">Exit</string>
|
||||
|
||||
|
||||
<string name="drone_state">AR.Drone State:</string>
|
||||
<string name="default_state">DISCONNECTED</string>
|
||||
<string name="display_desc">AR.Drone Camera signal</string>
|
||||
<string name="btn_land">Land</string>
|
||||
<string name="btn_take_off">TakeOff</string>
|
||||
<string name="btn_connect">Connect</string>
|
||||
<string name="btn_connect_ps3">Connect PS3</string>
|
||||
<string name="usb_joystick_state">USB PS3 controller State:</string>
|
||||
<string name="max_altitude">Altitude</string>
|
||||
<string name="max_angle">Angle</string>
|
||||
<string name="vertical_speed">Vertical Speed</string>
|
||||
<string name="rotation_speed">Rotation Speed</string>
|
||||
<string name="controller_deadzone">Controller Deadzone</string>
|
||||
<string name="max_altitude_desc">Maximum drone altitude in meters</string>
|
||||
<string name="max_angle_desc">Maximum bending angle for the drone in degrees</string>
|
||||
<string name="vertical_speed_desc">Maximum vertical speed, in milimeters per second</string>
|
||||
<string name="rotation_speed_desc">Maximum yaw speed, in degrees per second.</string>
|
||||
<string name="controller_deadzone_desc">Minimum controller axis position change that will impact on drone, in percents</string>
|
||||
<string name="btn_cancel">Cancel</string>
|
||||
<string name="btn_save">Save</string>
|
||||
<string name="configuration">Configuration</string>
|
||||
<string name="title_settings">Settings</string>
|
||||
<string name="controller_configuration">USB Controller</string>
|
||||
<string name="ardrone_configuration">AR.Drone</string>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:javadron="http://code.google.com/p/javadrone">
|
||||
|
||||
<PreferenceCategory android:title="@string/ardrone_configuration">
|
||||
<com.codeminders.ardrone.preferences.SeekBarPreference
|
||||
android:key="pref_altitude_max"
|
||||
android:title="@string/max_altitude"
|
||||
android:summary="@string/max_altitude_desc"
|
||||
android:defaultValue="1.5"
|
||||
android:max="1"
|
||||
android:persistent="true"
|
||||
javadron:max="10.0"
|
||||
javadron:min="0.0"
|
||||
javadron:interval="0.05"
|
||||
javadron:unitsLeft=""
|
||||
javadron:unitsRight="m"/>
|
||||
<com.codeminders.ardrone.preferences.SeekBarPreference
|
||||
android:key="pref_angle_max"
|
||||
android:title="@string/max_angle"
|
||||
android:summary="@string/max_angle_desc"
|
||||
android:defaultValue="6"
|
||||
android:max="1"
|
||||
android:persistent="true"
|
||||
javadron:max="57.0"
|
||||
javadron:min="0.0"
|
||||
javadron:interval="0.06"
|
||||
javadron:unitsLeft=""
|
||||
javadron:unitsRight="°"/>
|
||||
<com.codeminders.ardrone.preferences.SeekBarPreference
|
||||
android:key="pref_vertical_speed_max"
|
||||
android:title="@string/vertical_speed"
|
||||
android:summary="@string/vertical_speed_desc"
|
||||
android:defaultValue="1"
|
||||
android:max="1"
|
||||
android:persistent="true"
|
||||
javadron:max="3.0"
|
||||
javadron:min="0.0"
|
||||
javadron:interval="0.03"
|
||||
javadron:unitsLeft=""
|
||||
javadron:unitsRight="m/s"/>
|
||||
<com.codeminders.ardrone.preferences.SeekBarPreference
|
||||
android:key="pref_rotation_speed_max"
|
||||
android:title="@string/rotation_speed"
|
||||
android:summary="@string/rotation_speed_desc"
|
||||
android:defaultValue="50"
|
||||
android:max="1"
|
||||
android:persistent="true"
|
||||
javadron:max="350.0"
|
||||
javadron:min="40.0"
|
||||
javadron:interval="1"
|
||||
javadron:unitsLeft=""
|
||||
javadron:unitsRight="°/s"
|
||||
javadron:roundValue="true"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/controller_configuration">
|
||||
<com.codeminders.ardrone.preferences.SeekBarPreference
|
||||
android:key="pref_controller_deadzone"
|
||||
android:title="@string/controller_deadzone"
|
||||
android:summary="@string/controller_deadzone_desc"
|
||||
android:defaultValue="30"
|
||||
android:max="1"
|
||||
android:persistent="true"
|
||||
javadron:max="100.0"
|
||||
javadron:min="0.0"
|
||||
javadron:interval="5"
|
||||
javadron:unitsLeft=""
|
||||
javadron:unitsRight="%"
|
||||
javadron:roundValue="true"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
@@ -12,7 +12,8 @@ public class ControllerThread extends Thread{
|
||||
ARDrone drone;
|
||||
Controller controller;
|
||||
private final ControlMap controlMap = new ControlMap();
|
||||
private static float CONTROL_THRESHOLD = 0.5f;
|
||||
private float controlThreshhold = 0.5f;
|
||||
|
||||
private static final long READ_UPDATE_DELAY_MS = 5L;
|
||||
|
||||
private final AtomicBoolean flipSticks = new AtomicBoolean(false);
|
||||
@@ -91,22 +92,22 @@ public class ControllerThread extends Thread{
|
||||
float vertical_speed = 0f;
|
||||
float angular_speed = 0f;
|
||||
|
||||
if(Math.abs(((float) leftX) / 128f) > CONTROL_THRESHOLD)
|
||||
if(Math.abs(((float) leftX) / 128f) > controlThreshhold)
|
||||
{
|
||||
left_right_tilt = ((float) leftX) / 128f;
|
||||
}
|
||||
|
||||
if(Math.abs(((float) leftY) / 128f) > CONTROL_THRESHOLD)
|
||||
if(Math.abs(((float) leftY) / 128f) > controlThreshhold)
|
||||
{
|
||||
front_back_tilt = ((float) leftY) / 128f;
|
||||
}
|
||||
|
||||
if(Math.abs(((float) rightX) / 128f) > CONTROL_THRESHOLD)
|
||||
if(Math.abs(((float) rightX) / 128f) > controlThreshhold)
|
||||
{
|
||||
angular_speed = ((float) rightX) / 128f;
|
||||
}
|
||||
|
||||
if(Math.abs(-1 * ((float) rightY) / 128f) > CONTROL_THRESHOLD)
|
||||
if(Math.abs(-1 * ((float) rightY) / 128f) > controlThreshhold)
|
||||
{
|
||||
vertical_speed = -1 * ((float) rightY) / 128f;
|
||||
}
|
||||
@@ -149,6 +150,12 @@ public class ControllerThread extends Thread{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setControlThreshhold(float controlThreshhold) {
|
||||
this.controlThreshhold = controlThreshhold;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.codeminders.ardrone;
|
||||
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@@ -10,19 +11,28 @@ import com.codeminders.ardrone.controller.usbhost.AfterGlowUsbHostController;
|
||||
import com.codeminders.ardrone.controller.usbhost.SonyPS3UsbHostController;
|
||||
import com.codeminders.ardrone.controller.usbhost.UsbHostController;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
@@ -30,24 +40,31 @@ import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MainActivity extends Activity implements DroneVideoListener {
|
||||
@SuppressLint({ "NewApi", "NewApi", "NewApi", "NewApi" })
|
||||
public class MainActivity extends Activity implements DroneVideoListener, OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final long CONNECTION_TIMEOUT = 10000;
|
||||
|
||||
static ARDrone drone;
|
||||
|
||||
ImageView display;
|
||||
TextView state;
|
||||
TextView joystick_state;
|
||||
Button connectButton;
|
||||
UsbHostController controller;
|
||||
Button connectUsbControllerButton;
|
||||
Button btnConnectUsbControllerButton;
|
||||
Button btnTakeOffOrLand;
|
||||
|
||||
private Builder usbNotSupportedDialog;
|
||||
|
||||
UsbManager manager;
|
||||
|
||||
ControllerThread ctrThread;
|
||||
|
||||
private static final String ACTION_USB_PERMISSION = "com.access.device.USB_PERMISSION";
|
||||
|
||||
private static final String TAG = "AR.Drone";
|
||||
|
||||
static MainActivity mainActivity;
|
||||
SharedPreferences prefs;
|
||||
|
||||
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@@ -67,148 +84,186 @@ public class MainActivity extends Activity implements DroneVideoListener {
|
||||
controller = new SonyPS3UsbHostController(deviceConnected, manager);
|
||||
joystickFound = true;
|
||||
} catch (Throwable e) {
|
||||
connectUsbControllerButton.setText("Error");
|
||||
joystick_state.setText("Error");
|
||||
}
|
||||
} else if (AfterGlowUsbHostController.isA(deviceConnected)) {
|
||||
try {
|
||||
controller = new AfterGlowUsbHostController(deviceConnected, manager);
|
||||
joystickFound = true;
|
||||
} catch (Throwable e) {
|
||||
connectUsbControllerButton.setText("Error");
|
||||
joystick_state.setText("Error");
|
||||
}
|
||||
}
|
||||
|
||||
if (joystickFound) {
|
||||
connectUsbControllerButton.setEnabled(false);
|
||||
connectUsbControllerButton.setText("Connected");
|
||||
btnConnectUsbControllerButton.setEnabled(false);
|
||||
joystick_state.setText("Connected");
|
||||
joystick_state.setTextColor(Color.GREEN);
|
||||
// Start joystick reading thread
|
||||
ctrThread = new ControllerThread(drone, controller);
|
||||
ctrThread.setName("Controll Thread");
|
||||
loadControllerDeadZone();
|
||||
ctrThread.start();
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
connectUsbControllerButton.setText("Denied");
|
||||
connectUsbControllerButton.setEnabled(false);
|
||||
joystick_state.setText("Denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private Builder turnOnWiFiDialog;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mainActivity = this;
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
|
||||
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
|
||||
|
||||
state = (TextView) findViewById(R.id.state);
|
||||
joystick_state = (TextView) findViewById(R.id.joystick_state);
|
||||
display = (ImageView) findViewById(R.id.display);
|
||||
connectButton = (Button) findViewById(R.id.connect);
|
||||
Button btnLand = (Button) findViewById(R.id.land);
|
||||
btnLand.setEnabled(false);
|
||||
Button btnTakeOff = (Button) findViewById(R.id.takeOff);
|
||||
btnTakeOff.setEnabled(false);
|
||||
|
||||
btnTakeOffOrLand = (Button) findViewById(R.id.takeOffOrland);
|
||||
btnTakeOffOrLand.setEnabled(false);
|
||||
|
||||
turnOnWiFiDialog = new AlertDialog.Builder(this);
|
||||
turnOnWiFiDialog.setMessage("Please turn on WiFi and connect to AR.Drone wireless accsess point");
|
||||
turnOnWiFiDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}});
|
||||
|
||||
final Button btnConnect = (Button) findViewById(R.id.connect);
|
||||
btnConnect.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
state.setTextColor(Color.RED);
|
||||
state.setText("Connecting...");
|
||||
(new DroneStarter()).execute(MainActivity.drone);
|
||||
WifiManager connManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
|
||||
|
||||
if (connManager.isWifiEnabled()) {
|
||||
state.setTextColor(Color.RED);
|
||||
state.setText("Connecting..." + connManager.getConnectionInfo().getSSID());
|
||||
btnConnect.setEnabled(false);
|
||||
(new DroneStarter()).execute(MainActivity.drone);
|
||||
} else {
|
||||
turnOnWiFiDialog.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
connectUsbControllerButton = (Button) findViewById(R.id.ps3Button);
|
||||
|
||||
connectUsbControllerButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
|
||||
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
|
||||
UsbDevice device = null;
|
||||
while (deviceIterator.hasNext()) {
|
||||
device = deviceIterator.next();
|
||||
break;
|
||||
}
|
||||
|
||||
if (null != device) {
|
||||
PendingIntent permissionIntent = PendingIntent.getBroadcast(mainActivity, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
IntentFilter permissionFilter = new IntentFilter(ACTION_USB_PERMISSION);
|
||||
mainActivity.registerReceiver(usbReceiver, permissionFilter);
|
||||
manager.requestPermission(device, permissionIntent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void showButtons() {
|
||||
|
||||
final Button takeOff = (Button) findViewById(R.id.takeOff);
|
||||
if (takeOff != null) {
|
||||
takeOff.setVisibility(View.VISIBLE);
|
||||
takeOff.setClickable(true);
|
||||
takeOff.setEnabled(true);
|
||||
takeOff.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
btnConnectUsbControllerButton = (Button) findViewById(R.id.ps3Button);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= 12) {
|
||||
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
final PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
|
||||
btnConnectUsbControllerButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
takeOff();
|
||||
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
|
||||
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
|
||||
UsbDevice device = null;
|
||||
while (deviceIterator.hasNext()) {
|
||||
device = deviceIterator.next();
|
||||
break;
|
||||
}
|
||||
|
||||
if (null != device) {
|
||||
IntentFilter permissionFilter = new IntentFilter(ACTION_USB_PERMISSION);
|
||||
registerReceiver(usbReceiver, permissionFilter);
|
||||
manager.requestPermission(device, permissionIntent);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
usbNotSupportedDialog = new AlertDialog.Builder(this);
|
||||
usbNotSupportedDialog.setMessage("Your phone does not support USB connections");
|
||||
usbNotSupportedDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}});
|
||||
|
||||
btnConnectUsbControllerButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
usbNotSupportedDialog.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
final Button land = (Button) findViewById(R.id.land);
|
||||
if (land != null) {
|
||||
land.setVisibility(View.VISIBLE);
|
||||
land.setClickable(true);
|
||||
land.setEnabled(true);
|
||||
land.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
private void droneOnConnected() {
|
||||
|
||||
state.setTextColor(Color.GREEN);
|
||||
state.setText("Connected");
|
||||
loadDroneSettingsFromPref();
|
||||
connectButton.setEnabled(false);
|
||||
drone.addImageListener(this);
|
||||
|
||||
if (btnTakeOffOrLand != null) {
|
||||
btnTakeOffOrLand.setVisibility(View.VISIBLE);
|
||||
btnTakeOffOrLand.setClickable(true);
|
||||
btnTakeOffOrLand.setEnabled(true);
|
||||
btnTakeOffOrLand.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
land();
|
||||
try
|
||||
{
|
||||
drone.clearEmergencySignal();
|
||||
drone.trim();
|
||||
} catch(Throwable e)
|
||||
{
|
||||
Log.e(TAG, "Faliled init drone" , e);
|
||||
}
|
||||
|
||||
if (btnTakeOffOrLand.getText().equals(getString(R.string.btn_land))) {
|
||||
try
|
||||
{
|
||||
drone.land();
|
||||
} catch(Throwable e)
|
||||
{
|
||||
Log.e(TAG, "Faliled to execute take off command" , e);
|
||||
}
|
||||
|
||||
btnTakeOffOrLand.setText(R.string.btn_take_off);
|
||||
} else {
|
||||
try
|
||||
{
|
||||
drone.takeOff();
|
||||
} catch(Throwable e)
|
||||
{
|
||||
Log.e(TAG, "Faliled to execute take off command" , e);
|
||||
}
|
||||
btnTakeOffOrLand.setText(R.string.btn_land);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void takeOff() {
|
||||
|
||||
try
|
||||
{
|
||||
drone.clearEmergencySignal();
|
||||
drone.trim();
|
||||
drone.takeOff();
|
||||
} catch(Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void land() {
|
||||
try
|
||||
{
|
||||
drone.land();
|
||||
} catch(Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.activity_main, menu);
|
||||
menu.add(0, 1, 1, R.string.str_exit);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case 0:
|
||||
case R.id.menu_settings:
|
||||
startActivity(new Intent(this, SettingsPrefs.class));
|
||||
break;
|
||||
case 1:
|
||||
case R.id.menu_exit:
|
||||
exitOptionsDialog();
|
||||
break;
|
||||
}
|
||||
@@ -218,12 +273,10 @@ public class MainActivity extends Activity implements DroneVideoListener {
|
||||
|
||||
private void exitOptionsDialog()
|
||||
{
|
||||
// Disconnect from the done
|
||||
try {
|
||||
drone.disconnect();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "failed to stop ar. drone", e);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
@@ -246,7 +299,6 @@ private class VideoDisplayer extends AsyncTask<Void, Integer, Void> {
|
||||
public int h;
|
||||
public VideoDisplayer(int x, int y, int width, int height, int[] arr, int off, int scan) {
|
||||
super();
|
||||
// do stuff
|
||||
rgbArray = arr;
|
||||
offset = off;
|
||||
scansize = scan;
|
||||
@@ -257,7 +309,6 @@ private class VideoDisplayer extends AsyncTask<Void, Integer, Void> {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
|
||||
b = Bitmap.createBitmap(rgbArray, offset, scansize, w, h, Bitmap.Config.RGB_565);
|
||||
b.setDensity(100);
|
||||
return null;
|
||||
@@ -276,23 +327,24 @@ private class DroneStarter extends AsyncTask<ARDrone, Integer, Boolean> {
|
||||
ARDrone drone = drones[0];
|
||||
try {
|
||||
drone = new ARDrone(InetAddress.getByAddress(ARDrone.DEFAULT_DRONE_IP), 10000, 60000);
|
||||
MainActivity.drone = drone; // passing in null objects will not pass object refs
|
||||
MainActivity.drone = drone;
|
||||
drone.connect();
|
||||
drone.clearEmergencySignal();
|
||||
drone.waitForReady(CONNECTION_TIMEOUT);
|
||||
drone.playLED(1, 10, 4);
|
||||
drone.addImageListener(MainActivity.mainActivity);
|
||||
drone.selectVideoChannel(ARDrone.VideoChannel.HORIZONTAL_ONLY);
|
||||
drone.setCombinedYawMode(true);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to connect to drone", e);
|
||||
try {
|
||||
drone.clearEmergencySignal();
|
||||
drone.clearImageListeners();
|
||||
drone.clearNavDataListeners();
|
||||
drone.clearStatusChangeListeners();
|
||||
drone.disconnect();
|
||||
} catch (Exception e1) {
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "Failed to clear drone state", ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -301,15 +353,92 @@ private class DroneStarter extends AsyncTask<ARDrone, Integer, Boolean> {
|
||||
|
||||
protected void onPostExecute(Boolean success) {
|
||||
if (success.booleanValue()) {
|
||||
state.setTextColor(Color.GREEN);
|
||||
state.setText("Connected");
|
||||
connectButton.setEnabled(false);
|
||||
mainActivity.showButtons();
|
||||
droneOnConnected();
|
||||
} else {
|
||||
state.setTextColor(Color.RED);
|
||||
state.setText("Error");
|
||||
connectButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals(PREF_MAX_ALTITUDE)) {
|
||||
droneLoadMaxAltitude();
|
||||
} else if (key.equals(PREF_MAX_ANGLE)) {
|
||||
droneLoadMaxAngle();
|
||||
} else if (key.equals(PREF_MAX_VERICAL_SPEED)) {
|
||||
droneLoadMaxVerticalSpeed();
|
||||
} else if (key.equals(PREF_MAX_ROTATION_SPEED)) {
|
||||
drobeLoadMaxRotationSpeed();
|
||||
} else if (key.equals(PREF_MAX_CONTROLLER_DEDZONE)) {
|
||||
loadControllerDeadZone();
|
||||
}
|
||||
}
|
||||
|
||||
public static String PREF_MAX_ALTITUDE = "pref_altitude_max";
|
||||
public static String PREF_MAX_ANGLE = "pref_angle_max";
|
||||
public static String PREF_MAX_VERICAL_SPEED = "pref_vertical_speed_max";
|
||||
public static String PREF_MAX_ROTATION_SPEED = "pref_rotation_speed_max";
|
||||
public static String PREF_MAX_CONTROLLER_DEDZONE = "pref_controller_deadzone";
|
||||
|
||||
public static String DRONE_MAX_YAW_PARAM_NAME = "control:control_yaw";
|
||||
public static String DRONE_MAX_VERT_SPEED_PARAM_NAME = "control:control_vz_max";
|
||||
public static String DRONE_MAX_EULA_ANGLE = "control:euler_angle_max";
|
||||
public static String DRONE_MAX_ALTITUDE = "control:altitude_max";
|
||||
|
||||
private void loadDroneSettingsFromPref() {
|
||||
droneLoadMaxAltitude();
|
||||
droneLoadMaxAngle();
|
||||
droneLoadMaxVerticalSpeed();
|
||||
drobeLoadMaxRotationSpeed();
|
||||
loadControllerDeadZone();
|
||||
}
|
||||
|
||||
private void drobeLoadMaxRotationSpeed() {
|
||||
if (null != drone && prefs.contains(PREF_MAX_ROTATION_SPEED)) {
|
||||
setDroneParam(DRONE_MAX_YAW_PARAM_NAME, String.valueOf(prefs.getFloat(PREF_MAX_ROTATION_SPEED, 50f) * Math.PI / 180f));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadControllerDeadZone() {
|
||||
if (null != ctrThread && prefs.contains(PREF_MAX_CONTROLLER_DEDZONE)) {
|
||||
ctrThread.setControlThreshhold(prefs.getFloat(PREF_MAX_ROTATION_SPEED, 30f) / 100f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void droneLoadMaxVerticalSpeed() {
|
||||
if (null != drone && prefs.contains(PREF_MAX_VERICAL_SPEED)) {
|
||||
setDroneParam(DRONE_MAX_YAW_PARAM_NAME, String.valueOf(Math.round(prefs.getFloat(PREF_MAX_VERICAL_SPEED, 1f) * 1000)));
|
||||
}
|
||||
}
|
||||
|
||||
private void droneLoadMaxAngle() {
|
||||
if (null != drone && prefs.contains(PREF_MAX_ANGLE)) {
|
||||
setDroneParam(DRONE_MAX_EULA_ANGLE, String.valueOf(prefs.getFloat(PREF_MAX_ANGLE, 6f) * Math.PI / 180f));
|
||||
}
|
||||
}
|
||||
|
||||
private void droneLoadMaxAltitude() {
|
||||
if (null != drone && prefs.contains(PREF_MAX_ALTITUDE)) {
|
||||
setDroneParam(DRONE_MAX_ALTITUDE, String.valueOf(Math.round(prefs.getFloat(PREF_MAX_ALTITUDE, 1.5f) * 1000)));
|
||||
}
|
||||
}
|
||||
|
||||
private void setDroneParam(final String name, final String value) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
drone.setConfigOption(name, value);
|
||||
} catch (IOException ex) {
|
||||
Log.e(TAG, "Failed to set drone parameter (" + name + ") to value: " + value , ex);
|
||||
}
|
||||
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.codeminders.ardrone;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
public class SettingsPrefs extends PreferenceActivity {
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package com.codeminders.ardrone.preferences;
|
||||
|
||||
import com.codeminders.ardrone.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
|
||||
|
||||
private static final String TAG = SeekBarPreference.class.getSimpleName();
|
||||
|
||||
private static final float DEFAULT_VALUE = 50;
|
||||
|
||||
private static final String APP_NS = "http://code.google.com/p/javadrone";
|
||||
|
||||
private float maxValue = 100;
|
||||
private float minValue = 0;
|
||||
private float interval = 1;
|
||||
private float currentValue;
|
||||
private boolean roundValue = false;
|
||||
private String unitsLeft = "";
|
||||
private String unitsRight = "";
|
||||
private SeekBar seekBar;
|
||||
|
||||
private TextView statusText;
|
||||
|
||||
public SeekBarPreference(Context context, AttributeSet attrs) {
|
||||
|
||||
super(context, attrs);
|
||||
initPreference(context, attrs);
|
||||
}
|
||||
|
||||
public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
|
||||
super(context, attrs, defStyle);
|
||||
initPreference(context, attrs);
|
||||
Log.d(TAG, "Preferences are installed");
|
||||
}
|
||||
|
||||
private void initPreference(Context context, AttributeSet attrs) {
|
||||
|
||||
Log.d(TAG, "Set values from xml");
|
||||
setValuesFromXml(attrs);
|
||||
this.seekBar = new SeekBar(context, attrs);
|
||||
this.seekBar.setMax(Math.round((this.maxValue - this.minValue)/this.interval));
|
||||
this.seekBar.setOnSeekBarChangeListener(this);
|
||||
}
|
||||
|
||||
private void setValuesFromXml(AttributeSet attrs) {
|
||||
|
||||
this.maxValue = attrs.getAttributeFloatValue(APP_NS, "max", 100);
|
||||
this.minValue = attrs.getAttributeFloatValue(APP_NS, "min", 0);
|
||||
|
||||
this.unitsLeft = getAttributeStringValue(attrs, APP_NS, "unitsLeft", "");
|
||||
this.unitsRight = getAttributeStringValue(attrs, APP_NS, "unitsRight", "");
|
||||
this.roundValue = attrs.getAttributeBooleanValue(APP_NS, "roundValue", false);
|
||||
|
||||
try {
|
||||
String newInterval = attrs.getAttributeValue(APP_NS, "interval");
|
||||
if(newInterval != null)
|
||||
this.interval = Float.parseFloat(newInterval);
|
||||
}
|
||||
catch(Exception e) {
|
||||
Log.e(TAG, "Invalid interval value", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) {
|
||||
|
||||
String value = attrs.getAttributeValue(namespace, name);
|
||||
if(value == null)
|
||||
value = defaultValue;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onCreateView(ViewGroup parent){
|
||||
|
||||
Log.d(TAG, "Start creating view");
|
||||
RelativeLayout layout = null;
|
||||
try {
|
||||
LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
layout = (RelativeLayout)mInflater.inflate(R.layout.seek_bar_preference, parent, false);
|
||||
}
|
||||
catch(Exception e) {
|
||||
Log.e(TAG, "Error creating seek bar preference", e);
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindView(View view) {
|
||||
|
||||
super.onBindView(view);
|
||||
Log.d(TAG, "Start binding view");
|
||||
try
|
||||
{
|
||||
// move our seekbar to the new view we've been given
|
||||
ViewParent oldContainer = this.seekBar.getParent();
|
||||
ViewGroup newContainer = (ViewGroup) view.findViewById(R.id.seekBarPrefBarContainer);
|
||||
|
||||
if (oldContainer != newContainer) {
|
||||
// remove the seekbar from the old view
|
||||
if (oldContainer != null) {
|
||||
((ViewGroup) oldContainer).removeView(this.seekBar);
|
||||
}
|
||||
// remove the existing seekbar (there may not be one) and add ours
|
||||
newContainer.removeAllViews();
|
||||
newContainer.addView(this.seekBar, ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
Log.e(TAG, "Error binding view: ", e);
|
||||
}
|
||||
updateView(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a SeekBarPreference view with our current state
|
||||
* @param view
|
||||
*/
|
||||
protected void updateView(View view) {
|
||||
|
||||
Log.d(TAG, "updateView");
|
||||
try {
|
||||
RelativeLayout layout = (RelativeLayout)view;
|
||||
|
||||
this.statusText = (TextView)layout.findViewById(R.id.seekBarPrefValue);
|
||||
this.statusText.setText( roundValue ? String.valueOf((int) this.currentValue) : String.valueOf(this.currentValue));
|
||||
this.statusText.setMinimumWidth(30);
|
||||
this.seekBar.setProgress((int)Math.round((this.currentValue - this.minValue)/this.interval));
|
||||
|
||||
TextView unitsRight = (TextView)layout.findViewById(R.id.seekBarPrefUnitsRight);
|
||||
unitsRight.setText(this.unitsRight);
|
||||
|
||||
TextView unitsLeft = (TextView)layout.findViewById(R.id.seekBarPrefUnitsLeft);
|
||||
unitsLeft.setText(this.unitsLeft);
|
||||
}
|
||||
catch(Exception e) {
|
||||
Log.e(TAG, "Error updating seek bar preference", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
|
||||
Log.d(TAG, "onProgressChanged");
|
||||
float newValue = ((float)Math.round((progress*this.interval+ this.minValue)*100))/100 ;
|
||||
if(newValue > this.maxValue)
|
||||
newValue = this.maxValue;
|
||||
else if(newValue < this.minValue)
|
||||
newValue = this.minValue;
|
||||
if(!callChangeListener(Math.round(newValue))){
|
||||
seekBar.setProgress(Math.round((this.currentValue - this.minValue)/this.interval));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.currentValue = newValue;
|
||||
this.statusText.setText(roundValue ? String.valueOf((int)newValue) : String.valueOf(newValue));
|
||||
persistFloat(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Object onGetDefaultValue(TypedArray ta, int index){
|
||||
|
||||
Log.d(TAG,"onGetDefaultValue");
|
||||
float defaultValue = ta.getFloat(index, DEFAULT_VALUE);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
||||
|
||||
Log.d(TAG,"onSetInitialValue");
|
||||
if(restoreValue) {
|
||||
Log.d(TAG,"restoreValue");
|
||||
this.currentValue = getPersistedFloat(this.currentValue);
|
||||
}
|
||||
else {
|
||||
float temp = (float)this.minValue;
|
||||
try {
|
||||
temp = (Float)defaultValue;
|
||||
}
|
||||
catch(Exception e) {
|
||||
Log.e(TAG, "Invalid default value: " + defaultValue.toString(), e);
|
||||
}
|
||||
persistFloat(temp);
|
||||
this.currentValue = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||