Browse Source

Add About screen/fragment.

pull/11/head
Eric Kok 12 years ago
parent
commit
6a6250cdf2
  1. 6
      README
  2. BIN
      core/libs/ormlite-android-4.24.jar
  3. BIN
      core/libs/ormlite-core-4.24.jar
  4. BIN
      core/res/drawable-hdpi/ic_action_website.png
  5. BIN
      core/res/drawable-mdpi/ic_action_website.png
  6. BIN
      core/res/drawable-xhdpi/ic_action_website.png
  7. 2
      core/res/layout-w600dp/activity_torrents.xml
  8. 2
      core/res/layout-w720dp/activity_torrents.xml
  9. 8
      core/res/layout/activity_dialogholder.xml
  10. 48
      core/res/layout/fragment_about.xml
  11. 8
      core/res/layout/fragment_details.xml
  12. 3
      core/res/layout/fragment_torrents.xml
  13. 9
      core/res/menu/fragment_about.xml
  14. 5
      core/res/values-sw500dp/bools.xml
  15. 5
      core/res/values/bools.xml
  16. 50
      core/res/values/strings.xml
  17. 13
      core/src/org/transdroid/core/app/settings/ServerSetting.java
  18. 42
      core/src/org/transdroid/core/gui/AboutFragment.java
  19. 2
      core/src/org/transdroid/core/gui/DetailsActivity.java
  20. 24
      core/src/org/transdroid/core/gui/DetailsFragment.java
  21. 4
      core/src/org/transdroid/core/gui/TorrentsActivity.java
  22. 17
      core/src/org/transdroid/core/gui/TorrentsFragment.java
  23. 51
      core/src/org/transdroid/core/gui/log/DatabaseHelper.java
  24. 92
      core/src/org/transdroid/core/gui/log/ErrorLogEntry.java
  25. 73
      core/src/org/transdroid/core/gui/log/ErrorLogSender.java
  26. 54
      core/src/org/transdroid/core/gui/log/Log.java
  27. 53
      core/src/org/transdroid/core/gui/navigation/DialogHolderActivity.java
  28. 28
      core/src/org/transdroid/core/gui/navigation/NavigationHelper.java
  29. 13
      core/src/org/transdroid/core/gui/settings/SystemSettingsActivity.java

6
README

@ -20,6 +20,12 @@ along with Transdroid. If not, see <http://www.gnu.org/licenses/>.
--- ---
Some code/libraries are used in the project: Some code/libraries are used in the project:
ActionBarSherlock
Jake Wharton (Apache License, Version 2.0)
http://actionbarsherlock.com/
AndroidAnnotations
Pierre-Yves Ricau (eBusinessInformations) et al.
http://androidannotations.org/
Base16Encoder (Apache OpenJPA) Base16Encoder (Apache OpenJPA)
Marc Prud'hommeaux (Apache License, Version 2.0) Marc Prud'hommeaux (Apache License, Version 2.0)
MultipartEntity (AOSP) MultipartEntity (AOSP)

BIN
core/libs/ormlite-android-4.24.jar

Binary file not shown.

BIN
core/libs/ormlite-core-4.24.jar

Binary file not shown.

BIN
core/res/drawable-hdpi/ic_action_website.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
core/res/drawable-mdpi/ic_action_website.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
core/res/drawable-xhdpi/ic_action_website.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

2
core/res/layout-w600dp/activity_torrents.xml

@ -8,7 +8,7 @@
android:baselineAligned="false" android:baselineAligned="false"
tools:context=".TorrentsActivity" > tools:context=".TorrentsActivity" >
<ListView <com.actionbarsherlock.view.SherlockListView
android:id="@+id/filters_list" android:id="@+id/filters_list"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="match_parent" android:layout_height="match_parent"

2
core/res/layout-w720dp/activity_torrents.xml

@ -8,7 +8,7 @@
android:baselineAligned="false" android:baselineAligned="false"
tools:context=".TorrentsActivity" > tools:context=".TorrentsActivity" >
<ListView <com.actionbarsherlock.view.SherlockListView
android:id="@+id/filters_list" android:id="@+id/filters_list"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="match_parent" android:layout_height="match_parent"

8
core/res/layout/activity_dialogholder.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This layout is a simple wrapper to display dialogs (which might be show full screen, without border) -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/dialogholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DialogHolderActivity" />

