Commit d93a3071 authored by Alan McNatty's avatar Alan McNatty
Browse files

A bunch of changes for 1.7b3 - the ability to save and later upload artefacts, etc

parent e6a67a68
......@@ -2,12 +2,16 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="nz.net.catalyst.MaharaDroid"
android:versionCode="7"
android:versionName="1.8">
android:versionName="1.7">
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:debuggable="true" >
android:debuggable="false" >
<activity android:name=".ui.MaharaDroid"
<activity android:name=".ui.ArtefactExpandableListAdapterActivity"
android:label="@string/app_name" >
<!--
<activity android:name=".ui.ArtefactExpandableListAdapterActivity"
android:label="@string/options_menu_viewsaved" /> -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
......@@ -59,13 +63,12 @@
</activity>
<activity android:name=".ui.EditPreferences"
android:label="@string/options_menu_prefs" />
<activity android:name=".ui.ArtefactExpandableListAdapterActivity"
android:label="@string/options_menu_viewsaved" />
<service android:name=".upload.TransferService" android:label="@string/filetransfers"/>
</application>
<!-- API Level 4 aka 1.6 required for multi-send support -->
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<ExpandableListView android:id="@+id/listView"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#fff"
android:id="@+id/top"
>
<ImageView
android:id="@+id/banner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:src="@drawable/banner"
android:layout_gravity="left"
android:scaleType="fitStart"
/>
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/middle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:layout_below="@+id/top"
>
<TextView android:id="@+id/banner_text"
android:text="@string/artefacts_banner_text"
android:layout_width="wrap_content"
android:singleLine="false"
android:layout_height="wrap_content"
android:textStyle="bold"
android:layout_margin="5dp"
style="@android:style/TextAppearance.Large"
android:layout_below="@+id/banner"
/>
<TextView android:id="@+id/banner_text2"
android:text="@string/artefacts_banner_text2"
android:layout_margin="5dp"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:singleLine="false"
android:layout_height="wrap_content"
style="@android:style/TextAppearance.Small"
android:layout_below="@+id/banner_text"
/>
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bottom_heading"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#333"
android:layout_below="@+id/middle"
>
<TextView android:id="@+id/saved_artefacts_header"
android:text="@string/options_menu_viewsaved"
android:layout_margin="5dp"
android:layout_width="fill_parent"
android:singleLine="true"
android:layout_height="wrap_content"
style="@android:style/TextAppearance.Medium"
android:layout_below="@+id/banner_text2"
/>
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bottom"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#000"
android:layout_below="@+id/bottom_heading"
>
<ExpandableListView android:id="@+id/listView"
android:scrollbars="none"
android:choiceMode="multipleChoice"
android:fastScrollEnabled="true"
android:layout_below="@+id/saved_artefacts_header"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
/>
</LinearLayout>
\ No newline at end of file
<TextView android:id="@+id/no_saved_artefacts"
android:text="@string/artefacts_no_saved_artefacts"
android:layout_margin="0dp"
android:layout_width="fill_parent"
android:singleLine="true"
android:layout_height="wrap_content"
style="@android:style/TextAppearance.Small"
android:layout_below="@+id/listView"
android:visibility="gone"
/>
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/about"
android:icon="@android:drawable/ic_menu_info_details"
android:title="@string/pref_menu_about" />
<item android:id="@+id/option_pref"
android:icon= "@android:drawable/ic_menu_preferences"
android:title="@string/options_menu_prefs" />
<item android:id="@+id/option_upload"
android:icon="@android:drawable/ic_menu_upload"
android:title="@string/options_menu_uploadall" />
......
......@@ -3,6 +3,9 @@
<item android:id="@+id/context_upload"
android:icon="@android:drawable/ic_menu_upload"
android:title="@string/context_menu_upload" />
<item android:id="@+id/context_view"
android:icon="@android:drawable/ic_menu_view"
android:title="@string/context_menu_view" />
<item android:id="@+id/context_delete"
android:icon="@android:drawable/ic_delete"
android:title="@string/context_menu_delete" />
......
......@@ -6,7 +6,4 @@
<item android:id="@+id/option_pref"
android:icon= "@android:drawable/ic_menu_preferences"
android:title="@string/options_menu_prefs" />
<item android:id="@+id/view_saved_artefacts"
android:icon="@android:drawable/ic_menu_save"
android:title="@string/options_menu_viewsaved" />
</menu>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MaharaDroid</string>
<string name="startup_text">Welcome to MaharaDroid</string>
<string name="artefacts_banner_text">Open source eportfolios</string>
<string name="artefacts_banner_text2">[mah-har-rah;verb]: to think, thinking, thought</string>
<string name="artefacts_no_saved_artefacts">No saved artefacts</string>
<string name="options_menu_prefs">Preferences</string>
<string name="options_menu_deleteall">Delete All</string>
<string name="options_menu_uploadall">Upload All</string>
<string name="options_menu_viewsaved">Saved Artefacts</string>
<string name="context_menu_delete">Delete</string>
<string name="context_menu_upload">Upload</string>
<string name="context_menu_view">View</string>
<string name="context_menu_delete">Delete</string>
<string name="pref_upload_url_key">upload.uri</string>
<string name="pref_upload_url_title">Upload URI</string>
<string name="pref_upload_url_summary">Enter the URL to post files to Mahara</string>
<string name="pref_upload_url_default">http://master.dev.mahara.org/artefact/file/mobileupload.php</string>
<string name="pref_upload_username_key">upload.username</string>
<string name="pref_upload_username_title">Username</string>
<string name="pref_upload_username_summary">Enter your Mahara username</string>
<string name="pref_upload_token_key">upload.token</string>
<string name="pref_upload_token_title">Token</string>
<string name="pref_upload_token_summary">Enter your Mahara upload token</string>
<string name="pref_upload_username_key">upload.username</string>
<string name="pref_upload_username_title">Username</string>
<string name="pref_upload_username_summary">Enter your Mahara username</string>
<string name="pref_upload_connection_key">upload.connection</string>
<string name="pref_upload_connection_title">Connection Type</string>
<string name="pref_upload_connection_summary">Restrict artefact upload to the following connection types (default is fall back to handset settings):</string>
<string-array name="pref_upload_connection_entry">
<item>Default</item>
<item>WiFi only</item>
<item>Mobile only</item>
</string-array>
<string-array name="pref_upload_connection_entryValues">
<item></item>
<item>wifi</item>
<item>mobile</item>
</string-array>
<string name="prefcat_advanced">Advanced</string>
......@@ -63,6 +81,7 @@
<string name="uploadnotavailable">Sorry you can only uploaded files as artefacts.</string>
<string name="uploadingartifact">Uploading Artefact</string>
<string name="uploading">Uploading</string>
<string name="uploadnoconnection">Sorry you don\'t have a working data connection to upload at this time.</string>
<string name="filetransfers">File Transfers</string>
<string name="upload_confirm_label">Yes:</string>
......
......@@ -16,6 +16,14 @@
android:key="@string/pref_upload_token_key"
android:title="@string/pref_upload_token_title"
android:summary="@string/pref_upload_token_summary" />
<ListPreference
android:key="@string/pref_upload_connection_key"
android:title="@string/pref_upload_connection_title"
android:summary="@string/pref_upload_connection_summary"
android:defaultValue=""
android:entries="@array/pref_upload_connection_entry"
android:entryValues="@array/pref_upload_connection_entryValues"
android:dialogTitle="@string/pref_upload_connection_title" />
<PreferenceCategory
android:title="@string/prefcat_advanced">
......
package nz.net.catalyst.MaharaDroid;
import java.io.File;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.util.Log;
public class Utils {
static final String TAG = LogConfig.getLogTag(Utils.class);
// whether DEBUG level logging is enabled (whether globally, or explicitly
// for this log tag)
static final boolean DEBUG = LogConfig.isDebug(TAG);
// whether VERBOSE level logging is enabled
static final boolean VERBOSE = LogConfig.VERBOSE;
public static boolean canUpload(Context mContext) {
SharedPreferences mPrefs;
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
boolean allowWiFi = false, allowMobile = false;
String mSetting = mPrefs.getString(mContext.getResources().getString(R.string.pref_upload_connection_key), "");
// Check for no setting - default to phone
if ( mSetting.length() == 0 ) {
allowWiFi = allowMobile = true;
}
if ( mSetting.contains("wifi"))
allowWiFi = true;
if ( mSetting.contains("mobile"))
allowMobile = true;
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
int netType = info.getType();
if (netType == ConnectivityManager.TYPE_WIFI) {
if ( allowWiFi && info.isConnected() )
return true;
} else if (netType == ConnectivityManager.TYPE_MOBILE) {
if ( allowMobile && info.isConnected() )
return true;
}
return false;
}
public static String getFilePath(Context context, String u) {
Uri uri = Uri.parse(u);
String file_path = null;
if ( DEBUG ) Log.d(TAG, "URI = '" + uri.toString() + "', scheme = '" + uri.getScheme() + "'");
if ( uri.getScheme().equals("content") ) {
// Get the filename of the media file and use that as the default title.
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(uri, new String[]{android.provider.MediaStore.MediaColumns.DATA}, null, null, null);
if (cursor != null) {
if ( DEBUG ) Log.d(TAG, "cursor query succeeded");
cursor.moveToFirst();
file_path = cursor.getString(0);
cursor.close();
} else {
if ( DEBUG ) Log.d(TAG, "cursor query failed");
return null;
}
} else {
if ( DEBUG ) Log.d(TAG, "Not content scheme - returning native path");
// Not a content query
file_path = uri.getPath();
File t = new File(file_path);
if ( ! t.exists() )
return null;
}
return file_path;
}
}
......@@ -25,19 +25,20 @@ import java.util.Date;
import nz.net.catalyst.MaharaDroid.LogConfig;
import nz.net.catalyst.MaharaDroid.R;
import nz.net.catalyst.MaharaDroid.R.id;
import nz.net.catalyst.MaharaDroid.R.layout;
import nz.net.catalyst.MaharaDroid.R.menu;
import nz.net.catalyst.MaharaDroid.Utils;
import nz.net.catalyst.MaharaDroid.data.Artefact;
import nz.net.catalyst.MaharaDroid.data.ArtefactDataSQLHelper;
import nz.net.catalyst.MaharaDroid.ui.about.AboutActivity;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.BaseColumns;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
......@@ -77,9 +78,8 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
listview = (ExpandableListView) findViewById(R.id.listView);
listview.setOnChildClickListener(this);
registerForContextMenu(listview);
loadSavedArtefacts();
loadSavedArtefacts();
}
public void onResume() {
super.onResume();
......@@ -89,7 +89,8 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
@Override
public void onDestroy() {
artefactData.close();
if ( artefactData != null )
artefactData.close();
super.onDestroy();
}
......@@ -98,7 +99,9 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
adapter = new ExpandableListAdapter(this, new ArrayList<String>(),
new ArrayList<ArrayList<Artefact>>());
artefactData = new ArtefactDataSQLHelper(this);
if ( artefactData == null )
artefactData = new ArtefactDataSQLHelper(this);
SQLiteDatabase db = artefactData.getReadableDatabase();
Cursor cursor = db.query(ArtefactDataSQLHelper.TABLE, null, null, null, null,
null, null);
......@@ -112,30 +115,57 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
String title = cursor.getString(3);
String description = cursor.getString(4);
String tags = cursor.getString(5);
Artefact a = new Artefact(id, time, filename, title, description, tags);
adapter.addItem(a);
items++;
// TODO: check if file exists
if ( Utils.getFilePath(this, filename) != null ) {
Artefact a = new Artefact(id, time, filename, title, description, tags);
adapter.addItem(a);
items++;
} else {
Log.w(TAG, "Artefact '" + title +
"' file [" + filename +
"] no longer exists, deleting from saved artefacts");
deleteSavedArtefact(id);
}
}
// Set this blank adapter to the list view
if ( items > 0 ) {
listview.setVisibility(View.VISIBLE);
((TextView) findViewById(R.id.no_saved_artefacts)).setVisibility(View.GONE);
} else {
listview.setVisibility(View.GONE);
((TextView) findViewById(R.id.no_saved_artefacts)).setVisibility(View.VISIBLE);
}
// Set this blank adapter to the list view
listview.setAdapter(adapter);
artefactData.close();
// notifiyDataSetChanged triggers the re-draw
adapter.notifyDataSetChanged();
artefactData.close();
return items;
}
private void uploadArtefact(Artefact a, Boolean auto) {
// TODO Auto-generated method stub
Intent i = new Intent(this, ArtifactSettingsActivity.class);
i.putExtra("artefact", (Parcelable) a);
if ( auto )
i.putExtra("auto", "yes please");
startActivity(i);
}
private void viewArtefact(Artefact a) {
if ( DEBUG )
Log.d(TAG, "New intent to view '" + a.getFilename() + "'");
Intent i = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(a.getFilename()));
startActivity(i);
}
private void uploadAllSavedArtefacts() {
// TODO Auto-generated method stub
artefactData = new ArtefactDataSQLHelper(this);
SQLiteDatabase db = artefactData.getReadableDatabase();
if ( artefactData == null )
artefactData = new ArtefactDataSQLHelper(this);
SQLiteDatabase db = artefactData.getReadableDatabase();
Cursor cursor = db.query(ArtefactDataSQLHelper.TABLE, null, null, null, null,
null, null);
......@@ -155,12 +185,16 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
}
//---deletes a particular item---
public boolean deleteSavedArtefact(long id) {
if ( artefactData == null )
artefactData = new ArtefactDataSQLHelper(this);
SQLiteDatabase db = artefactData.getWritableDatabase();
SQLiteDatabase db = artefactData.getWritableDatabase();
return db.delete(ArtefactDataSQLHelper.TABLE, BaseColumns._ID + "=" + id, null) > 0;
}
//---deletes all items---
public boolean deleteAllSavedArtefacts() {
if ( artefactData == null )
artefactData = new ArtefactDataSQLHelper(this);
SQLiteDatabase db = artefactData.getWritableDatabase();
return db.delete(ArtefactDataSQLHelper.TABLE, null, null) > 0;
......@@ -185,6 +219,14 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
uploadAllSavedArtefacts();
loadSavedArtefacts();
break;
case R.id.about:
startActivity(new Intent(this, AboutActivity.class));
break;
case R.id.option_pref:
Intent intent = new Intent(this, EditPreferences.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
break;
}
return true;
}
......@@ -220,6 +262,7 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
children.add(new ArrayList<Artefact>());
}
children.get(index).add(art);
}
@Override
......@@ -314,7 +357,6 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
Artefact a = (Artefact) getChild(groupPosition, childPosition);
uploadArtefact(a, false);
return true;
}
......@@ -324,15 +366,18 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
inflater.inflate(R.menu.context, menu);
}
public boolean onContextItemSelected(MenuItem item) {
Boolean delete = false, upload = false;
Boolean delete = false, upload = false, view = false;
switch (item.getItemId()) {
case R.id.context_delete:
delete = true;
break;
case R.id.context_upload:
upload = true;
break;
case R.id.context_view:
view = true;
break;
case R.id.context_delete:
delete = true;
break;
}
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();
......@@ -341,8 +386,8 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
int childPosition = ExpandableListView.getPackedPositionChild(info.packedPosition);
// Toast.makeText(context, "Child " + childPosition + " clicked in group " + groupPosition,
// Toast.LENGTH_SHORT).show();
if ( DEBUG )
Log.d(TAG, "Child " + childPosition + " clicked in group " + groupPosition);
Artefact a = (Artefact) getChild(groupPosition, childPosition);
......@@ -351,19 +396,24 @@ public class ArtefactExpandableListAdapterActivity extends Activity implements O
loadSavedArtefacts();
} else if ( upload ) {
uploadArtefact(a, true);
} else if ( view ) {
viewArtefact(a);
}
return true;
} else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// String title = ((TextView) info.targetView).getText().toString();
String title = ((TextView) info.targetView).getText().toString();
// Toast.makeText(context, title + ": Group " + groupPosition + " clicked", Toast.LENGTH_SHORT).show();
//
if ( DEBUG )
Log.d(TAG, title + ": Group " + groupPosition + " clicked");
for ( int i = 0; i < getChildrenCount(groupPosition); i++ ) {
Artefact a = (Artefact) getChild(groupPosition, i);
if ( delete ) {
deleteSavedArtefact(a.getId());
} else if ( upload ) {
uploadArtefact(a, true);
} else if ( view ) {
viewArtefact(a);
}
}
if ( delete )
......
......@@ -20,13 +20,14 @@
package nz.net.catalyst.MaharaDroid.ui;
import java.io.File;
import nz.net.catalyst.MaharaDroid.LogConfig;
import nz.net.catalyst.MaharaDroid.R;
import nz.net.catalyst.MaharaDroid.R.id;
import nz.net.catalyst.MaharaDroid.R.layout;
import nz.net.catalyst.MaharaDroid.R.string;
import nz.net.catalyst.MaharaDroid.Utils;
import nz.net.catalyst.MaharaDroid.data.Artefact;
import nz.net.catalyst.MaharaDroid.data.ArtefactDataSQLHelper;
import nz.net.catalyst.MaharaDroid.ui.about.AboutActivity;
import nz.net.catalyst.MaharaDroid.upload.TransferService;
import android.app.Activity;
import android.content.ContentResolver;
......@@ -40,6 +41,9 @@ import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
......@@ -74,6 +78,9 @@ public class ArtifactSettingsActivity extends Activity implements OnClickListene
private String [] uris = null;
private Boolean isMulti = false;
private Button btnUpload;
private Button btnSave;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...