diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..dee7099 --- /dev/null +++ b/app/app.iml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 2e57537..f516866 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "com.example.admin.personallibrarycatalogue" - minSdkVersion 21 + minSdkVersion 16 targetSdkVersion 22 versionCode 1 versionName "1.0" @@ -24,4 +24,5 @@ dependencies { compile 'com.android.support:appcompat-v7:22.1.1' compile 'com.android.support:support-v4:22.1.1' compile 'com.google.android.gms:play-services:7.3.0' + compile(group: 'org.twitter4j', name: 'twitter4j-core', version: '4.0.3') } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 15e3a21..07cd5f8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,8 @@ package="com.example.admin.personallibrarycatalogue" > - + + + + android:label="@string/title_activity_books_list" > + android:launchMode="singleTask" > + + + + + + + + + @@ -33,6 +44,7 @@ android:name=".data.BooksProvider" android:authorities="com.example.admin.personallibrarycatalogue.app" /> + diff --git a/app/src/main/AndroidManifest.xml.orig b/app/src/main/AndroidManifest.xml.orig new file mode 100644 index 0000000..73d1d95 --- /dev/null +++ b/app/src/main/AndroidManifest.xml.orig @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +======= + android:label="@string/title_activity_books_list" + android:launchMode="singleTask" > +>>>>>>> lab_273_content_providers + + + + + + + + + + + diff --git a/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivity.java b/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivity.java index 68eec6f..7153e7e 100644 --- a/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivity.java +++ b/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivity.java @@ -1,6 +1,8 @@ package com.example.admin.personallibrarycatalogue; +import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.ContextMenu; @@ -8,14 +10,20 @@ import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; +import android.widget.EditText; public class BooksListActivity extends ActionBarActivity { + public static Context contextOfApplication; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_books_list); + + contextOfApplication = getApplicationContext(); + if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.fragment, new BooksListActivityFragment()) @@ -23,6 +31,21 @@ protected void onCreate(Bundle savedInstanceState) { } } + public static Context getContextOfApplication(){ + return contextOfApplication; + } + + @Override + public void onResume(){ + super.onResume(); + Uri uri = getIntent().getData(); + if (uri != null && uri.toString().startsWith(ConstantValues.TWITTER_CALLBACK_URL)) { + String verifier = uri.getQueryParameter(ConstantValues.URL_PARAMETER_TWITTER_OAUTH_VERIFIER); + String status = ((BooksListActivityFragment) getSupportFragmentManager().findFragmentById(R.id.fragment)).getStatus(); + new TwitterGetAccessTokenTask().execute(verifier,status); + } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. diff --git a/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivityFragment.java b/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivityFragment.java index c864d5c..64f49f8 100644 --- a/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivityFragment.java +++ b/app/src/main/java/com/example/admin/personallibrarycatalogue/BooksListActivityFragment.java @@ -1,13 +1,25 @@ package com.example.admin.personallibrarycatalogue; +import android.content.ContentValues; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.database.Cursor; +import android.support.v4.app.LoaderManager; +import android.graphics.Color; +import android.os.AsyncTask; +import android.preference.PreferenceManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.net.Uri; import android.support.v4.app.Fragment; import android.os.Bundle; +import android.support.v7.internal.widget.AdapterViewCompat; +import android.text.Editable; +import android.text.TextWatcher; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.MenuInflater; @@ -15,12 +27,21 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; +import android.widget.EditText; import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; import com.example.admin.personallibrarycatalogue.data.Book; import com.example.admin.personallibrarycatalogue.data.DatabaseContract; import com.example.admin.personallibrarycatalogue.data.LibraryDatabaseHelper; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import twitter4j.auth.RequestToken; + /** * The fragment which responsible for showing list of all books @@ -28,10 +49,25 @@ public class BooksListActivityFragment extends Fragment implements android.support.v4.app.LoaderManager.LoaderCallbacks { private static final int LIBRARY_LOADER = 0; - private final static String EXTRA_ID = "id"; + private static final String SPACE = " "; + private static final String I_HAVE_BOOK = "I have book"; + private static final String AND_WANT_TO_LET_KNOW = "and want to let world about it!"; + private final static String ID = "id"; private ListView listView_; + private static String status_ = ""; private BooksListAdapter booksListAdapter_; - private LibraryDatabaseHelper helper_; + + + private static final String[] BOOK_COLUMNS = { + + DatabaseContract.BooksTable.TABLE_NAME + "." + DatabaseContract.BooksTable._ID, + DatabaseContract.BooksTable.TITLE, + DatabaseContract.BooksTable.AUTHOR, + DatabaseContract.BooksTable.DESCRIPTION, + DatabaseContract.BooksTable.COVER, + DatabaseContract.BooksTable.YEAR, + DatabaseContract.BooksTable.ISBN + }; public BooksListActivityFragment() { } @@ -41,7 +77,7 @@ public Loader onCreateLoader(int i, Bundle bundle) { return new CursorLoader( getActivity(), DatabaseContract.BooksTable.CONTENT_URI, - DatabaseContract.BOOK_COLUMNS, + BOOK_COLUMNS, null, null, null @@ -58,15 +94,15 @@ public void onLoaderReset(Loader cursorLoader) { booksListAdapter_.swapCursor(null); } + @Override public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_books_list, container, false); - helper_ = new LibraryDatabaseHelper(getActivity()); listView_ = (ListView) rootView.findViewById(R.id.books_list_view); - booksListAdapter_ = new BooksListAdapter(this.getActivity(), null, 0); + booksListAdapter_ = new BooksListAdapter(getActivity(), null, 0); listView_.setAdapter(booksListAdapter_); // Set ContextMenu for listView @@ -114,6 +150,10 @@ public boolean onContextItemSelected(MenuItem item) { booksListAdapter_.notifyDataSetChanged(); break; + case R.id.share_in_twitter: + statusBuilder(cursor); + launchPrompt(getActivity()); + default: return super.onContextItemSelected(item); } @@ -125,7 +165,7 @@ public boolean onContextItemSelected(MenuItem item) { */ public void updateBook(Book book) { Intent intent = new Intent(getActivity(), AddBookActivity.class); - intent.putExtra(EXTRA_ID, book.getId()); + intent.putExtra(ID, book.getId()); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent); } @@ -136,4 +176,109 @@ public void deleteBook(Book book) { getActivity().getContentResolver().delete(bookWithIdUri, null, null); } + // Returns the typed message + public String getStatus() { + return status_; + } + + public void statusBuilder(Cursor cursor){ + Book book = LibraryDatabaseHelper.getBook(cursor); + status_ = I_HAVE_BOOK + SPACE + book.getTitle() + SPACE + book.getYear() + SPACE + book.getAuthor() + SPACE + AND_WANT_TO_LET_KNOW; + } + + + // Set up subwindow, where user can type the message + public void launchPrompt(Context context) { + LayoutInflater layoutInflater = LayoutInflater.from(context); + View promptView = layoutInflater.inflate(R.layout.prompt, null); + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); + alertDialogBuilder.setView(promptView); + + final TextView info = (TextView)promptView.findViewById(R.id.length_info); + + final EditText inputText = (EditText) promptView.findViewById(R.id.share_input); + inputText.setText(status_); + + inputText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + int accessibleLength = 140 - inputText.getText().toString().length(); + info.setText( Integer.toString(accessibleLength)); + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (!inputText.getText().toString().equalsIgnoreCase("")){ + int accessibleLength = 140 - inputText.getText().toString().length(); + if ((accessibleLength<140)&&(accessibleLength>10)) { + info.setTextColor(Color.GREEN); + info.setText(Integer.toString(accessibleLength)); + } else { + info.setTextColor(Color.RED); + info.setText(Integer.toString(accessibleLength)); + } + + } + } + }); + + + // setup a dialog window + alertDialogBuilder.setCancelable(false) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + + // get user input and set it to result + status_ = (inputText.getText().toString()); + if (status_.length() > 140) { + Toast.makeText(getActivity(), "The length of tweet must be less 140", Toast.LENGTH_LONG).show(); + } else if (status_.length()>0){ + logIn(); + } else Toast.makeText(getActivity(), "Please fill the field", Toast.LENGTH_LONG).show(); + } + }) + .setNegativeButton("Cancel", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + + + // create an alert dialog + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + } + + private void logIn() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); + if (!sharedPreferences.getBoolean(ConstantValues.PREFERENCE_TWITTER_IS_LOGGED_IN, false)) { + new TwitterAuthenticateTask().execute(); + } else { + new TwitterUpdateStatusTask().execute(getStatus()); + } + } + + class TwitterAuthenticateTask extends AsyncTask { + + @Override + protected void onPostExecute(RequestToken requestToken) { + if (requestToken != null) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken.getAuthenticationURL())); + startActivity(intent); + } + } + + @Override + protected RequestToken doInBackground(String... params) { + return TwitterUtil.getInstance().getRequestToken(); + } + } + + } diff --git a/app/src/main/java/com/example/admin/personallibrarycatalogue/ConstantValues.java b/app/src/main/java/com/example/admin/personallibrarycatalogue/ConstantValues.java new file mode 100644 index 0000000..cbf524a --- /dev/null +++ b/app/src/main/java/com/example/admin/personallibrarycatalogue/ConstantValues.java @@ -0,0 +1,15 @@ +package com.example.admin.personallibrarycatalogue; + +/** + * Created by Mikhail Valuyskiy on 08.06.2015. + */ +public class ConstantValues { + public static String TWITTER_CONSUMER_KEY = "RO9WR8PmKG5G8IUFDruZjf4CX"; + public static String TWITTER_CONSUMER_SECRET = "zfXLmbBb1LjrOyugs5nRyxTz0CWbRdv8XPclsXigV3ThH41ZY7"; + public static String TWITTER_CALLBACK_URL = "app://ruswizaradlab.com"; + public static String URL_PARAMETER_TWITTER_OAUTH_VERIFIER = "oauth_verifier"; + public static String PREFERENCE_TWITTER_OAUTH_TOKEN="TWITTER_OAUTH_TOKEN"; + public static String PREFERENCE_TWITTER_OAUTH_TOKEN_SECRET="TWITTER_OAUTH_TOKEN_SECRET"; + public static String PREFERENCE_TWITTER_IS_LOGGED_IN="TWITTER_IS_LOGGED_IN"; + public static String STRING_EXTRA_AUTHENCATION_URL = "AuthencationUrl"; +} diff --git a/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterGetAccessTokenTask.java b/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterGetAccessTokenTask.java new file mode 100644 index 0000000..e599be1 --- /dev/null +++ b/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterGetAccessTokenTask.java @@ -0,0 +1,60 @@ +package com.example.admin.personallibrarycatalogue; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.AsyncTask; +import android.preference.PreferenceManager; + +import twitter4j.Twitter; +import twitter4j.TwitterException; +import twitter4j.auth.AccessToken; +import twitter4j.auth.RequestToken; + +/** + * Created by Mikhail Valuyskiy on 16.06.2015. + */ +class TwitterGetAccessTokenTask extends AsyncTask { + + @Override + protected void onPostExecute(String status) { + new TwitterUpdateStatusTask().execute(status); + } + + @Override + protected String doInBackground(String... params) { + + Context context = BooksListActivity.getContextOfApplication(); + + Twitter twitter = TwitterUtil.getInstance().getTwitter(); + RequestToken requestToken = TwitterUtil.getInstance().getRequestToken(); + if ((params[0]!=null)) { + try { + + AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, params[0]); + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN, accessToken.getToken()); + editor.putString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN_SECRET, accessToken.getTokenSecret()); + editor.putBoolean(ConstantValues.PREFERENCE_TWITTER_IS_LOGGED_IN, true); + editor.commit(); + + return params[1]; + } catch (TwitterException e) { + e.printStackTrace(); + } + } else { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + String accessTokenString = sharedPreferences.getString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN, ""); + String accessTokenSecret = sharedPreferences.getString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN_SECRET, ""); + AccessToken accessToken = new AccessToken(accessTokenString, accessTokenSecret); + try { + TwitterUtil.getInstance().setTwitterFactory(accessToken); + return params[1]; + } catch (Exception e) { + e.printStackTrace(); + } + } + + return null; + } +} diff --git a/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterUpdateStatusTask.java b/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterUpdateStatusTask.java new file mode 100644 index 0000000..26c62c7 --- /dev/null +++ b/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterUpdateStatusTask.java @@ -0,0 +1,50 @@ +package com.example.admin.personallibrarycatalogue; + +/** + * Created by Mikhail Valuyskiy on 16.06.2015. + */ +import android.content.Context; +import android.content.SharedPreferences; +import android.os.AsyncTask; +import android.preference.PreferenceManager; +import android.widget.Toast; + +import twitter4j.TwitterException; +import twitter4j.auth.AccessToken; + +/** + * Created by Mikhail on 15.06.2015. + */ +class TwitterUpdateStatusTask extends AsyncTask { + + @Override + protected void onPostExecute(Boolean result) { + Context context = BooksListActivity.getContextOfApplication(); + if (result) + Toast.makeText(context, "Tweet successfully", Toast.LENGTH_SHORT).show(); + else + Toast.makeText(context, "Tweet failed", Toast.LENGTH_SHORT).show(); + } + + @Override + protected Boolean doInBackground(String... params) { + + Context context = BooksListActivity.getContextOfApplication(); + try { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + String accessTokenString = sharedPreferences.getString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN, ""); + String accessTokenSecret = sharedPreferences.getString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN_SECRET, ""); + + if ((accessTokenString!=null) && accessTokenSecret!=null) { + AccessToken accessToken = new AccessToken(accessTokenString, accessTokenSecret); + twitter4j.Status status = TwitterUtil.getInstance().getTwitterFactory().getInstance(accessToken).updateStatus(params[0]); + return true; + } + + } catch (TwitterException e) { + e.printStackTrace(); + } + return false; + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterUtil.java b/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterUtil.java new file mode 100644 index 0000000..610e53e --- /dev/null +++ b/app/src/main/java/com/example/admin/personallibrarycatalogue/TwitterUtil.java @@ -0,0 +1,63 @@ +package com.example.admin.personallibrarycatalogue; + +import twitter4j.Twitter; +import twitter4j.TwitterException; +import twitter4j.TwitterFactory; +import twitter4j.auth.AccessToken; +import twitter4j.auth.RequestToken; +import twitter4j.conf.ConfigurationBuilder; + +/** + * Created by Mikhail on 15.06.2015. + */ +public final class TwitterUtil { + + private RequestToken requestToken_ = null; + private TwitterFactory twitterFactory_ = null; + private Twitter twitter_; + + private TwitterUtil() { + ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setOAuthConsumerKey(ConstantValues.TWITTER_CONSUMER_KEY); + configurationBuilder.setOAuthConsumerSecret(ConstantValues.TWITTER_CONSUMER_SECRET); + twitter4j.conf.Configuration configuration = configurationBuilder.build(); + twitterFactory_ = new TwitterFactory(configuration); + twitter_ = twitterFactory_.getInstance(); + } + + public TwitterFactory getTwitterFactory() + { + return twitterFactory_; + } + + public void setTwitterFactory(AccessToken accessToken) + { + twitter_ = twitterFactory_.getInstance(accessToken); + } + + public Twitter getTwitter() + { + return twitter_; + } + public RequestToken getRequestToken() { + if (requestToken_ == null) { + try { + requestToken_ = twitterFactory_.getInstance().getOAuthRequestToken(ConstantValues.TWITTER_CALLBACK_URL); + } catch (TwitterException e) { + e.printStackTrace(); + } + } + return requestToken_; + } + + static TwitterUtil instance = new TwitterUtil(); + + public static TwitterUtil getInstance() { + return instance; + } + + + public void reset() { + instance = new TwitterUtil(); + } +} diff --git a/app/src/main/res/layout/prompt.xml b/app/src/main/res/layout/prompt.xml new file mode 100644 index 0000000..67b2127 --- /dev/null +++ b/app/src/main/res/layout/prompt.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/context_menu.xml b/app/src/main/res/menu/context_menu.xml index df07304..13f62af 100644 --- a/app/src/main/res/menu/context_menu.xml +++ b/app/src/main/res/menu/context_menu.xml @@ -12,4 +12,10 @@ android:orderInCategory="100" app:showAsAction="never" /> + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 0bd62bd..723e2e9 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -19,5 +19,4 @@ 0dp 0dp - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8c8271b..bb6075d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,6 +27,12 @@ Menu Edit Delete + Share in twitter + + + Let your friends know what\'s going on! + Please write less then 140 symbols + Title