48
core/res/layout/fragment_about.xml

@ -0,0 +1,48 @@
<?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"
android:layout_margin="@dimen/margin_default" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/app_name"
android:textSize="36sp"
android:textColor="@android:color/white"
android:fontFamily="sans-serif-condensed"
android:drawableLeft="@drawable/ic_launcher"
android:drawablePadding="@dimen/margin_half"
android:layout_marginTop="@dimen/margin_half"
android:layout_marginBottom="@dimen/margin_half" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/system_description"
android:gravity="center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/margin_default"
android:text="@string/app_developer"
android:textColor="@android:color/white"
android:textSize="18sp"
android:fontFamily="sans-serif-condensed"
android:gravity="center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4dip"
android:layout_marginBottom="@dimen/margin_default"
android:text="@string/app_license"
android:gravity="center" />
</LinearLayout>

8
core/res/layout/fragment_details.xml

@ -13,6 +13,14 @@
android:dividerHeight="0dip" android:dividerHeight="0dip"
android:visibility="gone" /> android:visibility="gone" />
<ProgressBar
android:id="@+id/loading_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminateDrawable="@drawable/loading_progress"
android:visibility="gone" />
<TextView <TextView
android:id="@+id/empty_text" android:id="@+id/empty_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"

3
core/res/layout/fragment_torrents.xml

@ -16,7 +16,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:indeterminateDrawable="@drawable/loading_progress" /> android:indeterminateDrawable="@drawable/loading_progress"
android:visibility="visible" />
<TextView <TextView
android:id="@+id/empty_text" android:id="@+id/empty_text"

9
core/res/menu/fragment_about.xml

@ -0,0 +1,9 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_visitwebsite"
android:icon="@drawable/ic_action_website"
android:showAsAction="always"
android:title="@string/action_visitwebsite" />
</menu>

5
core/res/values-sw500dp/bools.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Used to determine if a device is 'small', i.e. a phone; for reference: a Nexus 7's smallest width is 533dip -->
<bool name="small_screen">false</bool>
</resources>

5
core/res/values/bools.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Used to determine if a device is 'small', i.e. a phone; for reference: a Nexus 7's smallest width is 533dip -->
<bool name="small_screen">true</bool>
</resources>

