From 60b1b4234a2da1826c2b4a6ddcd22f480185e696 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Oct 2012 17:01:08 +0400 Subject: implement sync lastread position sharing --- src/org/fox/ttcomics/CommonActivity.java | 47 ++++++++++- src/org/fox/ttcomics/MainActivity.java | 21 ++++- src/org/fox/ttcomics/SyncClient.java | 123 ++++++++++++++++++++++++++++ src/org/fox/ttcomics/ViewComicActivity.java | 40 ++++++++- 4 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 src/org/fox/ttcomics/SyncClient.java (limited to 'src') diff --git a/src/org/fox/ttcomics/CommonActivity.java b/src/org/fox/ttcomics/CommonActivity.java index 0a368b5..f4aa04d 100644 --- a/src/org/fox/ttcomics/CommonActivity.java +++ b/src/org/fox/ttcomics/CommonActivity.java @@ -5,6 +5,8 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Date; +import android.accounts.Account; +import android.accounts.AccountManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -25,7 +27,11 @@ public class CommonActivity extends FragmentActivity { protected static final String FRAG_COMICS_PAGER = "comic_pager"; protected static final String FRAG_COMICS_LIST = "comics_list"; + protected final static int REQUEST_SHARE = 1; + protected static final int REQUEST_VIEWCOMIC = 2; + protected SharedPreferences m_prefs; + protected SyncClient m_syncClient = new SyncClient(); private boolean m_smallScreenMode = true; @@ -34,7 +40,15 @@ public class CommonActivity extends FragmentActivity { super.onCreate(savedInstanceState); m_prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - + + String googleAccount = getGoogleAccount(); + + if (googleAccount != null) { + m_syncClient.setOwner(googleAccount); + } else { + //toast("No Google account found, sync disabled."); + m_syncClient.setOwner("TEST-ACCOUNT"); + } } public static boolean isCompatMode() { @@ -159,6 +173,25 @@ public class CommonActivity extends FragmentActivity { return null; } + protected static String sha1(String s) { + try { + MessageDigest digest = java.security.MessageDigest.getInstance("SHA1"); + digest.update(s.getBytes()); + byte messageDigest[] = digest.digest(); + + StringBuffer hexString = new StringBuffer(); + for (int i=0; i { + protected String m_response = null; + protected int m_responseCode = -1; + + @Override + protected Boolean doInBackground(String... params) { + + String requestStr = "set".equals(params[0]) ? String.format("op=set&owner=%1$s&hash=%2$s&position=%3$s", m_owner, params[1], params[2]) : + String.format("op=get&owner=%1$s&hash=%2$s", m_owner, params[1]); + + try { + byte[] postData = requestStr.getBytes("UTF-8"); + + URL url = new URL(SYNC_ENDPOINT); + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setUseCaches(false); + conn.setRequestMethod("POST"); + + OutputStream out = conn.getOutputStream(); + out.write(postData); + out.close(); + + m_responseCode = conn.getResponseCode(); + + if (m_responseCode == HttpURLConnection.HTTP_OK) { + StringBuffer response = new StringBuffer(); + InputStreamReader in = new InputStreamReader(conn.getInputStream(), "UTF-8"); + + char[] buf = new char[1024]; + int read = 0; + + while ((read = in.read(buf)) >= 0) { + response.append(buf, 0, read); + } + + //Log.d(TAG, "<<< " + response); + + m_response = response.toString(); + + if (response.indexOf("ERROR") == -1) { + return true; + } else { + return false; + } + } else { + Log.d(TAG, "HTTP error, code: " + m_responseCode); + } + + conn.disconnect(); + + } catch (Exception e) { + e.printStackTrace(); + } + + return false; + } + + } + + private final String TAG = this.getClass().getSimpleName(); + private static final String SYNC_ENDPOINT = "http://tt-rss.org/tcrsync/"; + private String m_owner = null; + + public void setOwner(String owner) { + m_owner = CommonActivity.sha1(owner); + } + + public int getPosition(String hash, final PositionReceivedListener listener) { + if (m_owner != null) { + Log.d(TAG, "Requesting sync data..."); + + HttpTask task = new HttpTask() { + @Override + protected void onPostExecute(Boolean result) { + if (result) { + try { + listener.onPositionReceived(Integer.valueOf(m_response)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + }; + + task.execute("get", hash); + + } + return -1; + } + + public void setPosition(String hash, int position) { + if (m_owner != null) { + Log.d(TAG, "Uploading sync data..."); + + HttpTask task = new HttpTask(); + + task.execute("set", hash, String.valueOf(position)); + } + } + + public boolean hasOwner() { + return m_owner != null; + } + +} diff --git a/src/org/fox/ttcomics/ViewComicActivity.java b/src/org/fox/ttcomics/ViewComicActivity.java index 1bd47b5..8693048 100644 --- a/src/org/fox/ttcomics/ViewComicActivity.java +++ b/src/org/fox/ttcomics/ViewComicActivity.java @@ -28,8 +28,6 @@ import android.widget.TextView; public class ViewComicActivity extends CommonActivity { private final String TAG = this.getClass().getSimpleName(); - - private final static int REQUEST_SHARE = 1; private String m_fileName; private String m_tmpFileName; @@ -66,11 +64,15 @@ public class ViewComicActivity extends CommonActivity { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } + } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_view_comic, menu); + + menu.findItem(R.id.menu_sync_location).setVisible(m_prefs.getBoolean("use_position_sync", false) && m_syncClient.hasOwner()); + return true; } @@ -118,7 +120,7 @@ public class ViewComicActivity extends CommonActivity { m_tmpFileName = tmpFile.getAbsolutePath(); - startActivityForResult(Intent.createChooser(shareIntent, "Share comic"), REQUEST_SHARE); + startActivityForResult(Intent.createChooser(shareIntent, getString(R.string.share_comic)), REQUEST_SHARE); } catch (IOException e) { toast(getString(R.string.error_could_not_prepare_file_for_sharing)); @@ -146,6 +148,38 @@ public class ViewComicActivity extends CommonActivity { case R.id.menu_share: shareComic(); return true; + case R.id.menu_sync_location: + m_syncClient.getPosition(sha1(new File(m_fileName).getName()), new SyncClient.PositionReceivedListener() { + @Override + public void onPositionReceived(final int position) { + final ComicPager pager = (ComicPager) getSupportFragmentManager().findFragmentByTag(FRAG_COMICS_PAGER); + + if (pager != null && pager.isAdded()) { + int localPosition = pager.getPosition(); + + if (position > localPosition) { + AlertDialog.Builder builder = new AlertDialog.Builder(ViewComicActivity.this); + builder.setMessage(getString(R.string.sync_server_has_further_page, localPosition+1, position+1)) + .setCancelable(false) + .setPositiveButton(R.string.dialog_open_page, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + pager.setCurrentItem(position); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + AlertDialog alert = builder.create(); + alert.show(); + + } + + } + } + }); + return true; case R.id.menu_go_location: Dialog dialog = new Dialog(ViewComicActivity.this); AlertDialog.Builder builder = new AlertDialog.Builder(ViewComicActivity.this) -- cgit v1.2.3