The Android platform offers media playback tools that can be used by your applications to build an interface between the user and their music resources. We’re going to build a fundamental music player application for Android in this tutorial series.
In this tutorial help’s how to implement online music player with notification and local screen music controls .
We used Sound Cloud Used Stream Songs in this tutorial .As per your requirement can replace with your own resources to stream songs .And We Used DMAudioStreamer library help you to integrate audio streaming in your application.
Get Started
Dependencies Required:
dependencies { | |
implementation 'com.github.dibakarece:dmaudiostreamer:v1.0.4' | |
implementation 'androidx.appcompat:appcompat:1.0.2' | |
implementation 'com.google.android.material:material:1.0.0' | |
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' | |
implementation 'com.google.android.material:material:1.0.0' | |
implementation 'androidx.recyclerview:recyclerview:1.0.0' | |
implementation 'androidx.cardview:cardview:1.0.0' | |
testImplementation 'junit:junit:4.12' | |
androidTestImplementation 'androidx.test:runner:1.2.0' | |
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' | |
implementation 'com.nineoldandroids:library:2.4.0' | |
implementation 'com.squareup.picasso:picasso:2.5.2' | |
implementation 'com.sothree.slidinguppanel:library:3.3.1' | |
implementation 'com.github.ohoussein.playpauseview:playpauseview:1.0.2' | |
implementation 'com.jakewharton:butterknife:10.1.0' | |
annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' | |
implementation 'com.android.volley:volley:1.1.0' | |
implementation 'de.hdodenhof:circleimageview:3.0.0' | |
} |
1.Create Application Class
Create Application Used To Initialize Required Components On Launch of App
package in.androidhunt.musicDEmo; | |
import android.app.Application; | |
import android.content.Context; | |
import android.os.Handler; | |
import com.android.volley.Request; | |
import com.android.volley.RequestQueue; | |
import com.android.volley.toolbox.Volley; | |
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator; | |
import com.nostra13.universalimageloader.core.ImageLoader; | |
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; | |
import com.nostra13.universalimageloader.core.assist.QueueProcessingType; | |
public class App extends Application { | |
public static final String TAG = App.class.getSimpleName(); | |
public static final boolean ENCRYPTED = true; | |
public static volatile Handler applicationHandler = null; | |
private static App application; | |
private static Context mContext; | |
private static App mInstance; | |
private RequestQueue mRequestQueue; | |
public static Context getContext() { | |
return mContext; | |
} | |
public static synchronized App getInstance() { | |
return mInstance; | |
} | |
public static void initImageLoader(Context context) { | |
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context); | |
config.threadPriority(Thread.NORM_PRIORITY - 2); | |
config.denyCacheImageMultipleSizesInMemory(); | |
config.diskCacheFileNameGenerator(new Md5FileNameGenerator()); | |
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB | |
config.tasksProcessingOrder(QueueProcessingType.LIFO); | |
config.writeDebugLogs(); // Remove for release app | |
// Initialize ImageLoader with configuration. | |
ImageLoader.getInstance().init(config.build()); | |
} | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
mInstance = this; | |
initImageLoader(getApplicationContext()); | |
application = this; | |
} | |
public RequestQueue getRequestQueue() { | |
if (mRequestQueue == null) { | |
mRequestQueue = Volley.newRequestQueue(getApplicationContext()); | |
} | |
return mRequestQueue; | |
} | |
public <T> void addToRequestQueue(Request<T> req) { | |
req.setTag(TAG); | |
getRequestQueue().add(req); | |
} | |
@Override | |
public void onTerminate() { | |
super.onTerminate(); | |
application = null; | |
} | |
@Override | |
public void onLowMemory() { | |
super.onLowMemory(); | |
} | |
} |
2.Creating Music Albums Activity:
In This activity we used to list music albums in Grid View which Show in the Flowing Code.
AlbumActivity.java
package in.androidhunt.musicDEmo; | |
import android.content.Context; | |
import android.content.SharedPreferences; | |
import android.content.res.Resources; | |
import android.graphics.Rect; | |
import android.net.ConnectivityManager; | |
import android.net.NetworkInfo; | |
import android.os.Bundle; | |
import android.util.Log; | |
import android.util.TypedValue; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.view.Window; | |
import android.widget.ProgressBar; | |
import androidx.appcompat.app.AppCompatActivity; | |
import androidx.appcompat.widget.Toolbar; | |
import androidx.recyclerview.widget.DefaultItemAnimator; | |
import androidx.recyclerview.widget.GridLayoutManager; | |
import androidx.recyclerview.widget.RecyclerView; | |
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | |
import com.android.volley.RequestQueue; | |
import com.android.volley.Response; | |
import com.android.volley.VolleyError; | |
import com.android.volley.VolleyLog; | |
import com.android.volley.toolbox.JsonArrayRequest; | |
import com.android.volley.toolbox.Volley; | |
import com.google.android.material.appbar.AppBarLayout; | |
import com.google.android.material.appbar.CollapsingToolbarLayout; | |
import com.google.android.material.snackbar.Snackbar; | |
import org.json.JSONArray; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
import java.util.ArrayList; | |
import java.util.List; | |
import butterknife.BindView; | |
import butterknife.ButterKnife; | |
import in.androidhunt.musicDEmo.adapter.AlbumListAdapter; | |
import in.androidhunt.musicDEmo.model.Album; | |
public class AlbumsActivity extends AppCompatActivity implements AlbumListAdapter.OnItemClickListener { | |
private static final String TAG = AlbumsActivity.class.getSimpleName(); | |
private static String url = "https://www.androidhunt.in/apps/json/playlist.php"; | |
@BindView(R.id.recycler_view) | |
RecyclerView recyclerView; | |
@BindView(R.id.swipe_refresh) | |
SwipeRefreshLayout swiperefresh; | |
@BindView(R.id.toolbar) | |
Toolbar toolbar; | |
@BindView(R.id.avi) | |
ProgressBar progressBar; | |
@BindView(R.id.collapsing_toolbar) | |
CollapsingToolbarLayout collapsingToolbar; | |
@BindView(R.id.appbar) | |
AppBarLayout appBarLayout; | |
RequestQueue request; | |
private AlbumListAdapter adapter; | |
private List<Album> albumList; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
supportRequestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_albums); | |
ButterKnife.bind(this); | |
setSupportActionBar(toolbar); | |
getSupportActionBar().setDisplayHomeAsUpEnabled(true); | |
initCollapsingToolbar(); | |
swiperefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { | |
@Override | |
public void onRefresh() { | |
if (!isNetworkAvailable()) { | |
swiperefresh.setRefreshing(false); | |
} else { | |
swiperefresh.setRefreshing(true); | |
OnLineMode(); | |
} | |
} | |
}); | |
albumList = new ArrayList<>(); | |
adapter = new AlbumListAdapter(this, albumList); | |
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2); | |
recyclerView.setLayoutManager(mLayoutManager); | |
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true)); | |
recyclerView.setItemAnimator(new DefaultItemAnimator()); | |
recyclerView.setAdapter(adapter); | |
adapter.setOnItemClickListener(this); | |
OnLineMode(); | |
swiperefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { | |
@Override | |
public void onRefresh() { | |
if (!isNetworkAvailable()) { | |
swiperefresh.setRefreshing(false); | |
} else { | |
swiperefresh.setRefreshing(true); | |
OnLineMode(); | |
} | |
} | |
}); | |
} | |
/** | |
* Adding few albums for testing | |
*/ | |
public void OnLineMode() { | |
if (isNetworkAvailable()) { | |
showProgress(); | |
OfflineMode(); | |
request = Volley.newRequestQueue(this); | |
JsonArrayRequest movieReq = new JsonArrayRequest(url, | |
new Response.Listener<JSONArray>() { | |
@Override | |
public void onResponse(JSONArray response) { | |
Log.d(TAG, response.toString()); | |
albumList.clear(); | |
hideProgress(); | |
Log.d(TAG, response.toString()); | |
// This Is used store response to device acess it when user offline | |
SharedPreferences sharedPref = getSharedPreferences("SONGS", Context.MODE_PRIVATE); | |
SharedPreferences.Editor editor = sharedPref.edit(); | |
editor.clear(); | |
editor.putString("SONGS_1", response.toString()); | |
editor.commit(); | |
for (int i = 0; i < response.length(); i++) { | |
try { | |
JSONObject obj = response.getJSONObject(i); | |
Album a = new Album(obj.getString("title"), obj.getString("detail"), obj.getString("image"), obj.getString("id"), obj.getString("status")); | |
albumList.add(a); | |
} catch (JSONException e) { | |
e.printStackTrace(); | |
} | |
} | |
adapter.notifyDataSetChanged(); | |
} | |
}, new Response.ErrorListener() { | |
@Override | |
public void onErrorResponse(VolleyError error) { | |
VolleyLog.d(TAG, "Error: " + error.getMessage()); | |
OnLineMode(); | |
} | |
}); | |
// Adding request to request queue | |
App.getInstance().addToRequestQueue(movieReq); | |
} else { | |
final Snackbar snackbar = Snackbar.make(findViewById(R.id.main_content), "No Internet Connection", Snackbar.LENGTH_LONG); | |
snackbar.setAction("Offline", new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
snackbar.dismiss(); | |
} | |
}); | |
snackbar.show(); | |
hideProgress(); | |
OfflineMode(); | |
} | |
} | |
public void OfflineMode() { | |
albumList.clear(); | |
SharedPreferences sharedPref = getSharedPreferences("SONGS", Context.MODE_PRIVATE); | |
String res = sharedPref.getString("SONGS_1", ""); | |
try { | |
JSONArray response = new JSONArray(res); | |
for (int i = 0; i < response.length(); i++) { | |
JSONObject obj = response.getJSONObject(i); | |
Album a = new Album(obj.getString("title"), obj.getString("detail"), obj.getString("image"), obj.getString("id"), obj.getString("status")); | |
albumList.add(a); | |
} | |
} catch (JSONException e) { | |
e.printStackTrace(); | |
} | |
adapter.notifyDataSetChanged(); | |
} | |
private void initCollapsingToolbar() { | |
collapsingToolbar.setTitle(" "); | |
appBarLayout.setExpanded(true); | |
// hiding & showing the title when toolbar expanded & collapsed | |
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { | |
boolean isShow = false; | |
int scrollRange = -1; | |
@Override | |
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { | |
if (scrollRange == -1) { | |
scrollRange = appBarLayout.getTotalScrollRange(); | |
} | |
if (scrollRange + verticalOffset == 0) { | |
collapsingToolbar.setTitle("Songs"); | |
isShow = true; | |
} else if (isShow) { | |
collapsingToolbar.setTitle(" "); | |
isShow = false; | |
} | |
} | |
}); | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
switch (item.getItemId()) { | |
case android.R.id.home: | |
onBackPressed(); | |
return true; | |
default: | |
return super.onOptionsItemSelected(item); | |
} | |
} | |
//to hide indicators | |
void showProgress() { | |
progressBar.setVisibility(View.VISIBLE); | |
} | |
void hideProgress() { | |
progressBar.setVisibility(View.GONE); | |
swiperefresh.setRefreshing(false); | |
} | |
private boolean isNetworkAvailable() { | |
ConnectivityManager connectivityManager | |
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); | |
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); | |
return activeNetworkInfo != null && activeNetworkInfo.isConnected(); | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
finish(); | |
} | |
@Override | |
public void onItemClick(View view, Album album) { | |
PlaylistActivity.navigate(this, view.findViewById(R.id.thumbnail), album); | |
} | |
/** | |
* Converting dp to pixel | |
*/ | |
private int dpToPx(int dp) { | |
Resources r = getResources(); | |
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics())); | |
} | |
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { | |
private int spanCount; | |
private int spacing; | |
private boolean includeEdge; | |
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) { | |
this.spanCount = spanCount; | |
this.spacing = spacing; | |
this.includeEdge = includeEdge; | |
} | |
@Override | |
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { | |
int position = parent.getChildAdapterPosition(view); // item position | |
int column = position % spanCount; // item column | |
if (includeEdge) { | |
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing) | |
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing) | |
if (position < spanCount) { // top edge | |
outRect.top = spacing; | |
} | |
outRect.bottom = spacing; // item bottom | |
} else { | |
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing) | |
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) | |
if (position >= spanCount) { | |
outRect.top = spacing; // item top | |
} | |
} | |
} | |
} | |
} |
Creating Model For Album Items
package in.androidhunt.musicDEmo.model; | |
/** | |
* Created by Lincoln on 18/05/16. | |
*/ | |
public class Album { | |
private String name; | |
private String about; | |
private String thumbnail; | |
private String id; | |
private String status; | |
public Album() { | |
} | |
public Album(String name, String about, String thumbnail, String id, String status) { | |
this.name = name; | |
this.about = about; | |
this.thumbnail = thumbnail; | |
this.id = id; | |
this.status = status; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
public String getMusicDir() { | |
return about; | |
} | |
public void setMusicDir(String about) { | |
this.about = about; | |
} | |
public String getThumbnail() { | |
return thumbnail; | |
} | |
public void setThumbnail(String thumbnail) { | |
this.thumbnail = thumbnail; | |
} | |
public String getId() { | |
return id; | |
} | |
public void setId(String id) { | |
this.id = id; | |
} | |
public String getStatus() { | |
return status; | |
} | |
public void setStatus(String status) { | |
this.status = status; | |
} | |
} |
Create Xml Designs For Above Activity
activity_albums.xml
<?xml version="1.0" encoding="utf-8"?> | |
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
xmlns:custom="http://schemas.android.com/apk/res-auto" | |
android:id="@+id/main_content" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:background="@android:color/white" | |
android:fitsSystemWindows="true"> | |
<com.google.android.material.appbar.AppBarLayout | |
android:id="@+id/appbar" | |
android:layout_width="match_parent" | |
android:layout_height="250dp" | |
android:fitsSystemWindows="true" | |
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> | |
<com.google.android.material.appbar.CollapsingToolbarLayout | |
android:background="@drawable/jrntr" | |
android:id="@+id/collapsing_toolbar" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:fitsSystemWindows="true" | |
app:contentScrim="?attr/colorPrimary" | |
app:expandedTitleMarginEnd="64dp" | |
app:expandedTitleMarginStart="48dp" | |
app:expandedTitleTextAppearance="@android:color/transparent" | |
app:layout_scrollFlags="scroll|exitUntilCollapsed"> | |
<androidx.appcompat.widget.Toolbar | |
android:id="@+id/toolbar" | |
android:layout_width="match_parent" | |
android:layout_height="?attr/actionBarSize" | |
app:layout_collapseMode="pin" | |
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> | |
</com.google.android.material.appbar.CollapsingToolbarLayout> | |
</com.google.android.material.appbar.AppBarLayout> | |
<include layout="@layout/content_ablums" /> | |
<ProgressBar | |
android:id="@+id/avi" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
style="?android:attr/progressBarStyle" | |
android:visibility="visible" | |
android:layout_gravity="center" | |
android:layout_centerHorizontal="true" | |
android:layout_centerVertical="true" | |
/> | |
</androidx.coordinatorlayout.widget.CoordinatorLayout> |
content_albums.xml
<?xml version="1.0" encoding="utf-8"?> | |
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:layout_width="match_parent" | |
android:id="@+id/swipe_refresh" | |
android:layout_height="match_parent" | |
android:background="#E1E1E1" | |
app:layout_behavior="@string/appbar_scrolling_view_behavior"> | |
<androidx.recyclerview.widget.RecyclerView | |
android:id="@+id/recycler_view" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:clipToPadding="false" | |
android:scrollbars="vertical" /> | |
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> |
Creating Recycle View Adapter for Showing Albums in List
AlbumListAdapter.java
package in.androidhunt.musicDEmo.adapter; | |
import android.content.Context; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.ImageView; | |
import android.widget.TextView; | |
import android.widget.Toast; | |
import androidx.recyclerview.widget.RecyclerView; | |
import com.squareup.picasso.Picasso; | |
import java.util.List; | |
import butterknife.BindView; | |
import butterknife.ButterKnife; | |
import in.androidhunt.musicDEmo.R; | |
import in.androidhunt.musicDEmo.model.Album; | |
public class AlbumListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { | |
private List<Album> albumList; | |
private Context context; | |
private OnItemClickListener onItemClickListener; | |
public AlbumListAdapter(Context context, List<Album> albumList) { | |
this.context = context; | |
this.albumList = albumList; | |
} | |
@Override | |
public int getItemViewType(int position) { | |
return position; | |
} | |
@Override | |
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.album_item, parent, false); | |
return new ViewHolder(v); | |
} | |
@Override | |
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { | |
if (holder instanceof ViewHolder) { | |
final Album m = albumList.get(position); | |
((ViewHolder) holder).title.setText(m.getName()); | |
((ViewHolder) holder).gener.setText(m.getMusicDir()); | |
Picasso.with(context).load(m.getThumbnail()).into(((ViewHolder) holder).imageView); | |
holder.itemView.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
Album source = albumList.get(position); | |
String status = source.getStatus(); | |
if (status.contains("inactive")) { | |
String mesg = "Sorry Currently Un Available"; | |
Toast.makeText(context, mesg, Toast.LENGTH_LONG).show(); | |
} else { | |
onItemClickListener.onItemClick(v, source); | |
} | |
} | |
}); | |
} | |
} | |
@Override | |
public int getItemCount() { | |
return albumList.size(); | |
} | |
public void setOnItemClickListener(OnItemClickListener onItemClickListener) { | |
this.onItemClickListener = onItemClickListener; | |
} | |
public interface OnItemClickListener { | |
void onItemClick(View view, Album album); | |
} | |
public class ViewHolder extends RecyclerView.ViewHolder { | |
@BindView(R.id.thumbnail) | |
ImageView imageView; | |
@BindView(R.id.title) | |
TextView title; | |
@BindView(R.id.count) | |
TextView gener; | |
public ViewHolder(View v) { | |
super(v); | |
ButterKnife.bind(this, v); | |
} | |
} | |
} | |
Creating Album List Item
album_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:card_view="http://schemas.android.com/apk/res-auto" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content"> | |
<androidx.cardview.widget.CardView | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:layout_gravity="center" | |
android:layout_margin="@dimen/card_margin" | |
android:elevation="3dp" | |
card_view:cardCornerRadius="@dimen/card_album_radius"> | |
<RelativeLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<ImageView | |
android:id="@+id/thumbnail" | |
android:layout_width="match_parent" | |
android:layout_height="@dimen/album_cover_height" | |
android:background="?attr/selectableItemBackgroundBorderless" | |
android:scaleType="fitXY" /> | |
<TextView | |
android:id="@+id/title" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_below="@+id/thumbnail" | |
android:paddingLeft="@dimen/album_title_padding" | |
android:paddingRight="@dimen/album_title_padding" | |
android:paddingTop="@dimen/album_title_padding" | |
android:textColor="@color/album_title" | |
android:textSize="@dimen/album_title" /> | |
<TextView | |
android:id="@+id/count" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_below="@+id/title" | |
android:paddingBottom="@dimen/songs_count_padding_bottom" | |
android:paddingLeft="@dimen/album_title_padding" | |
android:paddingRight="@dimen/album_title_padding" | |
android:textSize="@dimen/songs_count" /> | |
<ImageView | |
android:id="@+id/overflow" | |
android:layout_width="@dimen/ic_album_overflow_width" | |
android:layout_height="@dimen/ic_album_overflow_height" | |
android:layout_alignParentRight="true" | |
android:layout_below="@+id/thumbnail" | |
android:layout_marginTop="@dimen/ic_album_overflow_margin_top" | |
android:scaleType="centerCrop" | |
android:src="@drawable/ic_more" /> | |
</RelativeLayout> | |
</androidx.cardview.widget.CardView> | |
</LinearLayout> |
The Final Design Of Above Activity As Shown Below

3.Creating Music Playlist Activity With All Music Controls
PlaylistActivity.java
package in.androidhunt.musicDEmo; | |
import android.app.PendingIntent; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.content.SharedPreferences; | |
import android.content.res.ColorStateList; | |
import android.graphics.Bitmap; | |
import android.graphics.drawable.BitmapDrawable; | |
import android.graphics.drawable.Drawable; | |
import android.media.session.PlaybackState; | |
import android.net.ConnectivityManager; | |
import android.net.NetworkInfo; | |
import android.os.Build; | |
import android.os.Bundle; | |
import android.support.v4.media.session.PlaybackStateCompat; | |
import android.text.format.DateUtils; | |
import android.transition.Slide; | |
import android.view.MenuItem; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.view.WindowManager; | |
import android.widget.ImageButton; | |
import android.widget.ImageView; | |
import android.widget.ProgressBar; | |
import android.widget.RelativeLayout; | |
import android.widget.TextView; | |
import androidx.annotation.Nullable; | |
import androidx.appcompat.app.AppCompatActivity; | |
import androidx.appcompat.widget.Toolbar; | |
import androidx.core.app.ActivityCompat; | |
import androidx.core.app.ActivityOptionsCompat; | |
import androidx.core.view.ViewCompat; | |
import androidx.palette.graphics.Palette; | |
import androidx.recyclerview.widget.DefaultItemAnimator; | |
import androidx.recyclerview.widget.LinearLayoutManager; | |
import androidx.recyclerview.widget.RecyclerView; | |
import com.android.volley.Request; | |
import com.android.volley.Response; | |
import com.android.volley.VolleyError; | |
import com.android.volley.toolbox.JsonObjectRequest; | |
import com.google.android.material.appbar.AppBarLayout; | |
import com.google.android.material.appbar.CollapsingToolbarLayout; | |
import com.google.android.material.floatingactionbutton.FloatingActionButton; | |
import com.google.android.material.snackbar.Snackbar; | |
import com.ohoussein.playpause.PlayPauseView; | |
import com.sothree.slidinguppanel.SlidingUpPanelLayout; | |
import com.squareup.picasso.Callback; | |
import com.squareup.picasso.Picasso; | |
import com.squareup.picasso.Target; | |
import org.json.JSONArray; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.concurrent.TimeUnit; | |
import butterknife.BindView; | |
import butterknife.ButterKnife; | |
import dm.audiostreamer.AudioStreamingManager; | |
import dm.audiostreamer.CurrentSessionCallback; | |
import dm.audiostreamer.Logger; | |
import dm.audiostreamer.MediaMetaData; | |
import in.androidhunt.musicDEmo.adapter.PlayListAdapter; | |
import in.androidhunt.musicDEmo.model.Album; | |
import in.androidhunt.musicDEmo.view.LineProgress; | |
import in.androidhunt.musicDEmo.view.Slider; | |
import in.androidhunt.musicDEmo.view.SquareImageView; | |
public class PlaylistActivity extends AppCompatActivity implements CurrentSessionCallback, View.OnClickListener, Slider.OnValueChangedListener { | |
@BindView(R.id.collapsing_toolbar_layout) | |
CollapsingToolbarLayout collapsingToolbarLayout; | |
@BindView(R.id.tool_bar) | |
Toolbar toolbar; | |
@BindView(R.id.playlist_layout) | |
RecyclerView playList; | |
@BindView(R.id.avi_loader) | |
ProgressBar avi; | |
@BindView(R.id.image_album) | |
SquareImageView albumImage; | |
@BindView(R.id.sliding_layout) | |
SlidingUpPanelLayout mLayout; | |
@BindView(R.id.btn_play) | |
PlayPauseView btn_play; | |
@BindView(R.id.image_songAlbumArt) | |
ImageView image_songAlbumArt; | |
@BindView(R.id.img_bottom_albArt) | |
ImageView img_bottom_albArt; | |
@BindView(R.id.image_songAlbumArtBlur) | |
ImageView image_songAlbumArtBlur; | |
@BindView(R.id.slidepanel_time_progress) | |
TextView time_progress_slide; | |
@BindView(R.id.slidepanel_time_total) | |
TextView time_total_slide; | |
@BindView(R.id.slidepanel_time_progress_bottom) | |
TextView time_progress_bottom; | |
@BindView(R.id.slidepanel_time_total_bottom) | |
TextView time_total_bottom; | |
@BindView(R.id.pgPlayPauseLayout) | |
RelativeLayout pgPlayPauseLayout; | |
@BindView(R.id.lineProgress) | |
LineProgress lineProgress; | |
@BindView(R.id.audio_progress_control) | |
Slider audioPg; | |
@BindView(R.id.btn_backward) | |
ImageView btn_backward; | |
@BindView(R.id.text_songName) | |
TextView text_songName; | |
@BindView(R.id.text_songAlb) | |
TextView text_songAlb; | |
@BindView(R.id.txt_bottom_SongName) | |
TextView txt_bottom_SongName; | |
@BindView(R.id.txt_bottom_SongAlb) | |
TextView txt_bottom_SongAlb; | |
@BindView(R.id.slideBottomView) | |
RelativeLayout slideBottomView; | |
@BindView(R.id.cover_mirror) | |
ImageView image_mirror; | |
private PlayListAdapter adapter; | |
private boolean isExpand = false; | |
private Context context; | |
@BindView(R.id.btn_forward) | |
ImageView btn_forward; | |
//For Implementation | |
private AudioStreamingManager streamingManager; | |
private MediaMetaData currentSong; | |
private List<MediaMetaData> listOfSongs = new ArrayList<MediaMetaData>(); | |
private String title; | |
private String musicDir; | |
private String platList_Id; | |
private String albumImg; | |
private boolean isPlaylistAdded; | |
public static final String PLAYLIST_ID = "playlist_id"; | |
public static final String MUSIC_DIR = "music_dir"; | |
public static final String ALBUM_ART = "album_art"; | |
public static final String ALBUM_NAME = "album_name"; | |
@BindView(R.id.fab) | |
FloatingActionButton floatingActionButton; | |
@BindView(R.id.app_bar_layout) | |
AppBarLayout appBarLayout; | |
public static void navigate(AlbumsActivity albumsActivity, View viewById, Album album) { | |
String about = album.getMusicDir(); | |
String imgurl = album.getThumbnail(); | |
String title = album.getName(); | |
String playlistid = album.getId(); | |
Intent intent = new Intent(albumsActivity, PlaylistActivity.class); | |
intent.putExtra(PLAYLIST_ID, playlistid); | |
intent.putExtra(MUSIC_DIR, about); | |
intent.putExtra(ALBUM_ART, imgurl); | |
intent.putExtra(ALBUM_NAME, title); | |
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(albumsActivity, viewById, imgurl); | |
ActivityCompat.startActivity(albumsActivity, intent, options.toBundle()); | |
} | |
@Override | |
protected void onCreate(@Nullable Bundle savedInstanceState) { | |
setTheme(R.style.BaseTheme_playlist); | |
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); | |
initActivityTransitions(); | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.playlist_activity); | |
ButterKnife.bind(this); | |
Intent i = getIntent(); | |
title = i.getStringExtra(ALBUM_NAME); | |
musicDir = i.getStringExtra(MUSIC_DIR); | |
platList_Id = i.getStringExtra(PLAYLIST_ID); | |
albumImg = i.getStringExtra(ALBUM_ART); | |
//Used or Element View Transitions | |
ViewCompat.setTransitionName(appBarLayout, albumImg); | |
supportPostponeEnterTransition(); | |
setSupportActionBar(toolbar); | |
getSupportActionBar().setDisplayHomeAsUpEnabled(true); | |
adapter = new PlayListAdapter(this, listOfSongs, title, musicDir); | |
collapsingToolbarLayout.setTitle(title); | |
collapsingToolbarLayout.setExpandedTitleColor(getResources().getColor(android.R.color.transparent)); | |
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this); | |
playList.setLayoutManager(mLayoutManager); | |
playList.setItemAnimator(new DefaultItemAnimator()); | |
playList.setAdapter(adapter); | |
Picasso.with(getBaseContext()).load(albumImg).into(albumImage); | |
Picasso.with(this).load(albumImg).into(albumImage, new Callback() { | |
@Override | |
public void onSuccess() { | |
Bitmap bitmap = ((BitmapDrawable) albumImage.getDrawable()).getBitmap(); | |
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() { | |
public void onGenerated(Palette palette) { | |
applyPalette(palette); | |
} | |
}); | |
} | |
@Override | |
public void onError() { | |
} | |
}); | |
adapter.setOnClickListener(new PlayListAdapter.SetOnclickListner() { | |
@Override | |
public void onClickSong(MediaMetaData album, int postion) { | |
if (!isPlaylistAdded) { | |
streamingManager.setMediaList(listOfSongs); | |
isPlaylistAdded = true; | |
checkAlreadyPlaying(); | |
streamingManager.setShowPlayerNotification(true); | |
streamingManager.setPendingIntentAct(getNotificationPendingIntent()); | |
} | |
playSong(album); | |
} | |
}); | |
ImageButton closeDrawer = findViewById(R.id.down_arrow); | |
closeDrawer.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
if (isExpand) { | |
mLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); | |
} | |
} | |
}); | |
floatingActionButton.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
if (listOfSongs.size() > 0) { | |
MediaMetaData album = listOfSongs.get(0); | |
if (!isPlaylistAdded) { | |
streamingManager.setMediaList(listOfSongs); | |
isPlaylistAdded = true; | |
checkAlreadyPlaying(); | |
streamingManager.setShowPlayerNotification(true); | |
streamingManager.setPendingIntentAct(getNotificationPendingIntent()); | |
} | |
playSong(album); | |
} | |
} | |
}); | |
this.context = PlaylistActivity.this; | |
configAudioStreamer(); | |
uiInitialization(); | |
onLoadPlaylist(platList_Id, albumImg); | |
checkAlreadyPlaying(); | |
} | |
@Override | |
public void onResume() { | |
super.onResume(); | |
checkAlreadyPlaying(); | |
if (streamingManager.isPlaying()) { | |
btn_play.change(false, true); | |
} else { | |
btn_play.change(true, true); | |
} | |
} | |
public void onLoadPlaylist(String movie, final String img) { | |
if (isNetworkAvailable()) { | |
OfflineMode(); | |
if (!movie.equals("")) { | |
avi.setVisibility(View.VISIBLE); | |
String songs = "https://api.soundcloud.com/playlists/" + movie + "?client_id=95f22ed54a5c297b1c41f72d713623ef"; | |
JsonObjectRequest movieReq = new JsonObjectRequest(Request.Method.GET, songs, | |
null, new Response.Listener<JSONObject>() { | |
@Override | |
public void onResponse(JSONObject response) { | |
storeResponse(response.toString()); | |
avi.setVisibility(View.GONE); | |
listOfSongs.clear(); | |
try { | |
JSONArray obj = response.getJSONArray("tracks"); | |
// Parsing json | |
for (int i = 0; i < obj.length(); i++) { | |
JSONObject media = obj.getJSONObject(i); | |
MediaMetaData mediaMetaData = new MediaMetaData(); | |
mediaMetaData.setMediaAlbum(title); | |
mediaMetaData.setMediaArt(img); | |
mediaMetaData.setMediaArtist(musicDir); | |
String songUrl = media.getString("stream_url") + "?client_id=95f22ed54a5c297b1c41f72d713623ef"; | |
String songtitle = media.getString("title").replaceAll(".mp3", "").replaceAll("[0-9]", "").replaceAll("\\[.*?\\]", "").replaceAll("-", "").replaceAll("_", "").replaceAll("\\.", "").replaceAll("\\p{P}", "").replaceAll("Kbps", ""); | |
mediaMetaData.setMediaUrl(songUrl); | |
long duration = Long.parseLong(media.getString("duration")); | |
mediaMetaData.setMediaDuration(TimeUnit.MILLISECONDS.toSeconds(duration) + ""); | |
mediaMetaData.setMediaTitle(songtitle); | |
mediaMetaData.setMediaId(songtitle); | |
listOfSongs.add(mediaMetaData); | |
} | |
adapter.notifyDataSetChanged(); | |
} catch (JSONException e) { | |
// TODO Auto-generated catch block | |
e.printStackTrace(); | |
} | |
} | |
}, new Response.ErrorListener() { | |
@Override | |
public void onErrorResponse(VolleyError error) { | |
avi.setVisibility(View.GONE); | |
} | |
}); | |
// Adding request to request queue | |
App.getInstance().addToRequestQueue(movieReq); | |
} | |
} else { | |
OfflineMode(); | |
avi.setVisibility(View.GONE); | |
final Snackbar snackbar = Snackbar.make(findViewById(R.id.sliding_layout), "No Internet Connection", Snackbar.LENGTH_LONG); | |
snackbar.setAction("Offline", new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
snackbar.dismiss(); | |
} | |
}); | |
snackbar.show(); | |
} | |
} | |
private void storeResponse(String response) { | |
SharedPreferences sharedPref = getSharedPreferences(title, Context.MODE_PRIVATE); | |
SharedPreferences.Editor editor = sharedPref.edit(); | |
editor.clear(); | |
editor.putString(title + "123", response); | |
editor.commit(); | |
} | |
public void OfflineMode() { | |
listOfSongs.clear(); | |
SharedPreferences sharedPref = getSharedPreferences(title, Context.MODE_PRIVATE); | |
String res = sharedPref.getString(title + "123", ""); | |
try { | |
JSONObject response = new JSONObject(res); | |
JSONArray obj = response.getJSONArray("tracks"); | |
for (int i = 0; i < obj.length(); i++) { | |
JSONObject media = obj.getJSONObject(i); | |
MediaMetaData mediaMetaData = new MediaMetaData(); | |
mediaMetaData.setMediaAlbum(title); | |
mediaMetaData.setMediaArt(albumImg); | |
mediaMetaData.setMediaArtist(musicDir); | |
String songUrl = media.getString("stream_url") + "?client_id=bd6d136e05d880eea1bc0b1a7bcad42f"; | |
String songtitle = media.getString("title").replaceAll(".mp3", "").replaceAll("[0-9]", "").replaceAll("\\[.*?\\]", "").replaceAll("-", "").replaceAll("_", "").replaceAll("\\.", "").replaceAll("\\p{P}", "").replaceAll("Kbps", ""); | |
mediaMetaData.setMediaId(songtitle); | |
mediaMetaData.setMediaUrl(songUrl); | |
long duration = Long.parseLong(media.getString("duration")); | |
mediaMetaData.setMediaDuration(TimeUnit.MILLISECONDS.toSeconds(duration) + ""); | |
mediaMetaData.setMediaTitle(songtitle); | |
listOfSongs.add(mediaMetaData); | |
} | |
} catch (JSONException e) { | |
// TODO Auto-generated catch block | |
e.printStackTrace(); | |
} | |
adapter.notifyDataSetChanged(); | |
} | |
private boolean isNetworkAvailable() { | |
ConnectivityManager connectivityManager | |
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); | |
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); | |
return activeNetworkInfo != null && activeNetworkInfo.isConnected(); | |
} | |
@Override | |
public boolean dispatchTouchEvent(MotionEvent motionEvent) { | |
try { | |
return super.dispatchTouchEvent(motionEvent); | |
} catch (NullPointerException e) { | |
return false; | |
} | |
} | |
private void initActivityTransitions() { | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |
Slide transition = new Slide(); | |
transition.excludeTarget(android.R.id.statusBarBackground, true); | |
getWindow().setEnterTransition(transition); | |
getWindow().setReturnTransition(transition); | |
} | |
} | |
private void applyPalette(Palette palette) { | |
int primaryDark = getResources().getColor(R.color.primary_dark); | |
int primary = getResources().getColor(R.color.primary); | |
collapsingToolbarLayout.setContentScrimColor(palette.getMutedColor(primary)); | |
collapsingToolbarLayout.setStatusBarScrimColor(palette.getDarkMutedColor(primaryDark)); | |
updateBackground(findViewById(R.id.fab), palette); | |
supportStartPostponedEnterTransition(); | |
} | |
private void updateBackground(FloatingActionButton fab, Palette palette) { | |
int lightVibrantColor = palette.getLightVibrantColor(getResources().getColor(android.R.color.white)); | |
int vibrantColor = palette.getVibrantColor(getResources().getColor(R.color.accent)); | |
fab.setRippleColor(lightVibrantColor); | |
fab.setBackgroundTintList(ColorStateList.valueOf(vibrantColor)); | |
} | |
private void uiInitialization() { | |
btn_backward.setOnClickListener(this); | |
btn_forward.setOnClickListener(this); | |
btn_play.setOnClickListener(this); | |
pgPlayPauseLayout.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View view) { | |
return; | |
} | |
}); | |
if (streamingManager.isPlaying()) { | |
btn_play.change(false, true); | |
} else { | |
btn_play.change(true, true); | |
} | |
slideBottomView.setVisibility(View.VISIBLE); | |
slideBottomView.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
mLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); | |
} | |
}); | |
audioPg.setMax(0); | |
audioPg.setOnValueChangedListener(this); | |
mLayout.addPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() { | |
@Override | |
public void onPanelSlide(View panel, float slideOffset) { | |
if (slideOffset == 0.0f) { | |
isExpand = false; | |
slideBottomView.setVisibility(View.VISIBLE); | |
// slideBottomView.getBackground().setAlpha(0); | |
} else if (slideOffset > 0.0f && slideOffset < 1.0f) { | |
// slideBottomView.getBackground().setAlpha((int) slideOffset * 255); | |
} else { | |
// slideBottomView.getBackground().setAlpha(100); | |
isExpand = true; | |
slideBottomView.setVisibility(View.GONE); | |
} | |
} | |
@Override | |
public void onPanelStateChanged(View panel, SlidingUpPanelLayout.PanelState previousState, SlidingUpPanelLayout.PanelState newState) { | |
if (SlidingUpPanelLayout.PanelState.EXPANDED == newState) { | |
isExpand = true; | |
} else if (SlidingUpPanelLayout.PanelState.COLLAPSED == newState) { | |
isExpand = false; | |
} | |
} | |
}); | |
} | |
private void configAudioStreamer() { | |
streamingManager = AudioStreamingManager.getInstance(context); | |
//Set PlayMultiple 'true' if want to playing sequentially one by one songs | |
// and provide the list of songs else set it 'false' | |
streamingManager.setPlayMultiple(true); | |
// streamingManager.setMediaList(listOfSongs); | |
//If you want to show the Player Notification then set ShowPlayerNotification as true | |
//and provide the pending intent so that after click on notification it will redirect to an activity | |
} | |
@Override | |
public void onBackPressed() { | |
if (isExpand) { | |
mLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); | |
} else { | |
super.onBackPressed(); | |
} | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
switch (item.getItemId()) { | |
case android.R.id.home: | |
onBackPressed(); | |
return true; | |
default: | |
return super.onOptionsItemSelected(item); | |
} | |
} | |
@Override | |
public void onStart() { | |
super.onStart(); | |
try { | |
if (streamingManager != null) { | |
streamingManager.subscribesCallBack(this); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
@Override | |
public void onStop() { | |
try { | |
if (streamingManager != null) { | |
streamingManager.unSubscribeCallBack(); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
super.onStop(); | |
} | |
@Override | |
protected void onDestroy() { | |
try { | |
if (streamingManager != null) { | |
streamingManager.unSubscribeCallBack(); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
super.onDestroy(); | |
} | |
@Override | |
public void updatePlaybackState(int state) { | |
Logger.e("updatePlaybackState: ", "" + state); | |
switch (state) { | |
case PlaybackStateCompat.STATE_PLAYING: | |
pgPlayPauseLayout.setVisibility(View.INVISIBLE); | |
btn_play.change(false, true); | |
if (currentSong != null) { | |
currentSong.setPlayState(PlaybackStateCompat.STATE_PLAYING); | |
notifyAdapter(currentSong); | |
} | |
break; | |
case PlaybackStateCompat.STATE_PAUSED: | |
pgPlayPauseLayout.setVisibility(View.INVISIBLE); | |
btn_play.change(true, true); | |
if (currentSong != null) { | |
currentSong.setPlayState(PlaybackStateCompat.STATE_PAUSED); | |
notifyAdapter(currentSong); | |
} | |
break; | |
case PlaybackStateCompat.STATE_NONE: | |
currentSong.setPlayState(PlaybackStateCompat.STATE_NONE); | |
notifyAdapter(currentSong); | |
break; | |
case PlaybackStateCompat.STATE_STOPPED: | |
pgPlayPauseLayout.setVisibility(View.INVISIBLE); | |
btn_play.change(true, true); | |
audioPg.setValue(0); | |
if (currentSong != null) { | |
currentSong.setPlayState(PlaybackStateCompat.STATE_NONE); | |
notifyAdapter(currentSong); | |
} | |
break; | |
case PlaybackStateCompat.STATE_BUFFERING: | |
pgPlayPauseLayout.setVisibility(View.VISIBLE); | |
if (currentSong != null) { | |
btn_play.change(true, true); | |
currentSong.setPlayState(PlaybackStateCompat.STATE_NONE); | |
notifyAdapter(currentSong); | |
} | |
break; | |
} | |
} | |
@Override | |
public void playSongComplete() { | |
String timeString = "00.00"; | |
time_total_bottom.setText(timeString); | |
time_total_slide.setText(timeString); | |
time_progress_bottom.setText(timeString); | |
time_progress_slide.setText(timeString); | |
lineProgress.setLineProgress(0); | |
audioPg.setValue(0); | |
} | |
@Override | |
public void currentSeekBarPosition(int progress) { | |
audioPg.setValue(progress); | |
setPGTime(progress); | |
} | |
@Override | |
public void playCurrent(int indexP, MediaMetaData currentAudio) { | |
showMediaInfo(currentAudio); | |
notifyAdapter(currentAudio); | |
} | |
@Override | |
public void playNext(int indexP, MediaMetaData CurrentAudio) { | |
showMediaInfo(CurrentAudio); | |
} | |
@Override | |
public void playPrevious(int indexP, MediaMetaData currentAudio) { | |
showMediaInfo(currentAudio); | |
} | |
@Override | |
public void onClick(View view) { | |
switch (view.getId()) { | |
case R.id.btn_forward: | |
streamingManager.onSkipToNext(); | |
break; | |
case R.id.btn_backward: | |
streamingManager.onSkipToPrevious(); | |
break; | |
case R.id.btn_play: | |
if (currentSong != null) { | |
playPauseEvent(view); | |
} | |
break; | |
} | |
} | |
@Override | |
public void onValueChanged(int value) { | |
streamingManager.onSeekTo(value); | |
streamingManager.scheduleSeekBarUpdate(); | |
} | |
private void notifyAdapter(MediaMetaData media) { | |
adapter.notifyPlayState(media); | |
} | |
private void playPauseEvent(View v) { | |
if (streamingManager.isPlaying()) { | |
streamingManager.onPause(); | |
((PlayPauseView) v).change(true, true); | |
} else { | |
streamingManager.onPlay(currentSong); | |
((PlayPauseView) v).change(false, true); | |
} | |
} | |
private void playSong(MediaMetaData media) { | |
if (streamingManager != null) { | |
streamingManager.onPlay(media); | |
showMediaInfo(media); | |
} | |
} | |
private void showMediaInfo(MediaMetaData media) { | |
currentSong = media; | |
audioPg.setValue(0); | |
audioPg.setMin(0); | |
audioPg.setMax(Integer.valueOf(media.getMediaDuration()) * 1000); | |
setPGTime(0); | |
setMaxTime(); | |
loadSongDetails(media); | |
} | |
private void checkAlreadyPlaying() { | |
if (streamingManager.isPlaying()) { | |
currentSong = streamingManager.getCurrentAudio(); | |
if (currentSong != null) { | |
currentSong.setPlayState(streamingManager.mLastPlaybackState); | |
showMediaInfo(currentSong); | |
notifyAdapter(currentSong); | |
if (streamingManager.mLastPlaybackState == PlaybackState.STATE_BUFFERING) { | |
btn_play.change(true, true); | |
pgPlayPauseLayout.setVisibility(View.VISIBLE); | |
} | |
} | |
} | |
} | |
private void loadSongDetails(MediaMetaData metaData) { | |
text_songName.setText(metaData.getMediaTitle()); | |
text_songAlb.setText(metaData.getMediaArtist()); | |
txt_bottom_SongName.setText(metaData.getMediaTitle()); | |
txt_bottom_SongAlb.setText(metaData.getMediaArtist()); | |
Picasso.with(PlaylistActivity.this).load(metaData.getMediaArt()).into(img_bottom_albArt); | |
Picasso.with(PlaylistActivity.this).load(metaData.getMediaArt()).into(image_songAlbumArt); | |
Picasso.with(getBaseContext()).load(metaData.getMediaArt()).into(new Target() { | |
@Override | |
public void onBitmapFailed(Drawable arg0) { | |
// TODO Auto-generated method stub | |
} | |
@Override | |
public void onBitmapLoaded(Bitmap arg0, Picasso.LoadedFrom arg1) { | |
image_songAlbumArtBlur.setImageBitmap(ImageUtils.fastblur(arg0, 0.1f, 10)); | |
int h = 300; | |
int s = 80; | |
image_mirror.setImageBitmap(ImageUtils.createReflectionBitmapForSingle(arg0, h, s)); | |
} | |
@Override | |
public void onPrepareLoad(Drawable arg0) { | |
// TODO Auto-generated method stub | |
} | |
}); | |
} | |
private void setPGTime(int progress) { | |
try { | |
String timeString = "00.00"; | |
int linePG = 0; | |
currentSong = streamingManager.getCurrentAudio(); | |
if (currentSong != null && progress != Long.parseLong(currentSong.getMediaDuration())) { | |
timeString = DateUtils.formatElapsedTime(progress / 1000); | |
Long audioDuration = Long.parseLong(currentSong.getMediaDuration()); | |
linePG = (int) (((progress / 1000) * 100) / audioDuration); | |
} | |
time_progress_bottom.setText(timeString); | |
time_progress_slide.setText(timeString); | |
lineProgress.setLineProgress(linePG); | |
} catch (NumberFormatException e) { | |
e.printStackTrace(); | |
} | |
} | |
private void setMaxTime() { | |
try { | |
String timeString = DateUtils.formatElapsedTime(Long.parseLong(currentSong.getMediaDuration())); | |
time_total_bottom.setText(timeString); | |
time_total_slide.setText(timeString); | |
} catch (NumberFormatException e) { | |
e.printStackTrace(); | |
} | |
} | |
private PendingIntent getNotificationPendingIntent() { | |
Intent intent = new Intent(context, PlaylistActivity.class); | |
intent.putExtra(PLAYLIST_ID, platList_Id); | |
intent.putExtra(MUSIC_DIR, musicDir); | |
intent.putExtra(ALBUM_ART, albumImg); | |
intent.putExtra(ALBUM_NAME, title); | |
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); | |
return pendingIntent; | |
} | |
} |
Creating Custom View to Show Line Progress
LineProgress.java
/* | |
* This is the source code of DMAudioStreaming for Android v. 1.0.0. | |
* You should have received a copy of the license in this archive (see LICENSE). | |
* Copyright @Dibakar_Mistry([email protected]), 2017. | |
*/ | |
package in.androidhunt.musicDEmo.view; | |
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.util.AttributeSet; | |
import android.view.View; | |
public class LineProgress extends View { | |
public int progress; | |
public Paint paint = new Paint(); | |
public LineProgress(Context context) { | |
super(context); | |
} | |
public LineProgress(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
} | |
public LineProgress(Context context, AttributeSet attrs, int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
super.onDraw(canvas); | |
paint = new Paint(); | |
paint.setColor(Color.TRANSPARENT); | |
canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), paint); | |
paint = new Paint(); | |
paint.setColor(Color.BLACK); | |
canvas.drawRect(0, 0, this.progress, this.getHeight(), paint); | |
} | |
public void setLineProgress(int pg) { | |
int wdt = this.getWidth(); | |
this.progress = pg * (wdt / 100); | |
invalidate(); | |
} | |
} | |
Creating Custom Seek Bar:
Slider.java
/* | |
* This is the source code of DMAudioStreaming for Android v. 1.0.0. | |
* You should have received a copy of the license in this archive (see LICENSE). | |
* Copyright @Dibakar_Mistry([email protected]), 2017. | |
*/ | |
package in.androidhunt.musicDEmo.view; | |
import android.content.Context; | |
import android.content.res.Resources; | |
import android.graphics.Bitmap; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.graphics.drawable.GradientDrawable; | |
import android.graphics.drawable.LayerDrawable; | |
import android.util.AttributeSet; | |
import android.util.TypedValue; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.widget.RelativeLayout; | |
import com.nineoldandroids.view.ViewHelper; | |
import in.androidhunt.musicDEmo.R; | |
public class Slider extends CustomView { | |
private int backgroundColor = Color.parseColor("#000000"); | |
private int backgroundColorLine = Color.parseColor("#000000"); | |
private Ball ball; | |
private Bitmap bitmap; | |
private int max = 100; | |
private int min = 0; | |
private OnValueChangedListener onValueChangedListener; | |
private boolean placedBall = false; | |
private boolean press = false; | |
private int value = 0; | |
public Slider(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
setAttributes(attrs); | |
} | |
/** | |
* Convert Dp to Pixel | |
*/ | |
public static int dpToPx(float dp, Resources resources) { | |
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics()); | |
return (int) px; | |
} | |
public static int getRelativeTop(View myView) { | |
if (myView.getId() == android.R.id.content) | |
return myView.getTop(); | |
else | |
return myView.getTop() + getRelativeTop((View) myView.getParent()); | |
} | |
public static int getRelativeLeft(View myView) { | |
if (myView.getId() == android.R.id.content) | |
return myView.getLeft(); | |
else | |
return myView.getLeft() + getRelativeLeft((View) myView.getParent()); | |
} | |
public int getMax() { | |
return max; | |
} | |
public void setMax(int max) { | |
this.max = max; | |
} | |
public int getMin() { | |
return min; | |
} | |
// GETERS & SETTERS | |
public void setMin(int min) { | |
this.min = min; | |
} | |
public OnValueChangedListener getOnValueChangedListener() { | |
return onValueChangedListener; | |
} | |
public void setOnValueChangedListener( | |
OnValueChangedListener onValueChangedListener) { | |
this.onValueChangedListener = onValueChangedListener; | |
} | |
public int getValue() { | |
return value; | |
} | |
public void setValue(final int value) { | |
if (placedBall == false) | |
post(new Runnable() { | |
@Override | |
public void run() { | |
setValue(value); | |
} | |
}); | |
else { | |
this.value = value; | |
float division = (ball.xFin - ball.xIni) / max; | |
ViewHelper.setX(ball, value * division + getHeight() / 2 - ball.getWidth() / 2); | |
ball.changeBackground(); | |
} | |
} | |
@Override | |
public void invalidate() { | |
ball.invalidate(); | |
super.invalidate(); | |
} | |
@Override | |
public boolean onTouchEvent(MotionEvent event) { | |
isLastTouch = true; | |
if (isEnabled()) { | |
if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { | |
if ((event.getX() <= getWidth() && event.getX() >= 0)) { | |
press = true; | |
// calculate value | |
int newValue = 0; | |
float division = (ball.xFin - ball.xIni) / (max - min); | |
if (event.getX() > ball.xFin) { | |
newValue = max; | |
} else if (event.getX() < ball.xIni) { | |
newValue = min; | |
} else { | |
newValue = min + (int) ((event.getX() - ball.xIni) / division); | |
} | |
if (value != newValue) { | |
value = newValue; | |
if (onValueChangedListener != null) | |
onValueChangedListener.onValueChanged(newValue); | |
} | |
// move ball indicator | |
float x = event.getX(); | |
x = (x < ball.xIni) ? ball.xIni : x; | |
x = (x > ball.xFin) ? ball.xFin : x; | |
ViewHelper.setX(ball, x); | |
ball.changeBackground(); | |
} else { | |
press = false; | |
isLastTouch = false; | |
} | |
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { | |
press = false; | |
} | |
} | |
return true; | |
} | |
@Override | |
public void setBackgroundColor(int color) { | |
backgroundColor = color; | |
backgroundColorLine = makeLineDeselectColor(); | |
if (isEnabled()) | |
beforeBackground = backgroundColor; | |
} | |
/** | |
* Make a dark color to press effect | |
* | |
* @return | |
*/ | |
protected int makeLineDeselectColor() { | |
int r = (this.backgroundColor >> 16) & 0xFF; | |
int g = (this.backgroundColor >> 8) & 0xFF; | |
int b = (this.backgroundColor >> 0) & 0xFF; | |
r = (r - 30 < 0) ? 0 : r - 30; | |
g = (g - 30 < 0) ? 0 : g - 30; | |
b = (b - 30 < 0) ? 0 : b - 30; | |
return Color.argb(128, r, g, b); | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
super.onDraw(canvas); | |
if (!placedBall) { | |
placeBall(); | |
} | |
Paint paint = new Paint(); | |
paint.setColor(backgroundColorLine); | |
paint.setStrokeWidth(dpToPx(3, getResources())); | |
canvas.drawLine(getHeight() / 2, getHeight() / 2, getWidth() - getHeight() / 2, getHeight() / 2, paint); | |
paint.setColor(backgroundColor); | |
float division = (ball.xFin - ball.xIni) / (max - min); | |
int value = this.value - min; | |
canvas.drawLine(getHeight() / 2, getHeight() / 2, value * division + getHeight() / 2, getHeight() / 2, paint); | |
if (press) { | |
paint.setColor(backgroundColor); | |
paint.setAntiAlias(true); | |
canvas.drawCircle(ViewHelper.getX(ball) + ball.getWidth() / 2, getHeight() / 2, getHeight() / 4, paint); | |
} | |
invalidate(); | |
} | |
// Set atributtes of XML to View | |
protected void setAttributes(AttributeSet attrs) { | |
setBackgroundResource(R.drawable.background_transparent); | |
// Set size of view | |
setMinimumHeight(dpToPx(48, getResources())); | |
setMinimumWidth(dpToPx(80, getResources())); | |
// Set background Color | |
// Color by resource | |
int bacgroundColor = attrs.getAttributeResourceValue(ANDROIDXML, "background", -1); | |
if (bacgroundColor != -1) { | |
setBackgroundColor(getResources().getColor(bacgroundColor)); | |
} else { | |
// Color by hexadecimal | |
int background = attrs.getAttributeIntValue(ANDROIDXML, "background", -1); | |
if (background != -1) | |
setBackgroundColor(background); | |
} | |
min = attrs.getAttributeIntValue(MATERIALDESIGNXML, "min", 0); | |
max = attrs.getAttributeIntValue(MATERIALDESIGNXML, "max", 0); | |
value = attrs.getAttributeIntValue(MATERIALDESIGNXML, "value", min); | |
ball = new Ball(getContext()); | |
LayoutParams params = new LayoutParams(dpToPx(15, getResources()), dpToPx(15, getResources())); | |
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE); | |
ball.setLayoutParams(params); | |
addView(ball); | |
} | |
private void placeBall() { | |
ViewHelper.setX(ball, getHeight() / 2 - ball.getWidth() / 2); | |
ball.xIni = ViewHelper.getX(ball); | |
ball.xFin = getWidth() - getHeight() / 2 - ball.getWidth() / 2; | |
ball.xCen = getWidth() / 2 - ball.getWidth() / 2; | |
placedBall = true; | |
} | |
// Event when slider change value | |
public interface OnValueChangedListener { | |
public void onValueChanged(int value); | |
} | |
class Ball extends View { | |
float xIni, xFin, xCen; | |
public Ball(Context context) { | |
super(context); | |
changeBackground(); | |
} | |
public void changeBackground() { | |
setBackgroundResource(R.drawable.background_checkbox); | |
LayerDrawable layer = (LayerDrawable) getBackground(); | |
GradientDrawable shape = (GradientDrawable) layer.findDrawableByLayerId(R.id.shape_bacground); | |
shape.setColor(backgroundColor); | |
} | |
} | |
} |
CustomView.java
/* | |
* This is the source code of DMAudioStreaming for Android v. 1.0.0. | |
* You should have received a copy of the license in this archive (see LICENSE). | |
* Copyright @Dibakar_Mistry([email protected]), 2017. | |
*/ | |
package in.androidhunt.musicDEmo.view; | |
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.util.AttributeSet; | |
import android.widget.RelativeLayout; | |
public class CustomView extends RelativeLayout { | |
final static String MATERIALDESIGNXML = "http://schemas.android.com/apk/res-auto"; | |
final static String ANDROIDXML = "http://schemas.android.com/apk/res/android"; | |
final int disabledBackgroundColor = Color.parseColor("#E2E2E2"); | |
// Indicate if user touched this view the last time | |
public boolean isLastTouch = false; | |
int beforeBackground; | |
boolean animation = false; | |
public CustomView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
} | |
@Override | |
public void setEnabled(boolean enabled) { | |
super.setEnabled(enabled); | |
if (enabled) | |
setBackgroundColor(beforeBackground); | |
else | |
setBackgroundColor(disabledBackgroundColor); | |
invalidate(); | |
} | |
@Override | |
protected void onAnimationStart() { | |
super.onAnimationStart(); | |
animation = true; | |
} | |
@Override | |
protected void onAnimationEnd() { | |
super.onAnimationEnd(); | |
animation = false; | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
super.onDraw(canvas); | |
if (animation) | |
invalidate(); | |
} | |
} |
Creating Custom Image View
SquareImageView.java
/* | |
* Copyright (C) 2015 Antonio Leiva | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package in.androidhunt.musicDEmo.view; | |
import android.content.Context; | |
import android.util.AttributeSet; | |
import android.widget.ImageView; | |
public class SquareImageView extends ImageView { | |
public SquareImageView(Context context) { | |
super(context); | |
} | |
public SquareImageView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
} | |
public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
} | |
@Override | |
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
int width = getMeasuredWidth(); | |
setMeasuredDimension(width, width); | |
} | |
} |
Creating XML Designs For PlaylistActivity
playlist_activity.xml
<?xml version="1.0" encoding="utf-8"?> | |
<com.sothree.slidinguppanel.SlidingUpPanelLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
xmlns:sothree="http://schemas.android.com/apk/res-auto" | |
android:id="@+id/sliding_layout" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:gravity="bottom" | |
sothree:umanoPanelHeight="?attr/actionBarSize" | |
sothree:umanoParalaxOffset="0dp" | |
sothree:umanoShadowHeight="4dp"> | |
<androidx.coordinatorlayout.widget.CoordinatorLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:fitsSystemWindows="true"> | |
<com.google.android.material.appbar.AppBarLayout | |
android:id="@+id/app_bar_layout" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:fitsSystemWindows="true" | |
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> | |
<com.google.android.material.appbar.CollapsingToolbarLayout | |
android:id="@+id/collapsing_toolbar_layout" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:fitsSystemWindows="true" | |
app:contentScrim="?attr/colorPrimary" | |
app:expandedTitleMarginEnd="64dp" | |
app:expandedTitleMarginStart="48dp" | |
app:layout_scrollFlags="scroll|exitUntilCollapsed"> | |
<in.androidhunt.musicDEmo.view.SquareImageView | |
android:id="@+id/image_album" | |
android:layout_width="match_parent" | |
android:layout_height="400dp" | |
android:adjustViewBounds="true" | |
android:background="@android:color/darker_gray" | |
android:scaleType="fitXY" | |
app:layout_collapseMode="parallax" | |
app:layout_collapseParallaxMultiplier="0.7" /> | |
<androidx.appcompat.widget.Toolbar | |
android:id="@+id/tool_bar" | |
android:layout_width="match_parent" | |
android:layout_height="?attr/actionBarSize" | |
android:layout_marginTop="24dp" | |
app:layout_collapseMode="pin" | |
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> | |
<androidx.appcompat.widget.Toolbar | |
android:id="@+id/toolbar_dummy" | |
android:visibility="invisible" | |
android:layout_width="match_parent" | |
android:layout_height="?attr/actionBarSize" | |
app:layout_collapseMode="pin" | |
/> | |
</com.google.android.material.appbar.CollapsingToolbarLayout> | |
</com.google.android.material.appbar.AppBarLayout> | |
<androidx.recyclerview.widget.RecyclerView | |
android:id="@+id/playlist_layout" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:clipToPadding="false" | |
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> | |
<com.google.android.material.floatingactionbutton.FloatingActionButton | |
android:id="@+id/fab" | |
style="@style/FabStyle" | |
app:layout_anchor="@id/app_bar_layout" | |
app:layout_anchorGravity="bottom|right|end" /> | |
<ProgressBar | |
android:id="@+id/avi_loader" | |
style="?android:attr/progressBarStyle" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerHorizontal="true" | |
android:layout_centerVertical="true" | |
android:layout_gravity="center" | |
android:visibility="visible" | |
/> | |
</androidx.coordinatorlayout.widget.CoordinatorLayout> | |
<include | |
android:id="@+id/include_sliding_panel_childtwo" | |
layout="@layout/include_slidingpanel_childtwo" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" /> | |
</com.sothree.slidinguppanel.SlidingUpPanelLayout> | |
include_slidingpanel_childtwo.xml
<?xml version="1.0" encoding="utf-8"?> | |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:id="@+id/dragView" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<ImageView | |
android:id="@+id/image_songAlbumArtBlur" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:scaleType="centerCrop" | |
android:src="@drawable/bg_default_album_art" /> | |
<RelativeLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
> | |
<ImageButton | |
android:id="@+id/down_arrow" | |
android:layout_width="35dp" | |
android:layout_height="35dp" | |
android:layout_marginTop="45dp" | |
android:layout_marginLeft="20dp" | |
android:gravity="start" | |
android:src="@drawable/ic_down_arow" | |
android:background="@drawable/ic_down_arow" | |
/> | |
<LinearLayout | |
android:id="@+id/layout_media_info" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:gravity="center_horizontal" | |
android:orientation="vertical" | |
android:layout_marginTop="30dp" | |
android:padding="15dp"> | |
<TextView | |
android:id="@+id/text_songName" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="My Fev Songs" | |
android:textColor="@android:color/white" | |
android:textSize="18sp" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/text_songAlb" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="5dp" | |
android:text="My Fev Album" | |
android:textColor="@android:color/white" | |
android:textSize="14sp" | |
android:textStyle="bold" /> | |
</LinearLayout> | |
<RelativeLayout | |
android:layout_width="240dp" | |
android:layout_height="380dp" | |
android:layout_below="@+id/layout_media_info" | |
android:layout_centerHorizontal="true" | |
android:layout_marginTop="20dp"> | |
<LinearLayout | |
android:id="@+id/linear_layout_music_cover" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:clickable="true" | |
android:gravity="center" | |
android:orientation="vertical"> | |
<ImageView | |
android:id="@+id/image_songAlbumArt" | |
android:layout_width="@dimen/cover_width_height" | |
android:layout_height="250dp" | |
android:scaleType="fitXY" | |
/> | |
<ImageView | |
android:id="@+id/cover_mirror" | |
android:layout_width="@dimen/cover_width_height" | |
android:layout_height="@dimen/cover_mirror_height" | |
android:scaleType="fitXY" | |
android:layout_marginTop="@dimen/cover_mirror_margin_top" | |
/> | |
</LinearLayout> | |
</RelativeLayout> | |
<include | |
android:id="@+id/bottom_palyLayout" | |
layout="@layout/include_slidepanelchildtwo_bottomview" | |
android:layout_width="match_parent" | |
android:layout_height="@dimen/bottom_control_panel" | |
android:layout_alignParentBottom="true" | |
android:gravity="center_vertical" | |
android:orientation="vertical" /> | |
<include | |
android:id="@+id/slideBottomView" | |
layout="@layout/include_slidepanelchildtwo_topviewtwo" | |
android:layout_width="match_parent" | |
android:layout_height="?attr/actionBarSize" | |
android:visibility="invisible" /> | |
</RelativeLayout> | |
</RelativeLayout> |
include_slidepanelchildtwo_topviewtwo.xml
<?xml version="1.0" encoding="utf-8"?> | |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:playpauseview="http://schemas.android.com/apk/res-auto" | |
android:layout_width="match_parent" | |
android:layout_height="?attr/actionBarSize" | |
android:background="@color/md_blue_grey_100" | |
android:elevation="4dp" | |
android:gravity="center" | |
android:orientation="horizontal"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="?attr/actionBarSize" | |
android:layout_toLeftOf="@+id/rel_bottombar_moreicon" | |
android:elevation="4dp"> | |
<ImageView | |
android:id="@+id/img_bottom_albArt" | |
android:layout_width="?attr/actionBarSize" | |
android:layout_height="?attr/actionBarSize" | |
android:scaleType="centerCrop" | |
android:src="@drawable/bg_default_album_art"> | |
</ImageView> | |
<RelativeLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:gravity="center" | |
android:orientation="vertical" | |
android:paddingLeft="5dp" | |
android:paddingRight="5dp"> | |
<TextView | |
android:id="@+id/txt_bottom_SongName" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:ellipsize="marquee" | |
android:focusable="true" | |
android:focusableInTouchMode="false" | |
android:freezesText="true" | |
android:marqueeRepeatLimit="marquee_forever" | |
android:scrollHorizontally="true" | |
android:singleLine="true" | |
android:text="" | |
android:textAppearance="?android:attr/textAppearanceMedium" | |
android:textColor="@color/md_blue_grey_700" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/txt_bottom_SongAlb" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="2dp" | |
android:singleLine="true" | |
android:text="" | |
android:textAppearance="?android:attr/textAppearanceSmall" | |
android:textColor="@color/md_blue_grey_700" | |
android:textStyle="normal" /> | |
</LinearLayout> | |
<in.androidhunt.musicDEmo.view.LineProgress | |
android:id="@+id/lineProgress" | |
android:layout_width="match_parent" | |
android:layout_height="3dp" | |
android:layout_alignParentTop="true" /> | |
</RelativeLayout> | |
</LinearLayout> | |
<LinearLayout | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_alignParentRight="true" | |
android:layout_centerVertical="true" | |
android:layout_marginLeft="5dp" | |
android:layout_marginRight="10dp" | |
android:gravity="center"> | |
<TextView | |
android:id="@+id/slidepanel_time_progress_bottom" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:paddingLeft="2dp" | |
android:paddingRight="2dp" | |
android:singleLine="true" | |
android:text="00.00" | |
android:textColor="@color/md_blue_grey_700" | |
android:textSize="14sp" /> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:paddingLeft="2dp" | |
android:paddingRight="2dp" | |
android:text="/" | |
android:textColor="@color/md_blue_grey_700" | |
android:textSize="14sp" /> | |
<TextView | |
android:id="@+id/slidepanel_time_total_bottom" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:paddingLeft="2dp" | |
android:paddingRight="2dp" | |
android:singleLine="true" | |
android:text="00.00" | |
android:textColor="@color/md_blue_grey_700" | |
android:textSize="20sp" | |
android:textStyle="bold" /> | |
</LinearLayout> | |
<RelativeLayout | |
android:id="@+id/rel_bottombar_moreicon" | |
android:layout_width="96dp" | |
android:layout_height="48dp" | |
android:layout_alignParentRight="true" | |
android:layout_centerVertical="true" | |
android:layout_marginLeft="5dp" | |
android:visibility="gone"> | |
<ImageView | |
android:id="@+id/bottombar_img_Favorite" | |
android:layout_width="48dp" | |
android:layout_height="match_parent" | |
android:layout_centerVertical="true" | |
android:layout_toLeftOf="@+id/bottombar_moreicon" | |
android:background="@drawable/bar_selector_white" | |
android:clickable="true" | |
android:scaleType="centerInside" /> | |
<ImageView | |
android:id="@+id/bottombar_moreicon" | |
android:layout_width="48dp" | |
android:layout_height="match_parent" | |
android:layout_alignParentRight="true" | |
android:layout_centerVertical="true" | |
android:background="@drawable/bar_selector_white" | |
android:clickable="true" | |
android:scaleType="centerInside" /> | |
</RelativeLayout> | |
</RelativeLayout> |
include_slidepanelchildtwo_bottomview.xml
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:orientation="vertical"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:gravity="center" | |
android:orientation="vertical" | |
android:paddingLeft="8dp" | |
android:paddingRight="8dp"> | |
<LinearLayout | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:gravity="center"> | |
<TextView | |
android:id="@+id/slidepanel_time_progress" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:paddingLeft="2dp" | |
android:paddingRight="2dp" | |
android:singleLine="true" | |
android:text="00.00" | |
android:textColor="@android:color/white" | |
android:textSize="14sp" /> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:paddingLeft="2dp" | |
android:paddingRight="2dp" | |
android:text="/" | |
android:textColor="@android:color/white" | |
android:textSize="14sp" /> | |
<TextView | |
android:id="@+id/slidepanel_time_total" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:paddingLeft="2dp" | |
android:paddingRight="2dp" | |
android:singleLine="true" | |
android:text="00.00" | |
android:textColor="@android:color/white" | |
android:textSize="20sp" | |
android:textStyle="bold" /> | |
</LinearLayout> | |
<in.androidhunt.musicDEmo.view.Slider | |
android:id="@+id/audio_progress_control" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:layout_toLeftOf="@+id/slidepanel_time_total" | |
android:layout_toRightOf="@+id/slidepanel_time_progress" | |
android:background="@android:color/white" | |
android:max="100" | |
android:min="0" /> | |
</LinearLayout> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="120dp" | |
android:gravity="center_vertical" | |
android:orientation="horizontal"> | |
<ImageView | |
android:id="@+id/btn_backward" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_weight="1" | |
android:background="@drawable/bar_selector_white" | |
android:gravity="center_vertical|right" | |
android:paddingBottom="15dp" | |
android:paddingTop="15dp" | |
android:src="@drawable/ic_rew_dark" /> | |
<RelativeLayout | |
android:layout_width="0dp" | |
android:layout_height="match_parent" | |
android:layout_weight="1"> | |
<RelativeLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<com.ohoussein.playpause.PlayPauseView | |
android:id="@+id/btn_play" | |
android:layout_width="60dp" | |
android:layout_height="60dp" | |
android:layout_centerInParent="true" | |
android:clickable="true" | |
android:stateListAnimator="@drawable/button_elevation" | |
/> | |
</RelativeLayout> | |
<RelativeLayout | |
android:id="@+id/pgPlayPauseLayout" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:clickable="true" | |
android:visibility="invisible"> | |
<ProgressBar | |
android:id="@+id/pgPlayPause" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
style="?android:attr/progressBarStyle" | |
android:layout_centerInParent="true" /> | |
</RelativeLayout> | |
</RelativeLayout> | |
<ImageView | |
android:id="@+id/btn_forward" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_weight="1" | |
android:background="@drawable/bar_selector_white" | |
android:gravity="center_vertical|right" | |
android:paddingBottom="15dp" | |
android:paddingTop="15dp" | |
android:src="@drawable/ic_fwd_dark" /> | |
</LinearLayout> | |
</LinearLayout> |
Creating Adapter For Music Playlist
PlayListAdapter.java
package in.androidhunt.musicDEmo.adapter; | |
import android.content.Context; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.TextView; | |
import androidx.annotation.NonNull; | |
import androidx.recyclerview.widget.RecyclerView; | |
import java.util.List; | |
import java.util.concurrent.TimeUnit; | |
import dm.audiostreamer.MediaMetaData; | |
import in.androidhunt.musicDEmo.R; | |
public class PlayListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { | |
private final List<MediaMetaData> songsList; | |
private final String title; | |
private final String musicDir; | |
private final Context context; | |
private SetOnclickListner onClickListener; | |
public PlayListAdapter(Context context, List<MediaMetaData> songList, String title, String musicDir) { | |
this.songsList = songList; | |
this.title = title; | |
this.musicDir = musicDir; | |
this.context = context; | |
} | |
@NonNull | |
@Override | |
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { | |
if (viewType == 0) { | |
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.albuminfo_item, parent, false); | |
return new ArtistViewHolder(v); | |
} else { | |
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.song_item, parent, false); | |
return new ViewHolder(v); | |
} | |
} | |
@Override | |
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { | |
if (holder instanceof ViewHolder) { | |
final MediaMetaData m = songsList.get(position - 1); | |
Long duration = Long.parseLong(m.getMediaDuration()); | |
int milliseconds = (int) TimeUnit.SECONDS.toMillis(duration); | |
int minutes = (int) ((milliseconds / (1000 * 60)) % 60); | |
int seconds = (int) ((milliseconds / 1000) % 60); | |
if (Integer.toString(seconds).length() == 1) { | |
String sec = "0" + Integer.toString(seconds); | |
((ViewHolder) holder).duration.setText(Integer.toString(minutes) + ":" + sec); | |
} else { | |
((ViewHolder) holder).duration.setText(Integer.toString(minutes) + ":" + Integer.toString(seconds)); | |
} | |
// Picasso.with(context).load(m.getThumbnailUrl()).error(R.mipmap.ic_launcher) | |
// .into(((ViewHolder) holder).imageView); | |
((ViewHolder) holder).songNo.setText(position + ""); | |
String tit = m.getMediaTitle(); | |
((ViewHolder) holder).title.setText(tit); | |
((ViewHolder) holder).itemView.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
onClickListener.onClickSong(m, position - 1); | |
} | |
}); | |
} else { | |
((ArtistViewHolder) holder).title.setText(title); | |
((ArtistViewHolder) holder).artist.setText(musicDir); | |
((ArtistViewHolder) holder).songs.setText(songsList.size() + " songs"); | |
} | |
} | |
@Override | |
public int getItemViewType(int position) { | |
return position; | |
} | |
@Override | |
public int getItemCount() { | |
return songsList.size() + 1; | |
} | |
public void setOnClickListener(SetOnclickListner onClickListener) { | |
this.onClickListener = onClickListener; | |
} | |
public void notifyPlayState(MediaMetaData metaData) { | |
if (this.songsList != null && metaData != null) { | |
int index = this.songsList.indexOf(metaData); | |
//TODO SOMETIME INDEX RETURN -1 THOUGH THE OBJECT PRESENT IN THIS LIST | |
if (index == -1) { | |
for (int i = 0; i < this.songsList.size(); i++) { | |
if (this.songsList.get(i).getMediaId().equalsIgnoreCase(metaData.getMediaId())) { | |
index = i; | |
break; | |
} | |
} | |
} | |
if (index > 0 && index < this.songsList.size()) { | |
this.songsList.set(index, metaData); | |
} | |
} | |
notifyDataSetChanged(); | |
} | |
public interface SetOnclickListner { | |
void onClickSong(MediaMetaData album, int postion); | |
} | |
public class ViewHolder extends RecyclerView.ViewHolder { | |
TextView songNo; | |
TextView title; | |
TextView duration; | |
public ViewHolder(View v) { | |
super(v); | |
songNo = (TextView) v.findViewById(R.id.itemThumbnail_View); | |
title = (TextView) v.findViewById(R.id.itemVideoTitle_View); | |
duration = (TextView) v.findViewById(R.id.dur_ation); | |
} | |
} | |
public class ArtistViewHolder extends RecyclerView.ViewHolder { | |
TextView artist; | |
TextView title; | |
TextView songs; | |
public ArtistViewHolder(View v) { | |
super(v); | |
artist = (TextView) v.findViewById(R.id.artist_name); | |
title = (TextView) v.findViewById(R.id.album_name); | |
songs = (TextView) v.findViewById(R.id.s_info); | |
} | |
} | |
} |
Creating playlist item xml design
song_item.xml
<?xml version="1.0" encoding="utf-8"?> | |
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
> | |
<RelativeLayout | |
android:id="@+id/itemThumbnailViewContainer" | |
android:layout_width="wrap_content" | |
android:layout_height="60dp" | |
android:layout_marginRight="6dp" | |
android:orientation="horizontal"> | |
<TextView | |
android:id="@+id/itemThumbnail_View" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_alignParentLeft="true" | |
android:layout_centerVertical="true" | |
android:layout_marginLeft="30dp" | |
android:text="1" | |
android:textAlignment="center" | |
android:textColor="@android:color/black" | |
android:textStyle="normal" | |
/> | |
<TextView | |
android:id="@+id/itemVideoTitle_View" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_alignParentLeft="true" | |
android:layout_centerVertical="true" | |
android:layout_marginLeft="70dp" | |
android:layout_marginRight="5dp" | |
android:maxLines="1" | |
android:text="Pranamam pranamam" | |
android:textAppearance="?android:attr/textAppearanceLarge" | |
android:textColor="@android:color/black" | |
android:textSize="16sp" /> | |
<TextView | |
android:id="@+id/dur_ation" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_alignParentRight="true" | |
android:layout_centerVertical="true" | |
android:layout_marginRight="8dp" | |
android:singleLine="true" | |
android:text="1:20" | |
android:textAppearance="?android:attr/textAppearanceLarge" | |
android:textColor="@android:color/black" | |
android:textSize="16sp" /> | |
</RelativeLayout> | |
</FrameLayout> |
albuminfo_item.xml
<?xml version="1.0" encoding="utf-8"?> | |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:background="@android:color/white"> | |
<TextView | |
android:id="@+id/album_name" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginLeft="15dp" | |
android:layout_marginTop="20dp" | |
android:gravity="left|center" | |
android:maxLines="1" | |
android:text="Rabhasa" | |
android:textColor="@android:color/black" | |
android:textSize=&quo |