50
core/res/values/strings.xml

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name" translatable="false">Transdroid</string>
<string name="action_add">Add</string> <string name="action_add">Add</string>
<string name="action_addfromfile">From file</string> <string name="action_addfromfile">From file</string>
@ -40,6 +38,7 @@
<string name="action_remoteplay">Remote play in VLC</string> <string name="action_remoteplay">Remote play in VLC</string>
<string name="action_download">Download using (S)FTP</string> <string name="action_download">Download using (S)FTP</string>
<string name="action_removesettings">Remove settings</string> <string name="action_removesettings">Remove settings</string>
<string name="action_visitwebsite">Visit transdroid.org</string>
<string name="navigation_nosettings">Transdroid allows you to monitor and manage the torrent client you run at home or on your seedbox. Setting things up can be a bit tricky, but we offer step-by-step guides and promise it\'ll be worth it!</string> <string name="navigation_nosettings">Transdroid allows you to monitor and manage the torrent client you run at home or on your seedbox. Setting things up can be a bit tricky, but we offer step-by-step guides and promise it\'ll be worth it!</string>
<string name="navigation_emptytorrents">Connected, but no torrent are active within the current filter</string> <string name="navigation_emptytorrents">Connected, but no torrent are active within the current filter</string>
@ -179,27 +178,6 @@
<string name="pref_installhelp">View install guides</string> <string name="pref_installhelp">View install guides</string>
<string name="pref_changelog">Recent changes</string> <string name="pref_changelog">Recent changes</string>
<string name="pref_about">About</string> <string name="pref_about">About</string>
<string name="error_httperror">Error during communication; check your connection</string>
<string name="error_jsonrequesterror">Internal error building request</string>
<string name="error_jsonresponseerror">Error parsing server response (please check your settings)</string>
<string name="error_daemonnotconnected">Web interface not connected to a running daemon</string>
<string name="error_401">Access denied (please check your settings)</string>
<string name="error_torrentfile">Can\'t read .torrent file</string>
<string name="error_parsingrss">Error while parsing the RSS feed</string>
<string name="error_invalid_url_form">This URL is not well-formed</string>
<string name="error_invalid_search_url">Your web search URL is invalid:</string>
<string name="error_invalid_ip_or_hostname">Input is not a valid IP address or host name</string>
<string name="error_invalid_port_number">Port number is always numeric</string>
<string name="error_invalid_directory">Directory paths end with a / or \</string>
<string name="error_invalid_timeout">Timeout can not be empty and is a positive number</string>
<string name="error_no_url_enclosure">The RSS feed item didn\'t provide an URL enclosure or link tag pointing to the .torrent file</string>
<string name="error_no_link">The RSS feed item does not provide a link to browse to</string>
<string name="error_norssfeed">URL is not a (valid) RSS feed</string>
<string name="error_media_not_available">SD card not available to read/write</string>
<string name="error_no_valid_settings_file">File does not seem to contain Transdroid settings</string>
<string name="error_file_not_found">There is no settings file found</string>
<string-array name="pref_daemon_types" translatable="false"> <string-array name="pref_daemon_types" translatable="false">
<item>BitComet</item> <item>BitComet</item>
<item>Bitflu 1.2+</item> <item>Bitflu 1.2+</item>
@ -258,5 +236,31 @@
<item>43200</item> <item>43200</item>
<item>86400</item> <item>86400</item>
</string-array> </string-array>
<string name="error_httperror">Error during communication; check your connection</string>
<string name="error_jsonrequesterror">Internal error building request</string>
<string name="error_jsonresponseerror">Error parsing server response (please check your settings)</string>
<string name="error_daemonnotconnected">Web interface not connected to a running daemon</string>
<string name="error_401">Access denied (please check your settings)</string>
<string name="error_torrentfile">Can\'t read .torrent file</string>
<string name="error_parsingrss">Error while parsing the RSS feed</string>
<string name="error_invalid_url_form">This URL is not well-formed</string>
<string name="error_invalid_search_url">Your web search URL is invalid:</string>
<string name="error_invalid_ip_or_hostname">Input is not a valid IP address or host name</string>
<string name="error_invalid_port_number">Port number is always numeric</string>
<string name="error_invalid_directory">Directory paths end with a / or \</string>
<string name="error_invalid_timeout">Timeout can not be empty and is a positive number</string>
<string name="error_no_url_enclosure">The RSS feed item didn\'t provide an URL enclosure or link tag pointing to the .torrent file</string>
<string name="error_no_link">The RSS feed item does not provide a link to browse to</string>
<string name="error_norssfeed">URL is not a (valid) RSS feed</string>
<string name="error_media_not_available">SD card not available to read/write</string>
<string name="error_no_valid_settings_file">File does not seem to contain Transdroid settings</string>
<string name="error_file_not_found">There is no settings file found</string>
<string name="app_name" translatable="false">Transdroid</string>
<string name="app_developer" translatable="false">\u00A9 Eric Kok, 2312 development</string>
<string name="app_license" translatable="false">Published under GNU General Public License v3</string>
<string name="system_description">Manage your torrents from your Android device</string>
<string name="system_libraries">LIBRARIES</string>
</resources> </resources>

13
core/src/org/transdroid/core/app/settings/ServerSetting.java

@ -207,16 +207,23 @@ public class ServerSetting implements SimpleListItem {
// Other objects are never equal to this // Other objects are never equal to this
return false; return false;
} }
/**
* Returns the appropriate daemon adapter to which tasks can be executed, in accordance with this server's settings
* @return An IDaemonAdapter instance of the specific torrent client daemon type
*/
public IDaemonAdapter createServerAdapter() { public IDaemonAdapter createServerAdapter() {
return type.createAdapter(convertToDaemonSettings());
}
private DaemonSettings convertToDaemonSettings() {
// Convert local server settings into an old-style DaemonSetting object // Convert local server settings into an old-style DaemonSetting object
// The local integer key is converted to the idString string // The local integer key is converted to the idString string
// TODO: Add localaddress and localnetwork to DaemonSettings, or solve properly rework the Connect library // TODO: Add localaddress and localnetwork to DaemonSettings, or solve properly rework the Connect library
// handling of settings // handling of settings
DaemonSettings daemonSettings = new DaemonSettings(name, type, address, port, ssl, sslTrustAll, sslTrustKey, return new DaemonSettings(name, type, address, port, ssl, sslTrustAll, sslTrustKey,
folder, useAuthentication, username, password, extraPass, os, downloadDir, ftpUrl, ftpPassword, folder, useAuthentication, username, password, extraPass, os, downloadDir, ftpUrl, ftpPassword,
timeout, alarmOnFinishedDownload, alarmOnNewTorrent, Integer.toString(key), isAutoGenerated); timeout, alarmOnFinishedDownload, alarmOnNewTorrent, Integer.toString(key), isAutoGenerated);
return type.createAdapter(daemonSettings);
} }
} }

