mirror of https://github.com/BOINC/boinc.git
Task expansion capability.
This commit is contained in:
parent
ef6b24fe2b
commit
ddc2d02e6e
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 583 B |
Binary file not shown.
After Width: | Height: | Size: 270 B |
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is part of BOINC.
|
||||
http://boinc.berkeley.edu
|
||||
Copyright (C) 2012 University of California
|
||||
|
||||
BOINC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License
|
||||
as published by the Free Software Foundation,
|
||||
either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
BOINC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="20dip"
|
||||
android:text="@string/prefs_loading"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar1"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
|
@ -73,6 +73,8 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<include
|
||||
android:id="@+id/expansion"
|
||||
layout="@layout/tasks_layout_listitem_expansion" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is part of BOINC.
|
||||
http://boinc.berkeley.edu
|
||||
Copyright (C) 2012 University of California
|
||||
|
||||
BOINC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License
|
||||
as published by the Free Software Foundation,
|
||||
either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
BOINC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="false"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="false"
|
||||
android:layout_centerVertical="false"
|
||||
android:gravity="left"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/projectName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Project Name:"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/friendlyAppName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Freindly App Name:"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/deadline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Deadline:"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/taskButtons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/abortTask"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@drawable/stopw48"
|
||||
android:src="@drawable/abortw24" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/suspendResumeTask"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/playw24" />
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
|
@ -197,6 +197,12 @@
|
|||
<string name="tasks_active_suspended">paused</string>
|
||||
<string name="tasks_active_abort_pending">stopping</string>
|
||||
<string name="tasks_active_quit_pending">stopping</string>
|
||||
|
||||
<!-- confirmation dialog -->
|
||||
<string name="confirm_abort_task_title">Abort task</string>
|
||||
<string name="confirm_abort_task_message">Abort task:</string>
|
||||
<string name="confirm_abort_task_confirm">Abort</string>
|
||||
<string name="confirm_abort_task_cancel">Cancel</string>
|
||||
|
||||
<!-- transfers tab strings -->
|
||||
<string name="trans_loading">Reading transfers…</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
******************************************************************************/
|
||||
package edu.berkeley.boinc;
|
||||
|
||||
import edu.berkeley.boinc.client.ClientNotification;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package edu.berkeley.boinc;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
|
||||
public class ConfirmationDialog extends android.support.v4.app.DialogFragment {
|
||||
private OnClickListener mConfirmClickListener = null;
|
||||
|
||||
public static ConfirmationDialog newInstance(String title, String message, String confirm) {
|
||||
ConfirmationDialog frag = new ConfirmationDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString("title", title);
|
||||
args.putString("message", message);
|
||||
args.putString("confirm", confirm);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
String title = getArguments().getString("title");
|
||||
String message = getArguments().getString("message");
|
||||
String confirm = getArguments().getString("confirm");
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(confirm, mConfirmClickListener)
|
||||
.setNegativeButton("Cancel", new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dismiss();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
public void setConfirmationClicklistener(OnClickListener cl) {
|
||||
mConfirmClickListener = cl;
|
||||
}
|
||||
|
||||
public interface ConfirmationDialogListener {
|
||||
void onDialogRead();
|
||||
void onDialogChecked(boolean isChecked);
|
||||
}
|
||||
}
|
|
@ -21,30 +21,54 @@ package edu.berkeley.boinc;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import edu.berkeley.boinc.adapter.TasksListAdapter;
|
||||
import edu.berkeley.boinc.client.ClientStatus;
|
||||
import edu.berkeley.boinc.client.Monitor;
|
||||
import edu.berkeley.boinc.rpc.Result;
|
||||
import android.app.Activity;
|
||||
import edu.berkeley.boinc.utils.BOINCDefs;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class TasksActivity extends Activity {
|
||||
public class TasksActivity extends FragmentActivity {
|
||||
|
||||
private final String TAG = "BOINC TasksActivity";
|
||||
|
||||
private Monitor monitor;
|
||||
private Boolean mIsBound;
|
||||
|
||||
private ClientStatus status; //client status, new information gets parsed by monitor, changes notified by "clientstatus" broadcast. read Result from here, to get information about tasks.
|
||||
|
||||
private ListView lv;
|
||||
private TasksListAdapter listAdapter;
|
||||
|
||||
private ArrayList<Result> data = new ArrayList<Result>(); //Adapter for list data
|
||||
|
||||
// Controls whether initialization of view elements of "tasks_layout"
|
||||
// is required. This is the case, every time the layout switched.
|
||||
private Boolean initialSetupRequired = true;
|
||||
private ArrayList<TaskData> data = new ArrayList<TaskData>(); //Adapter for list data
|
||||
private Boolean setup = false;
|
||||
|
||||
// This is called when the connection with the service has been established,
|
||||
// getService returns the Monitor object that is needed to call functions.
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
monitor = ((Monitor.LocalBinder)service).getService();
|
||||
mIsBound = true;
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
monitor = null;
|
||||
mIsBound = false;
|
||||
}
|
||||
};
|
||||
|
||||
private BroadcastReceiver mClientStatusChangeRec = new BroadcastReceiver() {
|
||||
|
||||
|
@ -52,15 +76,26 @@ public class TasksActivity extends Activity {
|
|||
@Override
|
||||
public void onReceive(Context context,Intent intent) {
|
||||
Log.d(TAG,"onReceive");
|
||||
populateLayout();
|
||||
loadData();
|
||||
}
|
||||
};
|
||||
private IntentFilter ifcsc = new IntentFilter("edu.berkeley.boinc.clientstatuschange");
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Log.d(TAG,"onCreate");
|
||||
|
||||
setContentView(R.layout.tasks_layout);
|
||||
// Establish a connection with the service, onServiceConnected gets called when
|
||||
// (calling within Tab needs getApplicationContext() for bindService to work!)
|
||||
getApplicationContext().bindService(new Intent(this, Monitor.class), mConnection, Service.START_STICKY_COMPATIBILITY);
|
||||
|
||||
//get singleton client status from monitor
|
||||
status = Monitor.getClientStatus();
|
||||
|
||||
//load data model
|
||||
loadData();
|
||||
|
||||
Log.d(TAG, "onCreate");
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
|
@ -68,7 +103,7 @@ public class TasksActivity extends Activity {
|
|||
//register noisy clientStatusChangeReceiver here, so only active when Activity is visible
|
||||
Log.d(TAG+"-onResume","register receiver");
|
||||
registerReceiver(mClientStatusChangeRec,ifcsc);
|
||||
populateLayout();
|
||||
loadData();
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
|
@ -78,44 +113,167 @@ public class TasksActivity extends Activity {
|
|||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
Log.d(TAG, "onDestroy()");
|
||||
|
||||
if (mIsBound) {
|
||||
getApplicationContext().unbindService(mConnection);
|
||||
mIsBound = false;
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void populateLayout() {
|
||||
try {
|
||||
//setup list and adapter
|
||||
ArrayList<Result> tmpA = Monitor.getClientStatus().getTasks();
|
||||
|
||||
if(tmpA == null) {
|
||||
setLayoutLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
//setup list and adapter
|
||||
ArrayList<Result> tmpA = status.getTasks();
|
||||
if(tmpA!=null) { //can be null before first monitor status cycle (e.g. when not logged in or during startup)
|
||||
|
||||
//deep copy, so ArrayList adapter actually recognizes the difference
|
||||
data.clear();
|
||||
for (Result tmp: tmpA) {
|
||||
data.add(tmp);
|
||||
}
|
||||
|
||||
if(initialSetupRequired) {// first time we got proper results, setup adapter
|
||||
initialSetupRequired = false;
|
||||
setContentView(R.layout.tasks_layout);
|
||||
updateData(tmpA);
|
||||
|
||||
if(!setup) { //first time we got proper results, setup adapter
|
||||
lv = (ListView) findViewById(R.id.tasksList);
|
||||
listAdapter = new TasksListAdapter(TasksActivity.this,R.id.tasksList,data);
|
||||
lv.setAdapter(listAdapter);
|
||||
}
|
||||
listAdapter = new TasksListAdapter(TasksActivity.this,R.id.tasksList,data);
|
||||
lv.setAdapter(listAdapter);
|
||||
|
||||
setup = true;
|
||||
}
|
||||
|
||||
Log.d(TAG,"loadData: array contains " + data.size() + " results.");
|
||||
listAdapter.notifyDataSetChanged(); //force list adapter to refresh
|
||||
|
||||
} catch (Exception e) {
|
||||
// data retrieval failed, set layout to loading...
|
||||
setLayoutLoading();
|
||||
|
||||
} else {
|
||||
Log.d(TAG, "loadData array is null");
|
||||
}
|
||||
}
|
||||
|
||||
private void setLayoutLoading() {
|
||||
setContentView(R.layout.generic_layout_loading);
|
||||
TextView loadingHeader = (TextView)findViewById(R.id.loading_header);
|
||||
loadingHeader.setText(R.string.tasks_loading);
|
||||
initialSetupRequired = true;
|
||||
|
||||
private void updateData(ArrayList<Result> newData) {
|
||||
// Create a new task data list based on new data
|
||||
ArrayList<TaskData> tdl = new ArrayList<TaskData>();
|
||||
for (Result r : newData) {
|
||||
tdl.add(new TaskData(r));
|
||||
}
|
||||
// search for the same id in the old tasks
|
||||
// maybe tasks were rearranged or updated
|
||||
for (int i = 0; i < tdl.size(); i++) {
|
||||
int j;
|
||||
for (j = 0; j < data.size(); j++) {
|
||||
if (tdl.get(i).id.equals(data.get(j).id)) {
|
||||
// this task is old.
|
||||
// retrieve expansion state
|
||||
tdl.get(i).expanded = data.get(j).expanded;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == data.size()) {
|
||||
// this is a new task, so add it
|
||||
data.add(tdl.get(i));
|
||||
}
|
||||
}
|
||||
// save new task data list
|
||||
data.clear();
|
||||
|
||||
for (TaskData td: tdl) {
|
||||
data.add(td);
|
||||
}
|
||||
}
|
||||
|
||||
public class TaskData {
|
||||
public static final int TASK_STATE_UNKNOWN = 0;
|
||||
public static final int TASK_STATE_PAUSED = 1;
|
||||
public static final int TASK_STATE_RUNNING = 2;
|
||||
|
||||
public static final int TASK_STATE_ACTIVE = 10;
|
||||
public static final int TASK_STATE_ABORTED = 11;
|
||||
|
||||
public Result result = null;
|
||||
public boolean expanded = false;
|
||||
public String id = "";
|
||||
public int nextRunState = TASK_STATE_UNKNOWN;
|
||||
public int currentRunState = TASK_STATE_UNKNOWN;
|
||||
public int nextAbortState = TASK_STATE_UNKNOWN;
|
||||
public int currentAbortState = TASK_STATE_UNKNOWN;
|
||||
|
||||
public TaskData(Result data) {
|
||||
this.result = data;
|
||||
this.expanded = false;
|
||||
this.id = data.name;
|
||||
this.currentRunState = determineRunningState();
|
||||
this.nextRunState = this.currentRunState;
|
||||
this.currentAbortState = determineAbortState();
|
||||
this.nextAbortState = this.currentAbortState;
|
||||
}
|
||||
|
||||
public final OnClickListener taskClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
expanded = !expanded;
|
||||
listAdapter.notifyDataSetChanged(); //force list adapter to refresh
|
||||
}
|
||||
};
|
||||
|
||||
public final OnClickListener abortClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ConfirmationDialog cd = ConfirmationDialog.newInstance(
|
||||
getString(R.string.confirm_abort_task_title) + "?",
|
||||
getString(R.string.confirm_abort_task_message) + " " + result.name,
|
||||
getString(R.string.confirm_abort_task_confirm));
|
||||
cd.setConfirmationClicklistener(new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
nextAbortState = TASK_STATE_ABORTED;
|
||||
monitor.abortResultAsync(result.project_url, result.name);
|
||||
}
|
||||
});
|
||||
cd.show(getSupportFragmentManager(), "");
|
||||
listAdapter.notifyDataSetChanged(); //force list adapter to refresh
|
||||
}
|
||||
};
|
||||
|
||||
public final OnClickListener suspendClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
nextRunState = TASK_STATE_PAUSED;
|
||||
monitor.suspendResultAsync(result.project_url, result.name);
|
||||
listAdapter.notifyDataSetChanged(); //force list adapter to refresh
|
||||
}
|
||||
};
|
||||
|
||||
public final OnClickListener resumeClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
nextRunState = TASK_STATE_RUNNING;
|
||||
monitor.resumeResultAsync(result.project_url, result.name);
|
||||
listAdapter.notifyDataSetChanged(); //force list adapter to refresh
|
||||
}
|
||||
};
|
||||
|
||||
public int determineRunningState() {
|
||||
if(result.active_task) {
|
||||
if(result.active_task_state == BOINCDefs.PROCESS_EXECUTING) {
|
||||
//running
|
||||
return TASK_STATE_RUNNING;
|
||||
} else {
|
||||
//suspended - ready to run
|
||||
return TASK_STATE_PAUSED;
|
||||
}
|
||||
} else {
|
||||
//paused or stopped
|
||||
return TASK_STATE_PAUSED;
|
||||
}
|
||||
}
|
||||
|
||||
public int determineAbortState() {
|
||||
if(!result.active_task) {
|
||||
switch (result.state) {
|
||||
case 6:
|
||||
return TASK_STATE_ABORTED;
|
||||
}
|
||||
}
|
||||
return TASK_STATE_ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,56 +18,63 @@
|
|||
******************************************************************************/
|
||||
package edu.berkeley.boinc.adapter;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import edu.berkeley.boinc.R;
|
||||
import edu.berkeley.boinc.rpc.Result;
|
||||
import edu.berkeley.boinc.TasksActivity.TaskData;
|
||||
import edu.berkeley.boinc.utils.BOINCDefs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class TasksListAdapter extends ArrayAdapter<Result>{
|
||||
public class TasksListAdapter extends ArrayAdapter<TaskData>{
|
||||
|
||||
//private final String TAG = "TasksListAdapter";
|
||||
private ArrayList<Result> entries;
|
||||
private Activity activity;
|
||||
private ArrayList<TaskData> entries;
|
||||
private Activity activity;
|
||||
|
||||
public TasksListAdapter(Activity a, int textViewResourceId, ArrayList<Result> entries) {
|
||||
super(a, textViewResourceId, entries);
|
||||
this.entries = entries;
|
||||
this.activity = a;
|
||||
}
|
||||
public TasksListAdapter(Activity a, int textViewResourceId, ArrayList<TaskData> entries) {
|
||||
super(a, textViewResourceId, entries);
|
||||
this.entries = entries;
|
||||
this.activity = a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
|
||||
View v = convertView;
|
||||
LayoutInflater vi = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
v = vi.inflate(R.layout.tasks_layout_listitem, null);
|
||||
View v = convertView;
|
||||
LayoutInflater vi = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
v = vi.inflate(R.layout.tasks_layout_listitem, null);
|
||||
v.setOnClickListener(entries.get(position).taskClickListener);
|
||||
|
||||
ProgressBar pb = (ProgressBar) v.findViewById(R.id.progressBar);
|
||||
TextView header = (TextView) v.findViewById(R.id.taskName);
|
||||
TextView status = (TextView) v.findViewById(R.id.taskStatus);
|
||||
TextView time = (TextView) v.findViewById(R.id.taskTime);
|
||||
TextView progress = (TextView) v.findViewById(R.id.taskProgress);
|
||||
|
||||
Result listItem = entries.get(position);
|
||||
|
||||
TaskData listItem = entries.get(position);
|
||||
|
||||
pb.setIndeterminate(false);
|
||||
pb.setProgressDrawable(this.activity.getResources().getDrawable((determineProgressBarLayout(listItem))));
|
||||
pb.setProgressDrawable(this.activity.getResources().getDrawable((determineProgressBarLayout(listItem))));
|
||||
|
||||
//v.setTag(listItem.name);
|
||||
String headerT = "Name: " + listItem.name;
|
||||
String headerT = "Name: " + listItem.result.name;
|
||||
header.setText(headerT);
|
||||
|
||||
Float fraction = listItem.fraction_done;
|
||||
if(!listItem.active_task && listItem.ready_to_report) { //fraction not available, set it to 100
|
||||
Float fraction = listItem.result.fraction_done;
|
||||
if(!listItem.result.active_task && listItem.result.ready_to_report) { //fraction not available, set it to 100
|
||||
fraction = Float.valueOf((float) 1.0);
|
||||
}
|
||||
pb.setProgress(Math.round(fraction * pb.getMax()));
|
||||
|
@ -77,83 +84,142 @@ public class TasksListAdapter extends ArrayAdapter<Result>{
|
|||
String statusT = determineStatusText(listItem);
|
||||
status.setText(statusT);
|
||||
|
||||
int elapsedTime = (int)listItem.elapsed_time;
|
||||
int elapsedTime = (int)listItem.result.elapsed_time;
|
||||
time.setText(String.format("%02d:%02d:%02d", elapsedTime/3600, (elapsedTime/60)%60, elapsedTime%60));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
RelativeLayout ll = (RelativeLayout) v.findViewById(R.id.expansion);
|
||||
if (listItem.expanded) {
|
||||
ll.setVisibility(View.VISIBLE);
|
||||
// update resume/suspend state (button state)
|
||||
listItem.currentRunState = listItem.determineRunningState();
|
||||
// update abort state (button state)
|
||||
listItem.currentAbortState = listItem.determineAbortState();
|
||||
// set deadline
|
||||
String deadline = (String) DateFormat.format("E d MMM yyyy hh:mm:ss aa", new Date(listItem.result.report_deadline*1000));
|
||||
((TextView) v.findViewById(R.id.deadline)).setText("Deadline: " + deadline);
|
||||
// set project name
|
||||
((TextView) v.findViewById(R.id.projectName)).setText("Project name: " + listItem.result.project_url);
|
||||
// TODO: set application friendly name
|
||||
|
||||
ImageView suspendResume = (ImageView) v.findViewById(R.id.suspendResumeTask);
|
||||
if (listItem.currentRunState == listItem.nextRunState) {
|
||||
// current button state is same as expected
|
||||
suspendResume.setEnabled(true);
|
||||
suspendResume.setClickable(true);
|
||||
if (listItem.currentRunState == TaskData.TASK_STATE_RUNNING) {
|
||||
suspendResume.setOnClickListener(listItem.suspendClickListener);
|
||||
suspendResume.setImageResource(R.drawable.pausew24);
|
||||
} else {
|
||||
suspendResume.setOnClickListener(listItem.resumeClickListener);
|
||||
suspendResume.setImageResource(R.drawable.playw24);
|
||||
}
|
||||
} else {
|
||||
// waiting for transient state to be as expected
|
||||
// button needs to be disabled (no action should be taken while waiting)
|
||||
suspendResume.setEnabled(false);
|
||||
suspendResume.setClickable(false);
|
||||
suspendResume.setOnClickListener(null);
|
||||
if (listItem.currentRunState == TaskData.TASK_STATE_RUNNING) {
|
||||
suspendResume.setImageResource(R.drawable.pausew24);
|
||||
} else {
|
||||
suspendResume.setImageResource(R.drawable.playw24);
|
||||
}
|
||||
}
|
||||
if (listItem.currentAbortState == listItem.nextAbortState) {
|
||||
// current button state is same as expected
|
||||
if (listItem.currentAbortState == TaskData.TASK_STATE_ABORTED) {
|
||||
suspendResume.setEnabled(false);
|
||||
suspendResume.setClickable(false);
|
||||
} else {
|
||||
suspendResume.setEnabled(true);
|
||||
suspendResume.setClickable(true);
|
||||
((ImageView) v.findViewById(R.id.abortTask)).setOnClickListener(listItem.abortClickListener);
|
||||
}
|
||||
} else {
|
||||
// waiting for transient state to be as expected
|
||||
// button needs to be disabled (no action should be taken while waiting)
|
||||
suspendResume.setEnabled(false);
|
||||
suspendResume.setClickable(false);
|
||||
suspendResume.setOnClickListener(null);
|
||||
}
|
||||
} else {
|
||||
ll.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
private String determineStatusText(TaskData tmp) {
|
||||
String text = "";
|
||||
if(tmp.result.active_task) {
|
||||
switch (tmp.result.active_task_state) {
|
||||
case 0:
|
||||
text = activity.getString(R.string.tasks_active_uninitialized);
|
||||
break;
|
||||
case 1:
|
||||
text = activity.getString(R.string.tasks_active_executing);
|
||||
break;
|
||||
case 5:
|
||||
text = activity.getString(R.string.tasks_active_abort_pending);
|
||||
break;
|
||||
case 8:
|
||||
text = activity.getString(R.string.tasks_active_quit_pending);
|
||||
break;
|
||||
case 9:
|
||||
text = activity.getString(R.string.tasks_active_suspended);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (tmp.result.state) {
|
||||
case 0:
|
||||
text = activity.getString(R.string.tasks_result_new);
|
||||
break;
|
||||
case 1:
|
||||
text = activity.getString(R.string.tasks_result_files_downloading);
|
||||
break;
|
||||
case 2:
|
||||
text = activity.getString(R.string.tasks_result_files_downloaded);
|
||||
break;
|
||||
case 3:
|
||||
text = activity.getString(R.string.tasks_result_compute_error);
|
||||
break;
|
||||
case 4:
|
||||
text = activity.getString(R.string.tasks_result_files_uploading);
|
||||
break;
|
||||
case 5:
|
||||
text = activity.getString(R.string.tasks_result_files_uploaded);
|
||||
break;
|
||||
case 6:
|
||||
text = activity.getString(R.string.tasks_result_aborted);
|
||||
break;
|
||||
case 7:
|
||||
text = activity.getString(R.string.tasks_result_upload_failed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String determineStatusText(Result tmp) {
|
||||
String text = "";
|
||||
if(tmp.active_task) {
|
||||
switch (tmp.active_task_state) {
|
||||
case 0:
|
||||
text = activity.getString(R.string.tasks_active_uninitialized);
|
||||
break;
|
||||
case 1:
|
||||
text = activity.getString(R.string.tasks_active_executing);
|
||||
break;
|
||||
case 5:
|
||||
text = activity.getString(R.string.tasks_active_abort_pending);
|
||||
break;
|
||||
case 8:
|
||||
text = activity.getString(R.string.tasks_active_quit_pending);
|
||||
break;
|
||||
case 9:
|
||||
text = activity.getString(R.string.tasks_active_suspended);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (tmp.state) {
|
||||
case 0:
|
||||
text = activity.getString(R.string.tasks_result_new);
|
||||
break;
|
||||
case 1:
|
||||
text = activity.getString(R.string.tasks_result_files_downloading);
|
||||
break;
|
||||
case 2:
|
||||
text = activity.getString(R.string.tasks_result_files_downloaded);
|
||||
break;
|
||||
case 3:
|
||||
text = activity.getString(R.string.tasks_result_compute_error);
|
||||
break;
|
||||
case 4:
|
||||
text = activity.getString(R.string.tasks_result_files_uploading);
|
||||
break;
|
||||
case 5:
|
||||
text = activity.getString(R.string.tasks_result_files_uploaded);
|
||||
break;
|
||||
case 6:
|
||||
text = activity.getString(R.string.tasks_result_aborted);
|
||||
break;
|
||||
case 7:
|
||||
text = activity.getString(R.string.tasks_result_upload_failed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private Integer determineProgressBarLayout(Result tmp) {
|
||||
if(tmp.active_task) {
|
||||
if(tmp.active_task_state == BOINCDefs.PROCESS_EXECUTING) {
|
||||
//running
|
||||
return R.drawable.progressbar_active;
|
||||
} else {
|
||||
//suspended - ready to run
|
||||
return R.drawable.progressbar_paused;
|
||||
}
|
||||
} else {
|
||||
if((tmp.state == BOINCDefs.RESULT_ABORTED) || (tmp.state == BOINCDefs.RESULT_UPLOAD_FAILED) || (tmp.state == BOINCDefs.RESULT_COMPUTE_ERROR)) {
|
||||
//error
|
||||
return R.drawable.progressbar_error;
|
||||
} else if (tmp.ready_to_report) {
|
||||
//finished
|
||||
return R.drawable.progressbar_active;
|
||||
} else {
|
||||
//paused or stopped
|
||||
return R.drawable.progressbar_paused;
|
||||
}
|
||||
}
|
||||
}
|
||||
private Integer determineProgressBarLayout(TaskData tmp) {
|
||||
if(tmp.result.active_task) {
|
||||
if(tmp.result.active_task_state == BOINCDefs.PROCESS_EXECUTING) {
|
||||
//running
|
||||
return R.drawable.progressbar_active;
|
||||
} else {
|
||||
//suspended - ready to run
|
||||
return R.drawable.progressbar_paused;
|
||||
}
|
||||
} else {
|
||||
if((tmp.result.state == BOINCDefs.RESULT_ABORTED) || (tmp.result.state == BOINCDefs.RESULT_UPLOAD_FAILED) || (tmp.result.state == BOINCDefs.RESULT_COMPUTE_ERROR)) {
|
||||
//error
|
||||
return R.drawable.progressbar_error;
|
||||
} else if (tmp.result.ready_to_report) {
|
||||
//finished
|
||||
return R.drawable.progressbar_active;
|
||||
} else {
|
||||
//paused or stopped
|
||||
return R.drawable.progressbar_paused;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -810,6 +810,42 @@ public class Monitor extends Service {
|
|||
param[1] = name;
|
||||
(new TransferRetryAsync()).execute(param);
|
||||
}
|
||||
|
||||
public Boolean suspendResult(String url, String name){
|
||||
return rpc.resultOp(RpcClient.RESULT_SUSPEND, url, name);
|
||||
}
|
||||
|
||||
public void suspendResultAsync(String url, String name){
|
||||
Log.d(TAG, "suspendResultAsync");
|
||||
String[] param = new String[2];
|
||||
param[0] = url;
|
||||
param[1] = name;
|
||||
(new SuspendResultAsync()).execute(param);
|
||||
}
|
||||
|
||||
public Boolean resumeResult(String url, String name){
|
||||
return rpc.resultOp(RpcClient.RESULT_RESUME, url, name);
|
||||
}
|
||||
|
||||
public void resumeResultAsync(String url, String name){
|
||||
Log.d(TAG, "resumeResultAsync");
|
||||
String[] param = new String[2];
|
||||
param[0] = url;
|
||||
param[1] = name;
|
||||
(new ResumeResultAsync()).execute(param);
|
||||
}
|
||||
|
||||
public Boolean abortResult(String url, String name){
|
||||
return rpc.resultOp(RpcClient.RESULT_RESUME, url, name);
|
||||
}
|
||||
|
||||
public void abortResultAsync(String url, String name){
|
||||
Log.d(TAG, "abortResultAsync");
|
||||
String[] param = new String[2];
|
||||
param[0] = url;
|
||||
param[1] = name;
|
||||
(new AbortResultAsync()).execute(param);
|
||||
}
|
||||
|
||||
public AccountOut createAccount(String url, String email, String userName, String pwd, String teamName) {
|
||||
AccountIn information = new AccountIn();
|
||||
|
@ -1067,6 +1103,98 @@ public class Monitor extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
private final class SuspendResultAsync extends AsyncTask<String,String,Boolean> {
|
||||
|
||||
private final String TAG = "SuspendResultAsync";
|
||||
|
||||
private String url;
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
this.url = params[0];
|
||||
this.name = params[1];
|
||||
publishProgress("doInBackground() - SuspendResultAsync url: " + url + " Name: " + name);
|
||||
|
||||
Boolean retry = rpc.resultOp(RpcClient.RESULT_SUSPEND, url, name);
|
||||
if(retry) {
|
||||
publishProgress("successful.");
|
||||
}
|
||||
return retry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
forceRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(String... arg0) {
|
||||
Log.d(TAG, "onProgressUpdate - " + arg0[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private final class ResumeResultAsync extends AsyncTask<String,String,Boolean> {
|
||||
|
||||
private final String TAG = "ResumeResultAsync";
|
||||
|
||||
private String url;
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
this.url = params[0];
|
||||
this.name = params[1];
|
||||
publishProgress("doInBackground() - ResumeResultAsync url: " + url + " Name: " + name);
|
||||
Boolean retry = rpc.resultOp(RpcClient.RESULT_RESUME, url, name);
|
||||
if(retry) {
|
||||
publishProgress("successful.");
|
||||
}
|
||||
return retry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
forceRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(String... arg0) {
|
||||
Log.d(TAG, "onProgressUpdate - " + arg0[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private final class AbortResultAsync extends AsyncTask<String,String,Boolean> {
|
||||
|
||||
private final String TAG = "AbortResultAsync";
|
||||
|
||||
private String url;
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
this.url = params[0];
|
||||
this.name = params[1];
|
||||
publishProgress("doInBackground() - AbortResultAsync url: " + url + " Name: " + name);
|
||||
|
||||
Boolean retry = rpc.resultOp(RpcClient.RESULT_ABORT, url, name);
|
||||
if(retry) {
|
||||
publishProgress("successful.");
|
||||
}
|
||||
return retry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
forceRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(String... arg0) {
|
||||
Log.d(TAG, "onProgressUpdate - " + arg0[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private final class WriteClientRunModeAsync extends AsyncTask<Integer, String, Boolean> {
|
||||
|
||||
private final String TAG = "WriteClientRunModeAsync";
|
||||
|
|
|
@ -22,8 +22,6 @@ import edu.berkeley.boinc.AppPreferences;
|
|||
import edu.berkeley.boinc.BOINCActivity;
|
||||
import edu.berkeley.boinc.R;
|
||||
import edu.berkeley.boinc.client.Monitor;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
|
@ -34,7 +32,6 @@ import android.util.Log;
|
|||
public class BootReceiver extends BroadcastReceiver {
|
||||
|
||||
private final String TAG = "BOINC BootReceiver";
|
||||
private NotificationManager mNM;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
@ -48,15 +45,8 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
//startServiceIntent.putExtra("autostart", true);
|
||||
context.startService(startServiceIntent);
|
||||
|
||||
mNM = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
|
||||
Notification notification = new Notification(R.drawable.boinc, context.getString(R.string.autostart_notification_header), System.currentTimeMillis());
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(context.getApplicationContext(), 0, new Intent(context.getApplicationContext(), BOINCActivity.class), 0);
|
||||
|
||||
// Set current view for notification panel
|
||||
notification.setLatestEventInfo(context.getApplicationContext(), context.getString(R.string.autostart_notification_header), context.getString(R.string.autostart_notification_text), contentIntent);
|
||||
|
||||
// Send notification
|
||||
mNM.notify(context.getResources().getInteger(R.integer.autostart_notification_id), notification);
|
||||
} else {
|
||||
// do nothing
|
||||
Log.d(TAG,"autostart disabeld");
|
||||
|
|
|
@ -1103,4 +1103,52 @@ public class RpcClient {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers operation on task in BOINC core client
|
||||
* @param operation operation to be triggered
|
||||
* @param projectUrl master URL of project
|
||||
* @param fileName name of the file
|
||||
* @return true for success, false for failure
|
||||
*/
|
||||
public boolean resultOp(int operation, String projectUrl, String resultName) {
|
||||
try {
|
||||
String opTag;
|
||||
switch (operation) {
|
||||
case RESULT_SUSPEND:
|
||||
opTag = "suspend_result";
|
||||
break;
|
||||
case RESULT_RESUME:
|
||||
opTag = "resume_result";
|
||||
break;
|
||||
case RESULT_ABORT:
|
||||
opTag = "abort_result";
|
||||
break;
|
||||
default:
|
||||
if (Logging.ERROR) Log.e(TAG, "resultOp() - unsupported operation: " + operation);
|
||||
return false;
|
||||
}
|
||||
mRequest.setLength(0);
|
||||
mRequest.append("<");
|
||||
mRequest.append(opTag);
|
||||
mRequest.append(">\n <project_url>");
|
||||
mRequest.append(projectUrl);
|
||||
mRequest.append("</project_url>\n <name>");
|
||||
mRequest.append(resultName);
|
||||
mRequest.append("</name>\n</");
|
||||
mRequest.append(opTag);
|
||||
mRequest.append(">\n");
|
||||
sendRequest(mRequest.toString());
|
||||
|
||||
SimpleReplyParser parser = SimpleReplyParser.parse(receiveReply());
|
||||
if (parser == null)
|
||||
return false;
|
||||
mLastErrorMessage = parser.getErrorMessage();
|
||||
return parser.result();
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (Logging.WARNING) Log.w(TAG, "error in transferOp()", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue