diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3f9edd0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,32 @@
+# built application files
+*.apk
+*.ap_
+.gradle/
+build/
+
+# files for the dex VM
+*.dex
+
+# Java class files
+*.class
+
+# generated files
+bin/
+gen/
+out/
+target/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Eclipse project files
+.classpath
+.project
+
+# Idea IDE files
+*.idea/
+*.iml
+
+*.DS_STORE
+
+custom_env.gradle
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..70224f9
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1,3 @@
+/build
+/src/androidTest
+/src/test
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..fde28da
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,59 @@
+apply plugin: 'com.android.application'
+apply plugin: 'com.neenbedankt.android-apt'
+
+android {
+ compileSdkVersion 24
+ buildToolsVersion "23.0.3"
+
+ defaultConfig {
+ applicationId "com.bobrusha.android.artists"
+ minSdkVersion 14
+ targetSdkVersion 24
+ versionCode 1
+ versionName "1.0"
+ }
+ signingConfigs {
+ release {
+ storeFile file('/Users/aleksandra/AndroidStudioProjects/Artists/app/my-release-key.keystore')
+ storePassword "qwerty"
+ keyAlias "mobilization"
+ keyPassword "qwerty"
+ }
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ signingConfig signingConfigs.release
+ }
+ }
+}
+
+repositories {
+ mavenCentral()
+ jcenter()
+ maven { url "https://clojars.org/repo/" }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:24.1.1'
+ compile 'com.android.support:recyclerview-v7:24.1.1'
+ compile 'com.android.support:design:24.1.1'
+ compile 'com.android.support:support-v4:24.1.1'
+ compile 'com.android.support:preference-v7:24.1.1'
+ compile 'com.android.support:preference-v14:24.1.1'
+ compile 'com.squareup.okhttp3:okhttp:3.2.0'
+ compile 'com.squareup.picasso:picasso:2.5.2'
+
+ compile 'com.jakewharton:butterknife:8.2.1'
+ apt 'com.jakewharton:butterknife-compiler:8.2.1'
+
+ provided 'frankiesardo:auto-parcel:1.0.1'
+ apt 'frankiesardo:auto-parcel:1.0.3'
+
+ compile 'com.fasterxml.jackson.core:jackson-core:2.8.1'
+ compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.1'
+ compile 'com.fasterxml.jackson.core:jackson-databind:2.8.1'
+}
diff --git a/app/my-release-key.keystore b/app/my-release-key.keystore
new file mode 100644
index 0000000..b3acb5a
Binary files /dev/null and b/app/my-release-key.keystore differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..fa1fc1d
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/aleksandra/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5efae56..800439d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
@@ -22,13 +23,6 @@
-
-
-
diff --git a/app/src/main/java/com/bobrusha/android/artists/ArtistDetailActivity.java b/app/src/main/java/com/bobrusha/android/artists/ArtistDetailActivity.java
deleted file mode 100644
index df34236..0000000
--- a/app/src/main/java/com/bobrusha/android/artists/ArtistDetailActivity.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.bobrusha.android.artists;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.text.TextUtils;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.bobrusha.android.artists.model.ArtistInfo;
-import com.squareup.picasso.Callback;
-import com.squareup.picasso.Picasso;
-
-/**
- * Activity with detailed information about chosen musician.
- *
- * @author Aleksandra Bobrova
- */
-public class ArtistDetailActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.activity_artist_detail);
- Intent intent = getIntent();
- ArtistInfo artistInfo = intent.getParcelableExtra(Constants.EXTRA_ARTIST);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setTitle(artistInfo.getName());
- actionBar.setDisplayHomeAsUpEnabled(true);
- }
-
- final ImageView imageView = (ImageView) findViewById(R.id.artist_detail_big_img);
- Picasso.with(imageView.getContext())
- .load(artistInfo.getCover().getBig())
- .into(imageView, new Callback() {
- @Override
- public void onSuccess() {
- imageView.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onError() {
- //Stop progressBar and show text
- findViewById(R.id.progress_bar).setVisibility(View.INVISIBLE);
- findViewById(R.id.artist_detail_no_image).setVisibility(View.VISIBLE);
-
- }
- });
-
- TextView genreTextView = (TextView) findViewById(R.id.artist_detail_genre_text);
- genreTextView.setText(TextUtils.join(", ", artistInfo.getGenres()));
-
- TextView albumsAndTracksTextView = (TextView) findViewById(R.id.artist_detail_albums_and_tracks);
- String pattern = getString(R.string.artist_detail_albums_and_tracks);
- albumsAndTracksTextView.setText(
- String.format(pattern, artistInfo.getAlbums(), artistInfo.getTracks())
- );
-
- TextView textOfBiographyTextView = (TextView) findViewById(R.id.artist_detail_biography_text);
- textOfBiographyTextView.setText(artistInfo.getDescription());
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-}
diff --git a/app/src/main/java/com/bobrusha/android/artists/ArtistInfoLoader.java b/app/src/main/java/com/bobrusha/android/artists/ArtistInfoLoader.java
index 5e7deed..6bc0e8c 100644
--- a/app/src/main/java/com/bobrusha/android/artists/ArtistInfoLoader.java
+++ b/app/src/main/java/com/bobrusha/android/artists/ArtistInfoLoader.java
@@ -1,11 +1,13 @@
package com.bobrusha.android.artists;
import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
import android.support.v4.content.AsyncTaskLoader;
+import com.bobrusha.android.artists.db.DBManager;
import com.bobrusha.android.artists.model.ArtistInfo;
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;
@@ -21,12 +23,8 @@
* @author Aleksandra Bobrova
*/
public class ArtistInfoLoader extends AsyncTaskLoader> {
- private static final String URL = "http://cache-default04f.cdn.yandex.net/download.cdn.yandex.net/mobilization-2016/artists.json";
+ private static final String URL = "http://download.cdn.yandex.net/mobilization-2016/artists.json";
private OkHttpClient client = new OkHttpClient();
- private Gson mGson = new Gson();
-
- private TypeToken> artists = new TypeToken>() {
- };
public ArtistInfoLoader(Context context) {
super(context);
@@ -54,8 +52,15 @@ public List loadInBackground() {
try {
response = client.newCall(request).execute();
ResponseBody responseBody = response.body();
- List artistInfoList = mGson.fromJson(responseBody.charStream(), artists.getType());
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ List artistInfoList = objectMapper.readValue(responseBody.charStream(), new TypeReference>() {
+ });
+
responseBody.close();
+
+ SQLiteDatabase db = MyApplication.getDbHelper().getWritableDatabase();
+ DBManager.putArtists(db, artistInfoList);
return artistInfoList;
} catch (IOException e) {
e.printStackTrace();
diff --git a/app/src/main/java/com/bobrusha/android/artists/BusProvider.java b/app/src/main/java/com/bobrusha/android/artists/BusProvider.java
deleted file mode 100644
index acf881a..0000000
--- a/app/src/main/java/com/bobrusha/android/artists/BusProvider.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.bobrusha.android.artists;
-
-import com.squareup.otto.Bus;
-
-/**
- * Class for providing instance of Bus.
- *
- * @author Aleksandra Bobrova
- * @see Bus
- */
-public class BusProvider {
- private static final Bus mInstance = new Bus();
-
- private BusProvider() {
- }
-
- public static Bus getInstance() {
- return mInstance;
- }
-}
diff --git a/app/src/main/java/com/bobrusha/android/artists/CacheLoader.java b/app/src/main/java/com/bobrusha/android/artists/CacheLoader.java
new file mode 100644
index 0000000..60a95d2
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/CacheLoader.java
@@ -0,0 +1,45 @@
+package com.bobrusha.android.artists;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.support.v4.content.AsyncTaskLoader;
+import android.util.Log;
+
+import com.bobrusha.android.artists.db.Contract;
+import com.bobrusha.android.artists.db.DBManager;
+import com.bobrusha.android.artists.model.ArtistInfo;
+import com.bobrusha.android.artists.model.Cover;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by Aleksandra on 20/07/16.
+ */
+public class CacheLoader extends AsyncTaskLoader> {
+
+ public CacheLoader(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onStartLoading() {
+ super.onStartLoading();
+ forceLoad();
+ }
+
+ @Override
+ public List loadInBackground() {
+ SQLiteDatabase db = MyApplication.getDbHelper().getReadableDatabase();
+ Cursor c = db.query(Contract.ArtistEntry.TABLE_NAME, null, null, null, null, null, null, null);
+ List artists = new ArrayList<>();
+ for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
+ artists.add(DBManager.getArtistFromCursor(c));
+ }
+ c.close();
+ return artists;
+ }
+
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/Constants.java b/app/src/main/java/com/bobrusha/android/artists/Constants.java
index 0d17407..1c8363b 100644
--- a/app/src/main/java/com/bobrusha/android/artists/Constants.java
+++ b/app/src/main/java/com/bobrusha/android/artists/Constants.java
@@ -1,7 +1,6 @@
package com.bobrusha.android.artists;
/**
- *
* @author Aleksandra Bobrova
*/
@@ -10,6 +9,7 @@ public interface Constants {
String PACKAGE_NAME_PREFIX = "com.bobrusha.android.artists.";
String EXTRA_ARTIST = PACKAGE_NAME_PREFIX + "artist";
- int ARTIST_INFO_LOADER_ID = 1;
+ int ARTIST_INFO_LOADER_ID = 10;
+ int CACHE_LOADER_ID = 20;
}
diff --git a/app/src/main/java/com/bobrusha/android/artists/MainActivity.java b/app/src/main/java/com/bobrusha/android/artists/MainActivity.java
deleted file mode 100644
index c498549..0000000
--- a/app/src/main/java/com/bobrusha/android/artists/MainActivity.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.bobrusha.android.artists;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.Loader;
-import android.support.v4.widget.SwipeRefreshLayout;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-
-import com.bobrusha.android.artists.recycler_view.ArtistPreviewAdapter;
-import com.bobrusha.android.artists.recycler_view.DividerItemDecoration;
-import com.bobrusha.android.artists.event.ArtistPreviewOnClickEvent;
-import com.bobrusha.android.artists.model.ArtistInfo;
-import com.squareup.otto.Subscribe;
-
-import java.util.List;
-
-/**
- * Main Activity for showing list of musicians.
- *
- * @author Aleksandra Bobrova
- */
-public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks> {
-
- private RecyclerView.Adapter mAdapter;
- private SwipeRefreshLayout mSwipeRefreshLayout;
- private Snackbar mSnackbar;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view_artists);
- recyclerView.setLayoutManager(new LinearLayoutManager(this));
-
- mAdapter = new ArtistPreviewAdapter();
- recyclerView.setAdapter(mAdapter);
-
- recyclerView.addItemDecoration(new DividerItemDecoration(this, R.drawable.divider));
-
- mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_layout);
- mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
- @Override
- public void onRefresh() {
- getSupportLoaderManager().restartLoader(Constants.ARTIST_INFO_LOADER_ID, null, MainActivity.this);
- mSwipeRefreshLayout.setRefreshing(false);
- }
- });
-
- getSupportLoaderManager().initLoader(Constants.ARTIST_INFO_LOADER_ID, null, this);
- }
-
- @Override
- public Loader> onCreateLoader(int id, Bundle args) {
- return new ArtistInfoLoader(this);
- }
-
- @Override
- public void onLoadFinished(Loader> loader, List data) {
- ((ArtistPreviewAdapter) mAdapter).setDataset(data);
- mSwipeRefreshLayout.setRefreshing(false);
-
- // Show snackBar if no data was loaded
- if (data == null) {
- if (mSnackbar == null) {
- mSnackbar = Snackbar.make(findViewById(R.id.refresh_layout),
- R.string.no_data_to_display,
- Snackbar.LENGTH_INDEFINITE);
- }
- mSnackbar.show();
- } else {
- if (mSnackbar != null) {
- mSnackbar.dismiss();
- }
- }
- }
-
- @Override
- public void onLoaderReset(Loader> loader) {
-
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- BusProvider.getInstance().register(this);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- BusProvider.getInstance().unregister(this);
- }
-
- /**
- * Method that calling then user chose musician.
- *
- * @param event – event for method invocation using Bus.
- */
- @Subscribe
- public void onArtistSelected(ArtistPreviewOnClickEvent event) {
- Intent intent = new Intent(this, ArtistDetailActivity.class);
- ArtistInfo artistInfo = event.getArtistInfo();
- intent.putExtra(Constants.EXTRA_ARTIST, artistInfo);
- startActivity(intent);
- }
-}
diff --git a/app/src/main/java/com/bobrusha/android/artists/MyApplication.java b/app/src/main/java/com/bobrusha/android/artists/MyApplication.java
new file mode 100644
index 0000000..1d2d3b5
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/MyApplication.java
@@ -0,0 +1,23 @@
+package com.bobrusha.android.artists;
+
+import android.app.Application;
+
+import com.bobrusha.android.artists.db.MyDbHelper;
+
+/**
+ * Created by Aleksandra on 20/07/16.
+ */
+public class MyApplication extends Application {
+ private static MyDbHelper dbHelper;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ dbHelper = new MyDbHelper(this);
+ }
+
+ public static MyDbHelper getDbHelper() {
+ return dbHelper;
+ }
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/db/Contract.java b/app/src/main/java/com/bobrusha/android/artists/db/Contract.java
new file mode 100644
index 0000000..95c42d4
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/db/Contract.java
@@ -0,0 +1,22 @@
+package com.bobrusha.android.artists.db;
+
+import android.provider.BaseColumns;
+
+/**
+ * Created by Aleksandra on 20/07/16.
+ */
+public final class Contract {
+
+ public static abstract class ArtistEntry implements BaseColumns {
+ public static final String TABLE_NAME = "artist";
+ public static final String COLUMN_NAME_ARTIST_ID = "artist_id";
+ public static final String COLUMN_NAME_ARTIST_NAME = "artist_name";
+ public static final String COLUMN_NAME_GENRES = "genres";
+ public static final String COLUMN_NAME_TRACKS = "amount_of_tracks";
+ public static final String COLUMN_NAME_ALBUMS = "amount_of_albums";
+ public static final String COLUMN_NAME_LINK = "link";
+ public static final String COLUMN_NAME_DESCRIPTION = "description";
+ public static final String COLUMN_NAME_COVER_SMALL = "cover_small";
+ public static final String COLUMN_NAME_COVER_BIG = "cover_big";
+ }
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/db/DBManager.java b/app/src/main/java/com/bobrusha/android/artists/db/DBManager.java
new file mode 100644
index 0000000..99a4137
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/db/DBManager.java
@@ -0,0 +1,77 @@
+package com.bobrusha.android.artists.db;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.text.TextUtils;
+
+import com.bobrusha.android.artists.model.ArtistInfo;
+import com.bobrusha.android.artists.model.Cover;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by Aleksandra on 20/07/16.
+ */
+public class DBManager {
+
+
+ public static void putArtist(SQLiteDatabase db, ArtistInfo artist) {
+ ContentValues values = new ContentValues();
+ values.put(Contract.ArtistEntry.COLUMN_NAME_ARTIST_ID, artist.id());
+ values.put(Contract.ArtistEntry.COLUMN_NAME_ARTIST_NAME, artist.name());
+ values.put(Contract.ArtistEntry.COLUMN_NAME_GENRES, TextUtils.join(", ", artist.genres()));
+ values.put(Contract.ArtistEntry.COLUMN_NAME_TRACKS, artist.tracks());
+ values.put(Contract.ArtistEntry.COLUMN_NAME_ALBUMS, artist.albums());
+ values.put(Contract.ArtistEntry.COLUMN_NAME_LINK, artist.link());
+ values.put(Contract.ArtistEntry.COLUMN_NAME_DESCRIPTION, artist.description());
+ values.put(Contract.ArtistEntry.COLUMN_NAME_COVER_BIG, artist.cover().getBig());
+ values.put(Contract.ArtistEntry.COLUMN_NAME_COVER_SMALL, artist.cover().getSmall());
+
+ String selection = Contract.ArtistEntry.COLUMN_NAME_ARTIST_ID + " LIKE ?";
+ String[] selectionArgs = {String.valueOf(artist.id())};
+
+ int count = db.update(
+ Contract.ArtistEntry.TABLE_NAME,
+ values,
+ selection,
+ selectionArgs);
+
+ if (count == 0) {
+ db.insert(Contract.ArtistEntry.TABLE_NAME, null, values);
+ }
+ }
+
+
+ public static void putArtists(SQLiteDatabase db, List artists) {
+ for (ArtistInfo artist : artists) {
+ putArtist(db, artist);
+ }
+
+ Cursor c = db.query(Contract.ArtistEntry.TABLE_NAME, null, null, null, null, null, null);
+ }
+
+
+ public static ArtistInfo getArtistFromCursor(Cursor c) {
+ String[] genres = c.getString(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_GENRES)).split(", ", -1);
+
+ Cover cover = new Cover();
+ cover.setSmall(c.getString(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_COVER_SMALL)));
+ cover.setBig(c.getString(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_COVER_BIG)));
+
+ ArtistInfo artistInfo = ArtistInfo.builder()
+ .id(c.getLong(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_ARTIST_ID)))
+ .name(c.getString(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_ARTIST_NAME)))
+ .genres(Arrays.asList(genres))
+ .tracks(c.getLong(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_TRACKS)))
+ .albums(c.getLong(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_ALBUMS)))
+ .link(c.getString(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_LINK)))
+ .description(c.getString(c.getColumnIndex(Contract.ArtistEntry.COLUMN_NAME_DESCRIPTION)))
+ .cover(cover)
+ .build();
+
+ return artistInfo;
+ }
+
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/db/MyDbHelper.java b/app/src/main/java/com/bobrusha/android/artists/db/MyDbHelper.java
new file mode 100644
index 0000000..458cbc2
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/db/MyDbHelper.java
@@ -0,0 +1,51 @@
+package com.bobrusha.android.artists.db;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+/**
+ * Created by Aleksandra on 20/07/16.
+ */
+public class MyDbHelper extends SQLiteOpenHelper {
+ public static final int DATABASE_VERSION = 1;
+ public static final String DATABASE_NAME = "Artists.db";
+
+ private static final String TEXT_TYPE = " TEXT";
+ private static final String INTEGER_TYPE = " INTEGER";
+ private static final String SEP = ", ";
+ private static final String CREATE_DB = "CREATE TABLE " + Contract.ArtistEntry.TABLE_NAME +
+ " (" + Contract.ArtistEntry._ID + " INTEGER PRIMARY KEY " + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_ARTIST_ID + INTEGER_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_ARTIST_NAME + TEXT_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_GENRES + TEXT_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_TRACKS + INTEGER_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_ALBUMS + INTEGER_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_LINK + TEXT_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_DESCRIPTION + TEXT_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_COVER_BIG + TEXT_TYPE + SEP +
+ Contract.ArtistEntry.COLUMN_NAME_COVER_SMALL + TEXT_TYPE +
+ " )";
+
+ private static final String SQL_DELETE_ENTRIES =
+ "DROP TABLE IF EXISTS " + Contract.ArtistEntry.TABLE_NAME;
+
+
+ public MyDbHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase sqLiteDatabase) {
+ sqLiteDatabase.execSQL(CREATE_DB);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
+ sqLiteDatabase.execSQL(SQL_DELETE_ENTRIES);
+ onCreate(sqLiteDatabase);
+ }
+
+
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/event/ArtistPreviewOnClickEvent.java b/app/src/main/java/com/bobrusha/android/artists/event/ArtistPreviewOnClickEvent.java
index 1e337ef..378ea45 100644
--- a/app/src/main/java/com/bobrusha/android/artists/event/ArtistPreviewOnClickEvent.java
+++ b/app/src/main/java/com/bobrusha/android/artists/event/ArtistPreviewOnClickEvent.java
@@ -9,13 +9,13 @@
* @see com.squareup.otto.Bus
*/
public class ArtistPreviewOnClickEvent {
- private final ArtistInfo mArtistInfo;
+ private final ArtistInfo artistInfo;
public ArtistPreviewOnClickEvent(ArtistInfo artistInfo) {
- mArtistInfo = artistInfo;
+ this.artistInfo = artistInfo;
}
public ArtistInfo getArtistInfo() {
- return mArtistInfo;
+ return artistInfo;
}
}
diff --git a/app/src/main/java/com/bobrusha/android/artists/model/ArtistInfo.java b/app/src/main/java/com/bobrusha/android/artists/model/ArtistInfo.java
index 4e8f7ed..eb1a8da 100644
--- a/app/src/main/java/com/bobrusha/android/artists/model/ArtistInfo.java
+++ b/app/src/main/java/com/bobrusha/android/artists/model/ArtistInfo.java
@@ -1,7 +1,13 @@
package com.bobrusha.android.artists.model;
-import android.os.Parcel;
import android.os.Parcelable;
+import android.support.annotation.Nullable;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import com.google.auto.value.AutoValue;
import java.util.List;
@@ -10,113 +16,89 @@
*
* @author Aleksandra Bobrova
*/
-public class ArtistInfo implements Parcelable {
- private long id;
- private String name;
- private List genres;
- private long tracks;
- private long albums;
- private String link;
- private String description;
- private Cover cover;
-
- public ArtistInfo() {
- }
+@AutoValue
+@JsonDeserialize(builder = AutoValue_ArtistInfo.Builder.class)
+public abstract class ArtistInfo implements Parcelable {
- protected ArtistInfo(Parcel in) {
- id = in.readLong();
- name = in.readString();
- genres = in.createStringArrayList();
- tracks = in.readLong();
- albums = in.readLong();
- link = in.readString();
- description = in.readString();
- cover = new Cover();
- cover.big = in.readString();
- cover.small = in.readString();
+ public static Builder builder() {
+ return new AutoValue_ArtistInfo.Builder();
}
- public static final Creator CREATOR = new Creator() {
- @Override
- public ArtistInfo createFromParcel(Parcel in) {
- return new ArtistInfo(in);
- }
-
- @Override
- public ArtistInfo[] newArray(int size) {
- return new ArtistInfo[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
+ public static ArtistInfo create(@JsonProperty("id") long id,
+ @JsonProperty("name") String name,
+ @JsonProperty("genres") List genres,
+ @JsonProperty("tracks") long tracks,
+ @JsonProperty("albums") long albums,
+ @JsonProperty("link") @Nullable String link,
+ @JsonProperty("description") String description,
+ @JsonProperty("cover") Cover cover) {
+ return builder().id(id)
+ .name(name)
+ .genres(genres)
+ .tracks(tracks)
+ .albums(albums)
+ .link(link)
+ .description(description)
+ .cover(cover)
+ .build();
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(id);
- dest.writeString(name);
- dest.writeStringList(genres);
- dest.writeLong(tracks);
- dest.writeLong(albums);
- dest.writeString(link);
- dest.writeString(description);
- dest.writeString(cover.big);
- dest.writeString(cover.small);
}
- public class Cover {
- private String small;
- private String big;
+ // Properties
+ @JsonProperty("id")
+ public abstract long id();
- public Cover() {
- }
+ @JsonProperty("name")
+ public abstract String name();
- public String getSmall() {
- return small;
- }
+ @JsonProperty("genres")
+ public abstract List genres();
- public String getBig() {
- return big;
- }
- }
+ @JsonProperty("tracks")
+ public abstract long tracks();
+ @JsonProperty("albums")
+ public abstract long albums();
- @Override
- public String toString() {
- return "ArtistInfo{" +
- "id=" + id +
- ", name='" + name + '\'' +
- ", genres=" + genres +
- ", albums=" + albums +
- ", link='" + link + '\'' +
- ", description='" + description + '\'' +
- ", cover=" + cover +
- '}';
- }
+ @JsonProperty("link")
+ @Nullable
+ public abstract String link();
- public String getName() {
- return name;
- }
+ @JsonProperty("description")
+ public abstract String description();
- public List getGenres() {
- return genres;
- }
+ @JsonProperty("cover")
+ public abstract Cover cover();
- public Cover getCover() {
- return cover;
- }
- public long getAlbums() {
- return albums;
- }
+ @AutoValue.Builder
+ @JsonPOJOBuilder(withPrefix = "")
+ public static abstract class Builder {
+ @JsonProperty("id")
+ public abstract Builder id(long id);
- public String getDescription() {
- return description;
- }
+ @JsonProperty("name")
+ public abstract Builder name(String name);
+
+ @JsonProperty("genres")
+ public abstract Builder genres(List genres);
+
+ @JsonProperty("tracks")
+ public abstract Builder tracks(long tracks);
+
+ @JsonProperty("albums")
+ public abstract Builder albums(long albums);
+
+ @JsonProperty("link")
+ public abstract Builder link(String link);
+
+ @JsonProperty("description")
+ public abstract Builder description(String description);
+
+ @JsonProperty("cover")
+ public abstract Builder cover(Cover cover);
- public long getTracks() {
- return tracks;
+ @JsonCreator
+ public abstract ArtistInfo build();
}
}
diff --git a/app/src/main/java/com/bobrusha/android/artists/model/Cover.java b/app/src/main/java/com/bobrusha/android/artists/model/Cover.java
new file mode 100644
index 0000000..45b6afe
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/model/Cover.java
@@ -0,0 +1,28 @@
+package com.bobrusha.android.artists.model;
+
+/**
+ * Created by Aleksandra on 20/07/16.
+ */
+public class Cover {
+ private String small;
+ private String big;
+
+ public Cover() {
+ }
+
+ public String getSmall() {
+ return small;
+ }
+
+ public String getBig() {
+ return big;
+ }
+
+ public void setSmall(String small) {
+ this.small = small;
+ }
+
+ public void setBig(String big) {
+ this.big = big;
+ }
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/receiver/MusicIntentReceiver.java b/app/src/main/java/com/bobrusha/android/artists/receiver/MusicIntentReceiver.java
new file mode 100644
index 0000000..eeab705
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/receiver/MusicIntentReceiver.java
@@ -0,0 +1,74 @@
+package com.bobrusha.android.artists.receiver;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+import android.support.v7.app.NotificationCompat;
+
+import com.bobrusha.android.artists.R;
+
+/**
+ * Created by Aleksandra on 03/08/16.
+ */
+public class MusicIntentReceiver extends BroadcastReceiver {
+ private static final String OPEN_IN_MARKET = "market://details?id=";
+ private static final String YA_MUSIC_PACKAGE_NAME = "ru.yandex.music";
+ private static final String YA_RADIO_PACKAGE_NAME = "ru.yandex.radio";
+ private static final int NOTIFICATION_ID = 1;
+
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(AudioManager.ACTION_HEADSET_PLUG)) {
+ int state = intent.getIntExtra("state", -1);
+
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ switch (state) {
+ case 0:
+ notificationManager.cancel(NOTIFICATION_ID);
+ break;
+ case 1:
+ NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context);
+ notificationBuilder.setContentTitle(context.getString(R.string.notification_title))
+ .setContentText(context.getString(R.string.notification_text))
+ .setSmallIcon(R.drawable.ic_earphones);
+
+ createAction(context, notificationBuilder, YA_MUSIC_PACKAGE_NAME,
+ R.drawable.ic_note, R.drawable.ic_download, R.string.open_ya_music);
+ createAction(context, notificationBuilder, YA_RADIO_PACKAGE_NAME,
+ R.drawable.ic_radio, R.drawable.ic_download, R.string.open_ya_radio);
+
+ Notification notification =
+ (new NotificationCompat.BigTextStyle(notificationBuilder)).bigText(
+ context.getString(R.string.notification_text)
+ ).build();
+ notificationManager.notify(NOTIFICATION_ID, notification);
+ break;
+ }
+ }
+ }
+
+ public void createAction(Context context, NotificationCompat.Builder builder, String packageName,
+ @DrawableRes int icOpen, @DrawableRes int icDownload, @StringRes int name) {
+ PackageManager manager = context.getPackageManager();
+ Intent intent = manager.getLaunchIntentForPackage(packageName);
+ if (intent != null) {
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
+ builder.addAction(icOpen, context.getString(name), pi);
+ } else {
+ PendingIntent pi = PendingIntent.getActivity(context, 0, new Intent(
+ Intent.ACTION_VIEW, Uri.parse(OPEN_IN_MARKET + packageName)), 0);
+ builder.addAction(icDownload, context.getString(name), pi);
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewAdapter.java b/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewAdapter.java
index 391ddc9..700c73b 100644
--- a/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewAdapter.java
+++ b/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewAdapter.java
@@ -1,5 +1,6 @@
package com.bobrusha.android.artists.recycler_view;
+import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -7,37 +8,47 @@
import com.bobrusha.android.artists.R;
import com.bobrusha.android.artists.model.ArtistInfo;
+import com.bobrusha.android.artists.ui.MainActivity;
import java.util.List;
/**
- *
* @author Aleksandra Bobrova
*/
public class ArtistPreviewAdapter extends RecyclerView.Adapter {
- private List mDataset;
-
+ private List dataset;
@Override
public ArtistPreviewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.artist_preview, parent, false);
- return new ArtistPreviewViewHolder(v);
+ final View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.artist_preview, parent, false);
+ final ArtistPreviewViewHolder h = new ArtistPreviewViewHolder(v);
+ v.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int adapterPosition = h.getAdapterPosition();
+ if (adapterPosition != RecyclerView.NO_POSITION) {
+ final Context context = view.getContext();
+ if (context instanceof MainActivity) {
+ ((MainActivity) context).onArtistSelected(dataset.get(adapterPosition));
+ }
+ }
+ }
+ });
+ return h;
}
@Override
public void onBindViewHolder(ArtistPreviewViewHolder holder, int position) {
- if (position < mDataset.size()) {
- holder.bind(mDataset.get(position));
- }
+ holder.bind(dataset.get(position));
}
@Override
public int getItemCount() {
- return mDataset == null ? 0 : mDataset.size();
+ return dataset == null ? 0 : dataset.size();
}
public void setDataset(List dataset) {
- mDataset = dataset;
+ this.dataset = dataset;
notifyDataSetChanged();
}
}
diff --git a/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewViewHolder.java b/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewViewHolder.java
index 4d2f3fa..8da7887 100644
--- a/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewViewHolder.java
+++ b/app/src/main/java/com/bobrusha/android/artists/recycler_view/ArtistPreviewViewHolder.java
@@ -1,56 +1,52 @@
package com.bobrusha.android.artists.recycler_view;
-import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
-import com.bobrusha.android.artists.BusProvider;
import com.bobrusha.android.artists.R;
-import com.bobrusha.android.artists.event.ArtistPreviewOnClickEvent;
import com.bobrusha.android.artists.model.ArtistInfo;
import com.squareup.picasso.Picasso;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
/**
- *
* @author Aleksandra Bobrova
*/
public class ArtistPreviewViewHolder extends RecyclerView.ViewHolder {
- private final Context context;
- private final TextView mArtistNameView;
- private final TextView mGenreTextView;
- private final TextView mAlbumsTextView;
- private final ImageView mImageView;
+ @BindView(R.id.preview_artist_name)
+ TextView artistNameView;
+
+ @BindView(R.id.preview_artist_genre)
+ TextView genreTextView;
+
+ @BindView(R.id.preview_artist_albums)
+ TextView albumsTextView;
+
+ @BindView(R.id.preview_artist_img)
+ ImageView coverImageView;
public ArtistPreviewViewHolder(View itemView) {
super(itemView);
- context = itemView.getContext();
- mArtistNameView = (TextView) itemView.findViewById(R.id.preview_artist_name);
- mGenreTextView = (TextView) itemView.findViewById(R.id.preview_artist_genre);
- mAlbumsTextView = (TextView) itemView.findViewById(R.id.preview_artist_albums);
- mImageView = (ImageView) itemView.findViewById(R.id.preview_artist_img);
+ ButterKnife.bind(this, itemView);
}
public void bind(final ArtistInfo artistInfo) {
- mArtistNameView.setText(artistInfo.getName());
-
- String genres = TextUtils.join(", ", artistInfo.getGenres());
- mGenreTextView.setText(genres);
+ artistNameView.setText(artistInfo.name());
- String pattern = context.getString(R.string.amount_of_albums_and_tracks);
- mAlbumsTextView.setText(String.format(pattern, artistInfo.getAlbums(), artistInfo.getTracks()));
+ if (artistInfo.genres() != null) {
+ String genres = TextUtils.join(", ", artistInfo.genres());
+ genreTextView.setText(genres);
+ }
- Picasso.with(context)
- .load(artistInfo.getCover().getSmall())
- .into(mImageView);
+ String pattern = artistNameView.getContext().getString(R.string.amount_of_albums_and_tracks);
+ albumsTextView.setText(String.format(pattern, artistInfo.albums(), artistInfo.tracks()));
- itemView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- BusProvider.getInstance().post(new ArtistPreviewOnClickEvent(artistInfo));
- }
- });
+ Picasso.with(coverImageView.getContext())
+ .load(artistInfo.cover().getSmall())
+ .into(coverImageView);
}
}
diff --git a/app/src/main/java/com/bobrusha/android/artists/recycler_view/DividerItemDecoration.java b/app/src/main/java/com/bobrusha/android/artists/recycler_view/DividerItemDecoration.java
index 92debe4..05b8968 100644
--- a/app/src/main/java/com/bobrusha/android/artists/recycler_view/DividerItemDecoration.java
+++ b/app/src/main/java/com/bobrusha/android/artists/recycler_view/DividerItemDecoration.java
@@ -14,10 +14,10 @@
* @author Aleksandra Bobrova
*/
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
- private final Drawable mDivider;
+ private final Drawable divider;
public DividerItemDecoration(Context context, int dividerId) {
- mDivider = ContextCompat.getDrawable(context, dividerId);
+ divider = ContextCompat.getDrawable(context, dividerId);
}
@Override
@@ -28,7 +28,7 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
return;
}
- outRect.top = mDivider.getIntrinsicHeight();
+ outRect.top = divider.getIntrinsicHeight();
}
@Override
@@ -42,10 +42,10 @@ public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state)
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int dividerTop = child.getBottom() + params.bottomMargin;
- int dividerBottom = dividerTop + mDivider.getIntrinsicHeight();
+ int dividerBottom = dividerTop + divider.getIntrinsicHeight();
- mDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
- mDivider.draw(canvas);
+ divider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
+ divider.draw(canvas);
}
}
}
diff --git a/app/src/main/java/com/bobrusha/android/artists/ui/MainActivity.java b/app/src/main/java/com/bobrusha/android/artists/ui/MainActivity.java
new file mode 100644
index 0000000..43e1a4e
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/ui/MainActivity.java
@@ -0,0 +1,152 @@
+package com.bobrusha.android.artists.ui;
+
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.design.widget.NavigationView;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+
+import com.bobrusha.android.artists.Constants;
+import com.bobrusha.android.artists.R;
+import com.bobrusha.android.artists.model.ArtistInfo;
+import com.bobrusha.android.artists.receiver.MusicIntentReceiver;
+import com.bobrusha.android.artists.ui.fragment.AboutFragment;
+import com.bobrusha.android.artists.ui.fragment.ArtistDetailFragment;
+import com.bobrusha.android.artists.ui.fragment.MainFragment;
+import com.bobrusha.android.artists.ui.fragment.SettingsFragment;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+
+/**
+ * Main Activity for managing fragments.
+ *
+ * @author Aleksandra Bobrova
+ */
+public class MainActivity extends AppCompatActivity {
+ @BindView(R.id.nvView)
+ NavigationView navigationView;
+
+ @BindView(R.id.drawer_layout)
+ DrawerLayout drawerLayout;
+
+ @BindView(R.id.toolbar)
+ Toolbar toolbar;
+
+ private ActionBarDrawerToggle drawerToggle;
+
+ private MusicIntentReceiver receiver;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ if (savedInstanceState == null) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.add(R.id.container_for_fragment, new MainFragment());
+ transaction.commit();
+ }
+
+ ButterKnife.bind(this);
+ setSupportActionBar(toolbar);
+ setupDrawerContent(navigationView);
+
+ drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
+ R.string.drawer_open, R.string.drawer_close);
+ drawerLayout.addDrawerListener(drawerToggle);
+
+ receiver = new MusicIntentReceiver();
+ }
+
+ @Override
+ protected void onPostCreate(@Nullable Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ drawerToggle.syncState();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
+ registerReceiver(receiver, filter);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ unregisterReceiver(receiver);
+ }
+
+
+ /**
+ * Method that calling then user chose musician.
+ *
+ * @param artistInfo - object with information for detailed fragment.
+ */
+ public void onArtistSelected(ArtistInfo artistInfo) {
+ ArtistDetailFragment fragment = new ArtistDetailFragment();
+ Bundle args = new Bundle();
+ args.putParcelable(Constants.EXTRA_ARTIST, artistInfo);
+ fragment.setArguments(args);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.container_for_fragment, fragment);
+ transaction.addToBackStack(null);
+ transaction.commit();
+ }
+
+ private void setupDrawerContent(NavigationView navigationView) {
+ navigationView.setNavigationItemSelectedListener(
+ new NavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(MenuItem menuItem) {
+ selectDrawerItem(menuItem);
+ return true;
+ }
+ });
+ }
+
+ private void selectDrawerItem(MenuItem menuItem) {
+ Fragment fragment;
+
+ switch (menuItem.getItemId()) {
+ case R.id.nav_home:
+ fragment = new MainFragment();
+ break;
+ case R.id.nav_settings:
+ fragment = new SettingsFragment();
+ break;
+ case R.id.nav_about_program:
+ fragment = new AboutFragment();
+ break;
+ default:
+ fragment = new MainFragment();
+ }
+
+ drawerLayout.closeDrawers();
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ fragmentManager.beginTransaction().replace(R.id.container_for_fragment, fragment).commit();
+ menuItem.setChecked(true);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (drawerToggle.onOptionsItemSelected(item)) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/ui/fragment/AboutFragment.java b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/AboutFragment.java
new file mode 100644
index 0000000..80a6d53
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/AboutFragment.java
@@ -0,0 +1,57 @@
+package com.bobrusha.android.artists.ui.fragment;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.bobrusha.android.artists.R;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+
+/**
+ * Created by Aleksandra on 16/07/16.
+ */
+public class AboutFragment extends Fragment {
+ private static final String EMAIL_TO = "bobrova.aleksand@gmail.com";
+ private static final String EMAIL_SUBJECT = "Artists app";
+ private static final String EMAIL_TYPE = "message/rfc822";
+
+ private static final Intent intent = new Intent(Intent.ACTION_SEND)
+ .setType(EMAIL_TYPE)
+ .putExtra(Intent.EXTRA_EMAIL, new String[]{EMAIL_TO})
+ .putExtra(Intent.EXTRA_SUBJECT, EMAIL_SUBJECT);
+
+ @BindView(R.id.btn_send_email_to_devs)
+ Button sendToButton;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.fragment_about, container, false);
+ ButterKnife.bind(this, v);
+ return v;
+
+ }
+
+ @OnClick(R.id.btn_send_email_to_devs)
+ public void onSendEmailClick() {
+ try {
+ startActivity(Intent.createChooser(intent, getString(R.string.send_email_chooser)));
+ } catch (ActivityNotFoundException ex) {
+ Snackbar snackbar = Snackbar.make(getActivity().findViewById(R.id.refresh_layout),
+ getString(R.string.no_email_client),
+ Snackbar.LENGTH_SHORT);
+ snackbar.show();
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/ui/fragment/ArtistDetailFragment.java b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/ArtistDetailFragment.java
new file mode 100644
index 0000000..9dbb99b
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/ArtistDetailFragment.java
@@ -0,0 +1,87 @@
+package com.bobrusha.android.artists.ui.fragment;
+
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.bobrusha.android.artists.Constants;
+import com.bobrusha.android.artists.R;
+import com.bobrusha.android.artists.model.ArtistInfo;
+import com.squareup.picasso.Callback;
+import com.squareup.picasso.Picasso;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+/**
+ * Created by Aleksandra on 15/07/16.
+ */
+public class ArtistDetailFragment extends Fragment {
+ private ArtistInfo artist;
+
+ @BindView(R.id.artist_detail_genre_text)
+ TextView genre;
+
+ @BindView(R.id.artist_detail_albums_and_tracks)
+ TextView albumsAndTracks;
+
+ @BindView(R.id.artist_detail_biography_text)
+ TextView bio;
+
+ @BindView(R.id.artist_detail_big_img)
+ ImageView imageView;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Bundle args = getArguments();
+ artist = args.getParcelable(Constants.EXTRA_ARTIST);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ final View v = inflater.inflate(R.layout.fragment_artist_detail, container, false);
+ ButterKnife.bind(this, v);
+
+ imageView = (ImageView) v.findViewById(R.id.artist_detail_big_img);
+ Picasso.with(imageView.getContext())
+ .load(artist.cover().getBig())
+ .into(imageView, new Callback() {
+ @Override
+ public void onSuccess() {
+ imageView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onError() {
+ //Stop progressBar and show image
+ v.findViewById(R.id.progress_bar).setVisibility(View.INVISIBLE);
+ v.findViewById(R.id.artist_detail_no_image).setVisibility(View.VISIBLE);
+
+ }
+ });
+
+ genre = (TextView) v.findViewById(R.id.artist_detail_genre_text);
+ genre.setText(TextUtils.join(", ", artist.genres()));
+
+ albumsAndTracks = (TextView) v.findViewById(R.id.artist_detail_albums_and_tracks);
+ String pattern = getString(R.string.artist_detail_albums_and_tracks);
+ albumsAndTracks.setText(
+ String.format(pattern, artist.albums(), artist.tracks())
+ );
+
+ bio = (TextView) v.findViewById(R.id.artist_detail_biography_text);
+ bio.setText(artist.description());
+
+ return v;
+ }
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/ui/fragment/MainFragment.java b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/MainFragment.java
new file mode 100644
index 0000000..0ed118f
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/MainFragment.java
@@ -0,0 +1,127 @@
+package com.bobrusha.android.artists.ui.fragment;
+
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.Loader;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.bobrusha.android.artists.ArtistInfoLoader;
+import com.bobrusha.android.artists.CacheLoader;
+import com.bobrusha.android.artists.Constants;
+import com.bobrusha.android.artists.R;
+import com.bobrusha.android.artists.model.ArtistInfo;
+import com.bobrusha.android.artists.recycler_view.ArtistPreviewAdapter;
+import com.bobrusha.android.artists.recycler_view.DividerItemDecoration;
+
+import java.util.List;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+public class MainFragment extends Fragment implements LoaderManager.LoaderCallbacks> {
+ private List newData;
+
+ @BindView(R.id.recycler_view_artists)
+ RecyclerView recyclerView;
+
+ @BindView(R.id.refresh_layout)
+ SwipeRefreshLayout swipeRefreshLayout;
+
+ private ArtistPreviewAdapter adapter;
+ private Snackbar snackbar;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.fragment_main, container, false);
+ ButterKnife.bind(this, v);
+
+ recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+
+ adapter = new ArtistPreviewAdapter();
+ recyclerView.setAdapter(adapter);
+
+ recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), R.drawable.divider));
+
+ swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ getActivity().getSupportLoaderManager()
+ .restartLoader(Constants.ARTIST_INFO_LOADER_ID, null, MainFragment.this);
+ getActivity().getSupportLoaderManager()
+ .restartLoader(Constants.CACHE_LOADER_ID, null, MainFragment.this);
+
+ swipeRefreshLayout.setRefreshing(false);
+ }
+ });
+
+ return v;
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ getLoaderManager().initLoader(Constants.ARTIST_INFO_LOADER_ID, null, this);
+ getLoaderManager().initLoader(Constants.CACHE_LOADER_ID, null, this);
+ }
+
+ @Override
+ public Loader> onCreateLoader(int id, Bundle args) {
+ switch (id) {
+ case Constants.ARTIST_INFO_LOADER_ID:
+ newData = null;
+ return new ArtistInfoLoader(getActivity());
+ case Constants.CACHE_LOADER_ID:
+ return new CacheLoader(getActivity());
+ }
+ return null;
+ }
+
+ @Override
+ public void onLoadFinished(Loader> loader, List data) {
+ swipeRefreshLayout.setRefreshing(false);
+
+ if (loader.getId() == Constants.CACHE_LOADER_ID && newData == null) {
+ adapter.setDataset(data);
+ return;
+ }
+
+ // Show snackBar if no data was loaded
+ if (data == null || data.isEmpty()) {
+ if (newData != null && !newData.isEmpty()) {
+ adapter.setDataset(newData);
+ } else {
+ if (snackbar == null) {
+ snackbar = Snackbar.make(swipeRefreshLayout,
+ R.string.no_data_to_display,
+ Snackbar.LENGTH_INDEFINITE);
+ }
+ snackbar.show();
+ }
+ } else {
+ if (loader.getId() == Constants.ARTIST_INFO_LOADER_ID) {
+ newData = data;
+ }
+ adapter.setDataset(data);
+ if (snackbar != null) {
+ snackbar.dismiss();
+ }
+ }
+
+ }
+
+ @Override
+ public void onLoaderReset(Loader> loader) {
+
+ }
+}
diff --git a/app/src/main/java/com/bobrusha/android/artists/ui/fragment/SettingsFragment.java b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/SettingsFragment.java
new file mode 100644
index 0000000..775710c
--- /dev/null
+++ b/app/src/main/java/com/bobrusha/android/artists/ui/fragment/SettingsFragment.java
@@ -0,0 +1,18 @@
+package com.bobrusha.android.artists.ui.fragment;
+
+import android.os.Bundle;
+import android.support.v7.preference.PreferenceFragmentCompat;
+
+
+import com.bobrusha.android.artists.R;
+
+/**
+ * Created by Aleksandra on 19/07/16.
+ */
+public class SettingsFragment extends PreferenceFragmentCompat {
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ addPreferencesFromResource(R.xml.settings);
+ }
+}
diff --git a/app/src/main/res/drawable-hdpi-v11/ic_download.png b/app/src/main/res/drawable-hdpi-v11/ic_download.png
new file mode 100644
index 0000000..0524b00
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v11/ic_download.png differ
diff --git a/app/src/main/res/drawable-hdpi-v11/ic_earphones.png b/app/src/main/res/drawable-hdpi-v11/ic_earphones.png
new file mode 100644
index 0000000..7e49b9f
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v11/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-hdpi-v11/ic_note.png b/app/src/main/res/drawable-hdpi-v11/ic_note.png
new file mode 100644
index 0000000..c6ddd05
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v11/ic_note.png differ
diff --git a/app/src/main/res/drawable-hdpi-v11/ic_radio.png b/app/src/main/res/drawable-hdpi-v11/ic_radio.png
new file mode 100644
index 0000000..639e059
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v11/ic_radio.png differ
diff --git a/app/src/main/res/drawable-hdpi-v9/ic_download.png b/app/src/main/res/drawable-hdpi-v9/ic_download.png
new file mode 100644
index 0000000..ddbd0ce
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v9/ic_download.png differ
diff --git a/app/src/main/res/drawable-hdpi-v9/ic_earphones.png b/app/src/main/res/drawable-hdpi-v9/ic_earphones.png
new file mode 100644
index 0000000..6470fb7
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v9/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-hdpi-v9/ic_note.png b/app/src/main/res/drawable-hdpi-v9/ic_note.png
new file mode 100644
index 0000000..dc961e5
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v9/ic_note.png differ
diff --git a/app/src/main/res/drawable-hdpi-v9/ic_radio.png b/app/src/main/res/drawable-hdpi-v9/ic_radio.png
new file mode 100644
index 0000000..00867a2
Binary files /dev/null and b/app/src/main/res/drawable-hdpi-v9/ic_radio.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_download.png b/app/src/main/res/drawable-hdpi/ic_download.png
new file mode 100644
index 0000000..9f1d8ad
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_download.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_earphones.png b/app/src/main/res/drawable-hdpi/ic_earphones.png
new file mode 100644
index 0000000..d8db6f3
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_note.png b/app/src/main/res/drawable-hdpi/ic_note.png
new file mode 100644
index 0000000..05a8648
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_note.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_radio.png b/app/src/main/res/drawable-hdpi/ic_radio.png
new file mode 100644
index 0000000..2a51a84
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_radio.png differ
diff --git a/app/src/main/res/drawable-mdpi-v11/ic_download.png b/app/src/main/res/drawable-mdpi-v11/ic_download.png
new file mode 100644
index 0000000..a119cd4
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v11/ic_download.png differ
diff --git a/app/src/main/res/drawable-mdpi-v11/ic_earphones.png b/app/src/main/res/drawable-mdpi-v11/ic_earphones.png
new file mode 100644
index 0000000..743719c
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v11/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-mdpi-v11/ic_note.png b/app/src/main/res/drawable-mdpi-v11/ic_note.png
new file mode 100644
index 0000000..9f5929e
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v11/ic_note.png differ
diff --git a/app/src/main/res/drawable-mdpi-v11/ic_radio.png b/app/src/main/res/drawable-mdpi-v11/ic_radio.png
new file mode 100644
index 0000000..b2a0100
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v11/ic_radio.png differ
diff --git a/app/src/main/res/drawable-mdpi-v9/ic_download.png b/app/src/main/res/drawable-mdpi-v9/ic_download.png
new file mode 100644
index 0000000..49d494d
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v9/ic_download.png differ
diff --git a/app/src/main/res/drawable-mdpi-v9/ic_earphones.png b/app/src/main/res/drawable-mdpi-v9/ic_earphones.png
new file mode 100644
index 0000000..0dd64ed
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v9/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-mdpi-v9/ic_note.png b/app/src/main/res/drawable-mdpi-v9/ic_note.png
new file mode 100644
index 0000000..4fc43d3
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v9/ic_note.png differ
diff --git a/app/src/main/res/drawable-mdpi-v9/ic_radio.png b/app/src/main/res/drawable-mdpi-v9/ic_radio.png
new file mode 100644
index 0000000..b581a2a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi-v9/ic_radio.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_download.png b/app/src/main/res/drawable-mdpi/ic_download.png
new file mode 100644
index 0000000..acd09cb
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_download.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_earphones.png b/app/src/main/res/drawable-mdpi/ic_earphones.png
new file mode 100644
index 0000000..19e6f23
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_note.png b/app/src/main/res/drawable-mdpi/ic_note.png
new file mode 100644
index 0000000..6c87df6
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_note.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_radio.png b/app/src/main/res/drawable-mdpi/ic_radio.png
new file mode 100644
index 0000000..1c94109
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_radio.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v11/ic_download.png b/app/src/main/res/drawable-xhdpi-v11/ic_download.png
new file mode 100644
index 0000000..180bdcd
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v11/ic_download.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v11/ic_earphones.png b/app/src/main/res/drawable-xhdpi-v11/ic_earphones.png
new file mode 100644
index 0000000..60c608e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v11/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v11/ic_note.png b/app/src/main/res/drawable-xhdpi-v11/ic_note.png
new file mode 100644
index 0000000..70a17a3
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v11/ic_note.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v11/ic_radio.png b/app/src/main/res/drawable-xhdpi-v11/ic_radio.png
new file mode 100644
index 0000000..e6fe62d
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v11/ic_radio.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v9/ic_download.png b/app/src/main/res/drawable-xhdpi-v9/ic_download.png
new file mode 100644
index 0000000..6313634
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v9/ic_download.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v9/ic_earphones.png b/app/src/main/res/drawable-xhdpi-v9/ic_earphones.png
new file mode 100644
index 0000000..456b28c
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v9/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v9/ic_note.png b/app/src/main/res/drawable-xhdpi-v9/ic_note.png
new file mode 100644
index 0000000..68f839a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v9/ic_note.png differ
diff --git a/app/src/main/res/drawable-xhdpi-v9/ic_radio.png b/app/src/main/res/drawable-xhdpi-v9/ic_radio.png
new file mode 100644
index 0000000..c38eef8
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi-v9/ic_radio.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_download.png b/app/src/main/res/drawable-xhdpi/ic_download.png
new file mode 100644
index 0000000..024442a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_download.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_earphones.png b/app/src/main/res/drawable-xhdpi/ic_earphones.png
new file mode 100644
index 0000000..5e4c3b4
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_note.png b/app/src/main/res/drawable-xhdpi/ic_note.png
new file mode 100644
index 0000000..9118a25
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_note.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_radio.png b/app/src/main/res/drawable-xhdpi/ic_radio.png
new file mode 100644
index 0000000..a7b9576
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_radio.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v11/ic_download.png b/app/src/main/res/drawable-xxhdpi-v11/ic_download.png
new file mode 100644
index 0000000..8e54cce
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v11/ic_download.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v11/ic_earphones.png b/app/src/main/res/drawable-xxhdpi-v11/ic_earphones.png
new file mode 100644
index 0000000..5e9d595
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v11/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v11/ic_note.png b/app/src/main/res/drawable-xxhdpi-v11/ic_note.png
new file mode 100644
index 0000000..0374073
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v11/ic_note.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v11/ic_radio.png b/app/src/main/res/drawable-xxhdpi-v11/ic_radio.png
new file mode 100644
index 0000000..9c586d0
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v11/ic_radio.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v9/ic_download.png b/app/src/main/res/drawable-xxhdpi-v9/ic_download.png
new file mode 100644
index 0000000..ccc41d1
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v9/ic_download.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v9/ic_earphones.png b/app/src/main/res/drawable-xxhdpi-v9/ic_earphones.png
new file mode 100644
index 0000000..8a877aa
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v9/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v9/ic_note.png b/app/src/main/res/drawable-xxhdpi-v9/ic_note.png
new file mode 100644
index 0000000..8968741
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v9/ic_note.png differ
diff --git a/app/src/main/res/drawable-xxhdpi-v9/ic_radio.png b/app/src/main/res/drawable-xxhdpi-v9/ic_radio.png
new file mode 100644
index 0000000..681a8a9
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi-v9/ic_radio.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_download.png b/app/src/main/res/drawable-xxhdpi/ic_download.png
new file mode 100644
index 0000000..1c8f804
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_download.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_earphones.png b/app/src/main/res/drawable-xxhdpi/ic_earphones.png
new file mode 100644
index 0000000..c6f0c19
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_earphones.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_note.png b/app/src/main/res/drawable-xxhdpi/ic_note.png
new file mode 100644
index 0000000..08b5b2b
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_note.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_radio.png b/app/src/main/res/drawable-xxhdpi/ic_radio.png
new file mode 100644
index 0000000..3d3ebc8
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_radio.png differ
diff --git a/app/src/main/res/drawable/divider.xml b/app/src/main/res/drawable/divider.xml
index 80b8c8c..edddbb2 100644
--- a/app/src/main/res/drawable/divider.xml
+++ b/app/src/main/res/drawable/divider.xml
@@ -2,6 +2,6 @@
-
+ android:height="1dp"/>
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index b3cbb43..3f8245d 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,16 +1,38 @@
-
-
-
-
+
+
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
-
+
+
+
diff --git a/app/src/main/res/layout/artist_preview.xml b/app/src/main/res/layout/artist_preview.xml
index 3cb7189..637c715 100644
--- a/app/src/main/res/layout/artist_preview.xml
+++ b/app/src/main/res/layout/artist_preview.xml
@@ -1,7 +1,7 @@
diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml
new file mode 100644
index 0000000..022dc98
--- /dev/null
+++ b/app/src/main/res/layout/fragment_about.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_artist_detail.xml b/app/src/main/res/layout/fragment_artist_detail.xml
similarity index 86%
rename from app/src/main/res/layout/activity_artist_detail.xml
rename to app/src/main/res/layout/fragment_artist_detail.xml
index b2f5639..3a8351c 100644
--- a/app/src/main/res/layout/activity_artist_detail.xml
+++ b/app/src/main/res/layout/fragment_artist_detail.xml
@@ -1,18 +1,14 @@
-
+
+ android:orientation="vertical">
+ android:visibility="invisible"/>
+
+ android:text="@string/artist_detail_fail_to_load_image"
+ android:visibility="invisible"/>
+
+
+
+
+
diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/toolbar.xml
new file mode 100644
index 0000000..a59d9dc
--- /dev/null
+++ b/app/src/main/res/layout/toolbar.xml
@@ -0,0 +1,11 @@
+
+
diff --git a/app/src/main/res/menu/drawer_menu.xml b/app/src/main/res/menu/drawer_menu.xml
new file mode 100644
index 0000000..be66d9f
--- /dev/null
+++ b/app/src/main/res/menu/drawer_menu.xml
@@ -0,0 +1,16 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..90bf001
--- /dev/null
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f8be218..bf9192d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -12,4 +12,27 @@
Не удалось загрузить изображение
Изображение
+
+
+ Исполнители
+ О программе
+ Настройки
+
+
+ Автор приложения: Боброва Александра
+ Написать разработчикам
+
+
+ Open navigation drawer
+ Close navigation drawer
+
+ Отправить сообщение
+ Для отправки сообщения необходимо установить почтовый клиент.
+
+ Наушники подключены
+ Выберите приложение для прослушивания музыки
+ Яндекс.Музыка
+ Яндекс.Радио
+ Отключить нотификацию
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 873f8f2..4d17e3a 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,13 +1,18 @@
-
+
+
+
+
+
diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml
new file mode 100644
index 0000000..35ccfb7
--- /dev/null
+++ b/app/src/main/res/xml/settings.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..76a88ef
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+
+ classpath 'com.android.tools.build:gradle:2.1.2'
+
+ classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
+
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..05ef575
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..9d47a7e
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Jul 13 17:26:27 MSK 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app'