42
core/src/org/transdroid/core/gui/AboutFragment.java

@ -0,0 +1,42 @@
package org.transdroid.core.gui;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.OptionsItem;
import org.androidannotations.annotations.OptionsMenu;
import android.app.Dialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Window;
import com.actionbarsherlock.app.SherlockDialogFragment;
/**
* Fragment that shows info about the application developer and used open source libraries.
* @author Eric Kok
*/
@EFragment(resName="fragment_about")
@OptionsMenu(resName="fragment_about")
public class AboutFragment extends SherlockDialogFragment {
@AfterViews
protected void init() {
// TODO: Add list of used open source libraries
}
@OptionsItem(resName="action_visitwebsite")
protected void visitWebsite() {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://transdroid.org")));
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Allow presenting of this fragment as a dialog
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
}

2
core/src/org/transdroid/core/gui/DetailsActivity.java

@ -103,7 +103,9 @@ public class DetailsActivity extends SherlockFragmentActivity implements Torrent
@Background @Background
protected void refreshTorrent() { protected void refreshTorrent() {
fragmentDetails.updateIsLoading(true);
DaemonTaskResult result = RetrieveTask.create(currentConnection).execute(); DaemonTaskResult result = RetrieveTask.create(currentConnection).execute();
fragmentDetails.updateIsLoading(false);
if (result instanceof RetrieveTaskSuccessResult) { if (result instanceof RetrieveTaskSuccessResult) {
onTorrentsRetrieved(((RetrieveTaskSuccessResult) result).getTorrents(), ((RetrieveTaskSuccessResult) result).getLabels()); onTorrentsRetrieved(((RetrieveTaskSuccessResult) result).getTorrents(), ((RetrieveTaskSuccessResult) result).getLabels());
} else { } else {

24
core/src/org/transdroid/core/gui/DetailsFragment.java

@ -18,6 +18,7 @@ import org.transdroid.daemon.TorrentDetails;
import org.transdroid.daemon.TorrentFile; import org.transdroid.daemon.TorrentFile;
import android.view.View; import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragment;
@ -25,7 +26,7 @@ import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.SherlockListView; import com.actionbarsherlock.view.SherlockListView;
/** /**
* Fragment that shown detailed statistics about some torrent. These come from some already fetched {@link Torrent} * Fragment that shows detailed statistics about some torrent. These come from some already fetched {@link Torrent}
* object, but it also retrieves further detailed statistics. * object, but it also retrieves further detailed statistics.
* @author Eric Kok * @author Eric Kok
*/ */
@ -40,12 +41,16 @@ public class DetailsFragment extends SherlockFragment {
protected TorrentDetails torrentDetails = null; protected TorrentDetails torrentDetails = null;
@InstanceState @InstanceState
protected ArrayList<TorrentFile> torrentFiles = null; protected ArrayList<TorrentFile> torrentFiles = null;
@InstanceState
protected boolean isLoadingTorrent = false;
// Views // Views
@ViewById(resName="details_list") @ViewById(resName="details_list")
protected SherlockListView detailsList; protected SherlockListView detailsList;
@ViewById @ViewById
protected TextView emptyText; protected TextView emptyText;
@ViewById
protected ProgressBar loadingProgress;
@AfterViews @AfterViews
protected void init() { protected void init() {
@ -68,9 +73,10 @@ public class DetailsFragment extends SherlockFragment {
clear(); clear();
this.torrent = newTorrent; this.torrent = newTorrent;
((DetailsAdapter) detailsList.getAdapter()).updateTorrent(newTorrent); ((DetailsAdapter) detailsList.getAdapter()).updateTorrent(newTorrent);
// Make the list (with detials header) visible // Make the list (with details header) visible
detailsList.setVisibility(View.VISIBLE); detailsList.setVisibility(View.VISIBLE);
emptyText.setVisibility(View.INVISIBLE); emptyText.setVisibility(isLoadingTorrent? View.INVISIBLE: View.VISIBLE);
loadingProgress.setVisibility(!isLoadingTorrent? View.VISIBLE: View.INVISIBLE);
// Also update the available actions in the action bar // Also update the available actions in the action bar
getActivity().supportInvalidateOptionsMenu(); getActivity().supportInvalidateOptionsMenu();
} }
@ -122,7 +128,17 @@ public class DetailsFragment extends SherlockFragment {
torrentDetails = null; torrentDetails = null;
torrentFiles = null; torrentFiles = null;
} }
/**
* Updates the shown screen depending on whether the torrent is loading
* @param isLoading True if the torrent is (re)loading, false otherwise
*/
public void updateIsLoading(boolean isLoading) {
this.isLoadingTorrent = isLoading;
if (isLoadingTorrent)
clear();
}
@Override @Override
public void onPrepareOptionsMenu(Menu menu) { public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu); super.onPrepareOptionsMenu(menu);

4
core/src/org/transdroid/core/gui/TorrentsActivity.java

@ -19,6 +19,7 @@ import org.transdroid.core.app.settings.ApplicationSettings;
import org.transdroid.core.app.settings.ServerSetting; import org.transdroid.core.app.settings.ServerSetting;
import org.transdroid.core.gui.lists.LocalTorrent; import org.transdroid.core.gui.lists.LocalTorrent;
import org.transdroid.core.gui.lists.SimpleListItem; import org.transdroid.core.gui.lists.SimpleListItem;
import org.transdroid.core.gui.log.Log;
import org.transdroid.core.gui.navigation.*; import org.transdroid.core.gui.navigation.*;
import org.transdroid.core.gui.navigation.NavigationSelectionView.NavigationFilterManager; import org.transdroid.core.gui.navigation.NavigationSelectionView.NavigationFilterManager;
import org.transdroid.core.gui.settings.*; import org.transdroid.core.gui.settings.*;
@ -323,7 +324,9 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
@Background @Background
protected void refreshTorrents() { protected void refreshTorrents() {
fragmentTorrents.updateIsLoading(true);
DaemonTaskResult result = RetrieveTask.create(currentConnection).execute(); DaemonTaskResult result = RetrieveTask.create(currentConnection).execute();
fragmentTorrents.updateIsLoading(false);
if (result instanceof RetrieveTaskSuccessResult) { if (result instanceof RetrieveTaskSuccessResult) {
onTorrentsRetrieved(((RetrieveTaskSuccessResult) result).getTorrents(), ((RetrieveTaskSuccessResult) result).getLabels()); onTorrentsRetrieved(((RetrieveTaskSuccessResult) result).getTorrents(), ((RetrieveTaskSuccessResult) result).getLabels());
} else { } else {
@ -454,6 +457,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
@UiThread @UiThread
protected void onCommunicationError(DaemonTaskFailureResult result) { protected void onCommunicationError(DaemonTaskFailureResult result) {
Log.i(this, result.getException().toString());
// TODO: Properly report this error // TODO: Properly report this error
Toast.makeText(this, getString(LocalTorrent.getResourceForDaemonException(result.getException())), Toast.makeText(this, getString(LocalTorrent.getResourceForDaemonException(result.getException())),
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();

17
core/src/org/transdroid/core/gui/TorrentsFragment.java

@ -7,6 +7,7 @@ import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.InstanceState; import org.androidannotations.annotations.InstanceState;
import org.androidannotations.annotations.ItemClick; import org.androidannotations.annotations.ItemClick;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById; import org.androidannotations.annotations.ViewById;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.gui.lists.*; import org.transdroid.core.gui.lists.*;
@ -172,10 +173,20 @@ public class TorrentsFragment extends SherlockFragment {
this.hasAConnection = hasAConnection; this.hasAConnection = hasAConnection;
if (!hasAConnection) if (!hasAConnection)
clear(); clear();
updateViewVisibility();
} }
private void updateViewVisibility() { /**
* Updates the shown screen depending on whether the torrents are loading
* @param isLoading True if the list of torrents is (re)loading, false otherwise
*/
public void updateIsLoading(boolean isLoading) {
this.isLoading = isLoading;
if (isLoading)
clear();
}
@UiThread
protected void updateViewVisibility() {
if (!hasAConnection) { if (!hasAConnection) {
torrentsList.setVisibility(View.GONE); torrentsList.setVisibility(View.GONE);
emptyText.setVisibility(View.GONE); emptyText.setVisibility(View.GONE);

51
core/src/org/transdroid/core/gui/log/DatabaseHelper.java

@ -0,0 +1,51 @@
package org.transdroid.core.gui.log;
import java.sql.SQLException;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
/**
* Helper to access the database to access persisting objects.
* @author Eric Kok
*/
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "transdroid.db";
private static final int DATABASE_VERSION = 1;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
try {
TableUtils.createTable(connectionSource, ErrorLogEntry.class);
} catch (SQLException e) {
Log.e(org.transdroid.core.gui.log.Log.LOG_NAME, "Could not create new table for ErrorLogEntry", e);
}
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int oldVersion,
int newVersion) {
try {
switch (oldVersion) {
case 1:
TableUtils.createTable(connectionSource, ErrorLogEntry.class);
/*case 1:
etc...*/
}
} catch (SQLException e) {
Log.e(org.transdroid.core.gui.log.Log.LOG_NAME, "Could not upgrade the table for ErrorLogEntry", e);
}
}
}

92
core/src/org/transdroid/core/gui/log/ErrorLogEntry.java

@ -0,0 +1,92 @@
package org.transdroid.core.gui.log;
import java.util.Date;
import android.os.Parcel;
import android.os.Parcelable;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
/**
* Represents an error log entry to be registered in the database.
* @author Eric Kok
*/
@DatabaseTable(tableName = "ErrorLogEntry")
public class ErrorLogEntry implements Parcelable {
public static final String ID = "logId";
public static final String DATEANDTIME = "dateAndTime";
@DatabaseField(id = true, columnName = ID)
private Integer logId;
@DatabaseField(columnName = DATEANDTIME)
private Date dateAndTime;
@DatabaseField
private Integer priority;
@DatabaseField
private String tag;
@DatabaseField
private String message;
public ErrorLogEntry() {
}
public ErrorLogEntry(Integer priority, String tag, String message) {
this.dateAndTime = new Date();
this.priority = priority;
this.tag = tag;
this.message = message;
}
public Integer getLogId() {
return logId;
}
public Date getDateAndTime() {
return dateAndTime;
}
public Integer getPriority() {
return priority;
}
public String getTag() {
return tag;
}
public String getMessage() {
return message;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(logId);
out.writeLong(dateAndTime.getTime());
out.writeInt(priority);
out.writeString(tag);
out.writeString(message);
}
public static final Parcelable.Creator<ErrorLogEntry> CREATOR = new Parcelable.Creator<ErrorLogEntry>() {
public ErrorLogEntry createFromParcel(Parcel in) {
return new ErrorLogEntry(in);
}
public ErrorLogEntry[] newArray(int size) {
return new ErrorLogEntry[size];
}
};
private ErrorLogEntry(Parcel in) {
logId = in.readInt();
dateAndTime = new Date(in.readLong());
priority = in.readInt();
tag = in.readString();
message = in.readString();
}
}

73
core/src/org/transdroid/core/gui/log/ErrorLogSender.java

@ -0,0 +1,73 @@
package org.transdroid.core.gui.log;
import java.sql.SQLException;
import java.util.List;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.OrmLiteDao;
import org.transdroid.core.R;
import org.transdroid.core.app.settings.ServerSetting;
import org.transdroid.core.gui.navigation.NavigationHelper;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import com.j256.ormlite.dao.Dao;
@EBean
public class ErrorLogSender {
@Bean
protected NavigationHelper navigationHelper;
@OrmLiteDao(helper = DatabaseHelper.class, model = ErrorLogEntry.class)
protected Dao<ErrorLogEntry, Integer> errorLogDao;
public void collectAndSendLog(final Activity callingActivity, final ServerSetting serverSetting) {
try {
// Prepare an email with error logging information
StringBuilder body = new StringBuilder();
body.append("Please describe your problem:\n\n\n");
body.append("\n");
body.append(navigationHelper.getAppNameAndVersion());
body.append("\n");
body.append(serverSetting.getType().toString());
body.append(" settings: ");
body.append(serverSetting.getHumanReadableIdentifier());
body.append("\n\nConnection and error log:");
// Print the individual error log messages as stored in the database
List<ErrorLogEntry> all = errorLogDao.queryBuilder().orderBy(ErrorLogEntry.ID, true).query();
for (ErrorLogEntry errorLogEntry : all) {
body.append("\n");
body.append(errorLogEntry.getLogId());
body.append(" -- ");
body.append(errorLogEntry.getDateAndTime());
body.append(" -- ");
body.append(errorLogEntry.getPriority());
body.append(" -- ");
body.append(errorLogEntry.getMessage());
}
Intent target = new Intent(Intent.ACTION_SEND);
target.setType("message/rfc822");
target.putExtra(Intent.EXTRA_EMAIL, new String[] { "transdroid.org@gmail.com" });
target.putExtra(Intent.EXTRA_SUBJECT, "Transdroid error report");
target.putExtra(Intent.EXTRA_TEXT, body.toString());
try {
callingActivity.startActivity(Intent.createChooser(target,
callingActivity.getString(R.string.pref_sendlog)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} catch (ActivityNotFoundException e) {
Log.i(callingActivity, "Tried to send error log, but there is no email app installed.");
}
} catch (SQLException e) {
Log.e(callingActivity, "Cannot read the error log to build an error report to send: " + e.toString());
}
}
}

54
core/src/org/transdroid/core/gui/log/Log.java

@ -0,0 +1,54 @@
package org.transdroid.core.gui.log;
import java.sql.SQLException;
import java.util.Date;
import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.EBean.Scope;
import org.androidannotations.annotations.OrmLiteDao;
import android.content.Context;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.DeleteBuilder;
/**
* Application-wide logging class that registers entries in the database (for a certain time).
* @author Eric Kok
*/
@EBean(scope = Scope.Singleton)
public class Log {
public static final String LOG_NAME = "Transdroid";
private static final long MAX_LOG_AGE = 15 * 60 * 1000; // 15 minutes
@OrmLiteDao(helper = DatabaseHelper.class, model = ErrorLogEntry.class)
Dao<ErrorLogEntry, Integer> errorLogDao;
protected void log(String logName, int priority, String message) {
android.util.Log.println(priority, LOG_NAME, message);
try {
// Store this log message to the database
errorLogDao.create(new ErrorLogEntry(priority, logName, message));
// Truncate the error log
DeleteBuilder<ErrorLogEntry, Integer> db = errorLogDao.deleteBuilder();
db.setWhere(db.where().le(ErrorLogEntry.DATEANDTIME, new Date(new Date().getTime() - MAX_LOG_AGE)));
errorLogDao.delete(db.prepare());
} catch (SQLException e) {
android.util.Log.e(LOG_NAME, "Cannot write log message to database: " + e.toString());
}
}
public static void e(Context caller, String message) {
Log_.getInstance_(caller).log(caller.getClass().toString(), android.util.Log.ERROR, message);
}
public static void i(Context caller, String message) {
Log_.getInstance_(caller).log(caller.getClass().toString(), android.util.Log.INFO, message);
}
public static void d(Context caller, String message) {
Log_.getInstance_(caller).log(caller.getClass().toString(), android.util.Log.DEBUG, message);
}
}

53
core/src/org/transdroid/core/gui/navigation/DialogHolderActivity.java

@ -0,0 +1,53 @@
package org.transdroid.core.gui.navigation;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
import org.transdroid.core.gui.log.Log;
import android.content.Context;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentTransaction;
import com.actionbarsherlock.app.SherlockFragmentActivity;
@EActivity(resName = "activity_dialogholder")
public class DialogHolderActivity extends SherlockFragmentActivity {
@Extra
protected String dialogType;
/**
* Use this method to show some dialog; it will show the dialog as full screen fragment on smaller devices. Use the
* DialogFragment's class here only; a new instance will be created by this holder activity.
*/
public static void showDialog(Context context, Class<? extends DialogFragment> dialogType) {
DialogHolderActivity_.intent(context).start();
}
@AfterViews
public void init() {
try {
// Instantiate an instance of the requested dialog
DialogFragment dialog = (DialogFragment) Class.forName(dialogType).newInstance();
// Determine if the dialog should be shown as full size screen
boolean isSmall = NavigationHelper_.getInstance_(this).isSmallScreen();
if (!isSmall) {
// Show as normal dialog
dialog.show(this.getSupportFragmentManager(), "about_dialog");
} else {
// Small device, so show the fragment full screen
FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
// Note: the fragment is not added to the back stack, as this activity already is
ft.add(android.R.id.content, dialog).commit();
}
} catch (InstantiationException e) {
Log.e(this, "Tried to show a dialog of type " + dialogType + ", but that cannot be instantiated.");
} catch (IllegalAccessException e) {
Log.e(this, "Tried to show a dialog of type " + dialogType + ", but it is not accessible.");
} catch (ClassNotFoundException e) {
Log.e(this, "Tried to show a dialog of type " + dialogType + ", but that class doesn't exist.");
}
}
}

28
core/src/org/transdroid/core/gui/navigation/NavigationHelper.java

@ -2,9 +2,12 @@ package org.transdroid.core.gui.navigation;
import org.androidannotations.annotations.EBean; import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.RootContext; import org.androidannotations.annotations.RootContext;
import org.transdroid.core.R;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build; import android.os.Build;
@EBean @EBean
@ -13,6 +16,31 @@ public class NavigationHelper {
@RootContext @RootContext
protected Context context; protected Context context;
/**
* Whether any search-related UI components should be shown in the interface. At the moment returns false only if we
* run as Transdroid Lite version.
* @return True if search is enabled, false otherwise
*/
public String getAppNameAndVersion() {
String appName = context.getString(R.string.app_name);
try {
PackageInfo m = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return appName + " " + m.versionName + " (" + m.versionCode + ")";
} catch (NameNotFoundException e) {
return appName;
}
}
/**
* Returns whether the device is considered small (i.e. a phone) rather than large (i.e. a tablet). Can, for example,
* be used to determine if a dialog should be shown full screen. Currently is true if the device's smallest
* dimension is 500 dip.
* @return True if the app runs on a small device, false otherwise
*/
public boolean isSmallScreen() {
return context.getResources().getBoolean(R.bool.small_screen);
}
/** /**
* Whether any search-related UI components should be shown in the interface. At the moment returns false only if we * Whether any search-related UI components should be shown in the interface. At the moment returns false only if we
* run as Transdroid Lite version. * run as Transdroid Lite version.

13
core/src/org/transdroid/core/gui/settings/SystemSettingsActivity.java

@ -4,12 +4,16 @@ import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.EActivity;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.app.settings.ApplicationSettings; import org.transdroid.core.app.settings.ApplicationSettings;
import org.transdroid.core.gui.AboutFragment;
import org.transdroid.core.gui.log.ErrorLogSender;
import org.transdroid.core.gui.navigation.DialogHolderActivity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference; import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener; import android.preference.Preference.OnPreferenceClickListener;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockPreferenceActivity; import com.actionbarsherlock.app.SherlockPreferenceActivity;
@ -20,6 +24,8 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity {
@Bean @Bean
protected ApplicationSettings applicationSettings; protected ApplicationSettings applicationSettings;
@Bean
protected ErrorLogSender errorLogSender;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
@ -39,7 +45,7 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity {
private OnPreferenceClickListener onSendLogClick = new OnPreferenceClickListener() { private OnPreferenceClickListener onSendLogClick = new OnPreferenceClickListener() {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
// TODO: Implement error log collection and sending errorLogSender.collectAndSendLog(SystemSettingsActivity.this, applicationSettings.getLastUsedServer());
return true; return true;
} }
}; };
@ -55,7 +61,8 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity {
private OnPreferenceClickListener onChangeLogClick = new OnPreferenceClickListener() { private OnPreferenceClickListener onChangeLogClick = new OnPreferenceClickListener() {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
// TODO: Implement about change log screen // TODO: Implement change log screen
Toast.makeText(SystemSettingsActivity.this, "TODO: Implement change log screen", Toast.LENGTH_LONG).show();
return true; return true;
} }
}; };
@ -63,7 +70,7 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity {
private OnPreferenceClickListener onAboutClick = new OnPreferenceClickListener() { private OnPreferenceClickListener onAboutClick = new OnPreferenceClickListener() {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
// TODO: Implement about screen with app version, developer name and used open source libraries DialogHolderActivity.showDialog(SystemSettingsActivity.this, AboutFragment.class);
return true; return true;
} }
}; };

Loading…
Cancel
Save