Task expansion capability.

This commit is contained in:
Keith Uplinger 2013-05-03 14:58:42 +00:00 committed by Joachim Fritzsch
parent ef6b24fe2b
commit ddc2d02e6e
17 changed files with 718 additions and 152 deletions

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

View File

@ -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>

View File

@ -73,6 +73,8 @@
</LinearLayout>
<include
android:id="@+id/expansion"
layout="@layout/tasks_layout_listitem_expansion" />
</LinearLayout>

View File

@ -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>

View File

@ -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&#8230;</string>

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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";

View File

@ -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");

View File

@ -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;
}
}
}