1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-19 09:54:15 +01:00

AndroidGCS: Create a fragment API.

The ObjectManagerFragment will automatically registers against the
activity to be notified when an onOPConnected or onOPDisconnected method
occurs.  The Fragment API also duplicates the registerObjectUpdates(UAVObject)
method from ObjectManagerActivity so that it's objectUpdated() method is called
whenever and using the appropriate UI thread.
This commit is contained in:
James Cotton 2012-08-08 08:37:35 -05:00
parent 0f0e5faba0
commit 6bed9fcb3c
6 changed files with 243 additions and 42 deletions

View File

@ -4,6 +4,12 @@
android:layout_height="match_parent"
android:layout_gravity="center" >
<fragment
android:name="org.openpilot.androidgcs.SystemAlarmsFragment"
android:id="@+id/viewer"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/system_alarms_status"

View File

@ -0,0 +1,18 @@
<?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:orientation="vertical" >
<ProgressBar
android:id="@+id/progressBar3"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/system_alarms_fragment_field"
android:layout_width="200dip"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -29,7 +29,7 @@ import android.widget.TextView;
public abstract class ObjectManagerActivity extends Activity {
private final String TAG = "ObjectManagerActivity";
private static int LOGLEVEL = 0;
private static int LOGLEVEL = 1;
// private static boolean WARN = LOGLEVEL > 1;
private static boolean DEBUG = LOGLEVEL > 0;
@ -162,6 +162,9 @@ public abstract class ObjectManagerActivity extends Activity {
stats.addUpdatedObserver(telemetryObserver);
telemetryStatsConnected = true;
updateStats();
if (DEBUG) Log.d(TAG, "Notifying listeners about connection. There are " + connectionListeners.countObservers());
connectionListeners.connected();
}
/**
@ -175,6 +178,9 @@ public abstract class ObjectManagerActivity extends Activity {
TextView txRate = (TextView) findViewById(R.id.telemetry_stats_tx_rate);
rxRate.setText("");
txRate.setText("");
// Providing a null update triggers a disconnect on fragments
connectionListeners.disconnected();
}
@Override
@ -223,6 +229,50 @@ public abstract class ObjectManagerActivity extends Activity {
public void onBind() {
}
/**
* Callbacks so ObjectManagerFragments get the onOPConnected and onOPDisconnected signals
*/
class ConnectionObserver extends Observable {
public void disconnected() {
synchronized(this) {
setChanged();
notifyObservers();
}
}
public void connected() {
synchronized(this) {
setChanged();
notifyObservers(objMngr);
}
}
};
private ConnectionObserver connectionListeners = new ConnectionObserver();
public class OnConnectionListener implements Observer {
// Local reference of the fragment to notify, store in constructor
ObjectManagerFragment fragment;
OnConnectionListener(ObjectManagerFragment fragment) { this.fragment = fragment; };
// Whenever the observer is updated either conenct or disconnect based on the data
@Override
public void update(Observable observable, Object data) {
Log.d(TAG, "onConnectionListener called");
if (data == null)
fragment.onOPDisconnected();
else
fragment.onOPConnected(objMngr);
}
} ;
void addOnConnectionListenerFragment(ObjectManagerFragment frag) {
connectionListeners.addObserver(new OnConnectionListener(frag));
if (DEBUG) Log.d(TAG, "Connecting " + frag + " there are now " + connectionListeners.countObservers());
if (mConnected)
frag.onOPConnected(objMngr);
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

View File

@ -0,0 +1,102 @@
package org.openpilot.androidgcs;
import java.util.List;
import java.util.ListIterator;
import java.util.Observable;
import java.util.Observer;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectManager;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class ObjectManagerFragment extends Fragment {
private static final String TAG = ObjectManagerFragment.class.getSimpleName();
private static int LOGLEVEL = 1;
// private static boolean WARN = LOGLEVEL > 1;
private static boolean DEBUG = LOGLEVEL > 0;
UAVObjectManager objMngr;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DEBUG) Log.d(TAG, "Created an ObjectManagerFragment");
// For an activity this registers against the telemetry service intents. Fragments must be notified by their
// parent activity
}
/**
* Attach to the parent activity so it can notify us when the connection
* changed
*/
public void onAttach(Activity activity) {
super.onAttach(activity);
if (DEBUG) Log.d(TAG,"onAttach");
((ObjectManagerActivity)activity).addOnConnectionListenerFragment(this);
}
// The below methods should all be called by the parent activity at the appropriate times
void onOPConnected(UAVObjectManager objMngr) {
this.objMngr = objMngr;
if (DEBUG) Log.d(TAG,"onOPConnected");
}
void onOPDisconnected() {
objMngr = null;
if (DEBUG) Log.d(TAG,"onOPDisconnected");
}
public void onBind() {
}
/**
* Called whenever any objects subscribed to via registerObjects
*/
protected void objectUpdated(UAVObject obj) {
}
/**
* A message handler and a custom Observer to use it which calls
* objectUpdated with the right object type
*/
final Handler uavobjHandler = new Handler();
private class UpdatedObserver implements Observer {
UAVObject obj;
UpdatedObserver(UAVObject obj) { this.obj = obj; };
public void update(Observable observable, Object data) {
uavobjHandler.post(new Runnable() {
@Override
public void run() { objectUpdated(obj); }
});
}
};
/**
* Register an activity to receive updates from this object
*
* the objectUpdated() method will be called in the original UI thread
*/
protected void registerObjectUpdates(UAVObject object) {
object.addUpdatedObserver(new UpdatedObserver(object));
}
protected void registerObjectUpdates(List<List<UAVObject>> objects) {
ListIterator<List<UAVObject>> li = objects.listIterator();
while(li.hasNext()) {
ListIterator<UAVObject> li2 = li.next().listIterator();
while(li2.hasNext())
registerObjectUpdates(li2.next());
}
}
}

View File

@ -1,51 +1,14 @@
package org.openpilot.androidgcs;
import java.util.List;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectField;
import android.os.Bundle;
import android.widget.TextView;
/**
* All the work for this activity is performed by it's fragment
*/
public class SystemAlarmActivity extends ObjectManagerActivity {
/**
* Update the UI whenever the attitude is updated
*/
protected void objectUpdated(UAVObject obj) {
if (obj.getName().compareTo("SystemAlarms") != 0)
return;
TextView alarms = (TextView) findViewById(R.id.system_alarms_status);
UAVObjectField a = obj.getField("Alarm");
List<String> names = a.getElementNames();
String contents = new String();
List <String> options = a.getOptions();
// Rank the alarms by order of severity, skip uninitialized
for (int j = options.size() - 1; j > 0; j--) {
for (int i = 0; i < names.size(); i++) {
if(a.getDouble(i) == j)
contents += names.get(i) + " : " + a.getValue(i).toString() + "\n";
}
}
alarms.setText(contents);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.system_alarms);
}
@Override
void onOPConnected() {
super.onOPConnected();
// Connect the update method to AttitudeActual
UAVObject obj = objMngr.getObject("SystemAlarms");
if (obj != null)
registerObjectUpdates(obj);
objectUpdated(obj);
}
}
}

View File

@ -0,0 +1,62 @@
package org.openpilot.androidgcs;
import java.util.List;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectField;
import org.openpilot.uavtalk.UAVObjectManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class SystemAlarmsFragment extends ObjectManagerFragment {
private static final String TAG = SystemAlarmsFragment.class.getSimpleName();
//@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.system_alarms_fragment, container, false);
}
public void onOPConnected(UAVObjectManager objMngr) {
super.onOPConnected(objMngr);
Log.d(TAG,"On connected");
UAVObject obj = objMngr.getObject("SystemAlarms");
if (obj != null)
registerObjectUpdates(obj);
objectUpdated(obj);
}
/**
* Called whenever any objects subscribed to via registerObjects
*/
@Override
protected void objectUpdated(UAVObject obj) {
Log.d(TAG, "Updated");
if (obj.getName().compareTo("SystemAlarms") == 0) {
TextView alarms = (TextView) getActivity().findViewById(R.id.system_alarms_fragment_field);
UAVObjectField a = obj.getField("Alarm");
List<String> names = a.getElementNames();
String contents = new String();
List <String> options = a.getOptions();
// Rank the alarms by order of severity, skip uninitialized
for (int j = options.size() - 1; j > 0; j--) {
for (int i = 0; i < names.size(); i++) {
if(a.getDouble(i) == j)
contents += names.get(i) + " : " + a.getValue(i).toString() + "\n";
}
}
alarms.setText(contents);
}
}
}