自定义android 音乐通知栏 ——可伸缩扩展

Android custom notification for music player Example

 

In this tutorial, you will learn how to create Custom Notifications in your Android music player application. A notification is a message you can display to the user in the status bar outside of your Android application. Notifications can be clicked to perform an action or to open a new activity. We will be creating a custom notification that is usually used by music player apps.
Lets get started.

Create an empty android application project and copy the following contents to MainActivity.java :

package com.tutorialsface.customnotification;
 
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
 
public class MainActivity extends ActionBarActivity {
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
 
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true ;
}
 
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true ;
}
return super .onOptionsItemSelected(item);
}
 
public void startService(View v) {
Intent serviceIntent = new Intent(MainActivity. this , NotificationService. class );
serviceIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(serviceIntent);
}
}

Change the contents of the layout file activity_main.xml:

< RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
     xmlns:tools = "http://schemas.android.com/tools"
     android:layout_width = "match_parent"
     android:layout_height = "match_parent"
     tools:context = "com.tutorialsface.customnotification.MainActivity" >
 
     < TextView
         android:id = "@+id/textView1"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:layout_alignParentTop = "true"
         android:layout_centerHorizontal = "true"
         android:layout_marginTop = "53dp"
         android:text = "Custom Notification Tutorial" />
 
     < Button
         android:id = "@+id/button1"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:layout_centerHorizontal = "true"
         android:layout_centerVertical = "true"
         android:onClick = "startService"
         android:text = "Show Notification" />
 
</ RelativeLayout >

In music player, playback of songs has to be done within a service which runs in background even after the application is closed. We will create such service to handle the inputs given through the buttons shown by the Notification layout.

To learn more about Android Services you can follow this.

Lets create a service now.

Create a new java file named NotificationService.java and extend it for Service as shown below:

package com.tutorialsface.customnotification;
 
import android.os.IBinder;
import android.app.Service;
import android.content.Intent;
 
public class NotificationService extends Service {
 
@Override
public void onDestroy() {
super .onDestroy();
}
 
@Override
public IBinder onBind(Intent intent) {
return null ;
}
 
}

Override the method OnStartCommand() of Service class.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
showNotification();
Toast.makeText( this , "Service Started" , Toast.LENGTH_SHORT).show();
 
} else if (intent.getAction().equals(Constants.ACTION.PREV_ACTION)) {
Toast.makeText( this , "Clicked Previous" , Toast.LENGTH_SHORT).show();
Log.i(LOG_TAG, "Clicked Previous" );
} else if (intent.getAction().equals(Constants.ACTION.PLAY_ACTION)) {
Toast.makeText( this , "Clicked Play" , Toast.LENGTH_SHORT).show();
Log.i(LOG_TAG, "Clicked Play" );
} else if (intent.getAction().equals(Constants.ACTION.NEXT_ACTION)) {
Toast.makeText( this , "Clicked Next" , Toast.LENGTH_SHORT).show();
Log.i(LOG_TAG, "Clicked Next" );
} else if (intent.getAction().equals(
Constants.ACTION.STOPFOREGROUND_ACTION)) {
Log.i(LOG_TAG, "Received Stop Foreground Intent" );
Toast.makeText( this , "Service Stoped" , Toast.LENGTH_SHORT).show();
stopForeground( true );
stopSelf();
}
return START_STICKY;
}

You will get some errors after adding the above code. So to resolve them, create a new class named Constants to store all the required constant variables.

Copy the following code for Constants.java:

package com.tutorialsface.customnotification;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
 
public class Constants {
public interface ACTION {
public static String MAIN_ACTION = "com.marothiatechs.customnotification.action.main" ;
public static String INIT_ACTION = "com.marothiatechs.customnotification.action.init" ;
public static String PREV_ACTION = "com.marothiatechs.customnotification.action.prev" ;
public static aString PLAY_ACTION = "com.marothiatechs.customnotification.action.play" ;
public static String NEXT_ACTION = "com.marothiatechs.customnotification.action.next" ;
public static String STARTFOREGROUND_ACTION = "com.marothiatechs.customnotification.action.startforeground" ;
public static String STOPFOREGROUND_ACTION = "com.marothiatechs.customnotification.action.stopforeground" ;
 
}
 
public interface NOTIFICATION_ID {
public static int FOREGROUND_SERVICE = 101 ;
}
 
public static Bitmap getDefaultAlbumArt(Context context) {
Bitmap bm = null ;
BitmapFactory.Options options = new BitmapFactory.Options();
try {
bm = BitmapFactory.decodeResource(context.getResources(),
R.drawable.default_album_art, options);
} catch (Error ee) {
} catch (Exception e) {
}
return bm;
}
 
}

Now create a new method inside your NotificationService.java with the name showNotification() and copy the content as shown below:

Notification status;
private final String LOG_TAG = "NotificationService" ;
 
private void showNotification() {
// Using RemoteViews to bind custom layouts into Notification
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.status_bar);
RemoteViews bigViews = new RemoteViews(getPackageName(),
R.layout.status_bar_expanded);
 
// showing default album image
views.setViewVisibility(R.id.status_bar_icon, View.VISIBLE);
views.setViewVisibility(R.id.status_bar_album_art, View.GONE);
bigViews.setImageViewBitmap(R.id.status_bar_album_art,
Constants.getDefaultAlbumArt( this ));
 
Intent notificationIntent = new Intent( this , MainActivity. class );
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity( this , 0 ,
notificationIntent, 0 );
 
Intent previousIntent = new Intent( this , NotificationService. class );
previousIntent.setAction(Constants.ACTION.PREV_ACTION);
PendingIntent ppreviousIntent = PendingIntent.getService( this , 0 ,
previousIntent, 0 );
 
Intent playIntent = new Intent( this , NotificationService. class );
playIntent.setAction(Constants.ACTION.PLAY_ACTION);
PendingIntent pplayIntent = PendingIntent.getService( this , 0 ,
playIntent, 0 );
 
Intent nextIntent = new Intent( this , NotificationService. class );
nextIntent.setAction(Constants.ACTION.NEXT_ACTION);
PendingIntent pnextIntent = PendingIntent.getService( this , 0 ,
nextIntent, 0 );
 
Intent closeIntent = new Intent( this , NotificationService. class );
closeIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
PendingIntent pcloseIntent = PendingIntent.getService( this , 0 ,
closeIntent, 0 );
 
views.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
 
views.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);
 
views.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);
 
views.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);
 
views.setImageViewResource(R.id.status_bar_play,
R.drawable.apollo_holo_dark_pause);
bigViews.setImageViewResource(R.id.status_bar_play,
R.drawable.apollo_holo_dark_pause);
 
views.setTextViewText(R.id.status_bar_track_name, "Song Title" );
bigViews.setTextViewText(R.id.status_bar_track_name, "Song Title" );
 
views.setTextViewText(R.id.status_bar_artist_name, "Artist Name" );
bigViews.setTextViewText(R.id.status_bar_artist_name, "Artist Name" );
 
bigViews.setTextViewText(R.id.status_bar_album_name, "Album Name" );
 
status = new Notification.Builder( this ).build();
status.contentView = views;
status.bigContentView = bigViews;
status.flags = Notification.FLAG_ONGOING_EVENT;
status.icon = R.drawable.ic_launcher;
status.contentIntent = pendingIntent;
startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE, status);
}

You need to add the following imports for the new references in the method we just defined:

import android.app.Notification;
import android.app.PendingIntent;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;

 

In showNotification() method we created a new notification and added our custom layouts named status_layout.xml and status_bar_expanded.xml

status_bar.xml is the layout for small notification while status_layout_expanded.xml is for the big layout.

Leta create these two layout files and move them to layouts folder in the res directory of your project:

status_bar.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 = "horizontal" >
 
     < ImageView
         android:id = "@+id/status_bar_album_art"
         android:layout_width = "@dimen/status_bar_album_art"
         android:layout_height = "@dimen/status_bar_album_art"
         android:gravity = "center" />
 
     < ImageView
         android:id = "@+id/status_bar_icon"
         android:layout_width = "@dimen/status_bar_album_art"
         android:layout_height = "@dimen/status_bar_album_art"
         android:background = "@drawable/status_bg"
         android:scaleType = "center"
         android:src = "@drawable/ic_launcher"
         android:visibility = "gone" />
 
     < LinearLayout
         android:layout_width = "0dp"
         android:layout_height = "wrap_content"
         android:layout_gravity = "center_vertical"
         android:layout_weight = "1"
         android:orientation = "vertical"
         android:paddingLeft = "@dimen/status_bar_button_info_container_padding_left" >
 
         < TextView
             android:id = "@+id/status_bar_track_name"
             android:layout_width = "wrap_content"
             android:layout_height = "wrap_content"
             android:textColor = "@color/white"
             android:textSize = "@dimen/text_size_medium"
             android:textStyle = "bold" />
 
         < TextView
             android:id = "@+id/status_bar_artist_name"
             android:layout_width = "wrap_content"
             android:layout_height = "wrap_content" />
 
     </ LinearLayout >
 
     < ImageButton
         android:id = "@+id/status_bar_play"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:contentDescription = "@string/cd_play" />
 
     < ImageButton
         android:id = "@+id/status_bar_next"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:contentDescription = "@string/cd_next"
         android:src = "@drawable/apollo_holo_dark_next" />
 
     < ImageButton
         android:id = "@+id/status_bar_collapse"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:src = "@drawable/apollo_holo_dark_notifiation_bar_collapse" />
 
</ LinearLayout >

status_bar_expanded.xml

 
<? xml version = "1.0" encoding = "utf-8" ?>
< RelativeLayout android:id = "@+id/notificationbg" android:layout_width = "fill_parent" android:layout_height = "128.0dip"
    xmlns:android = "http://schemas.android.com/apk/res/android" >
    
     < ImageView
         android:id = "@+id/status_bar_album_art"
         android:layout_width = "@dimen/notification_expanded_height"
         android:layout_height = "@dimen/notification_expanded_height"
         android:scaleType = "centerCrop"
         android:layout_alignParentLeft = "true"
         android:layout_alignParentBottom = "true" />
     
     < LinearLayout
         android:gravity = "center_vertical"
         android:orientation = "horizontal"
         android:id = "@+id/buttons"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:divider = "?android:listDivider"
         android:layout_toRightOf = "@id/status_bar_album_art"
         android:layout_alignParentRight = "true"
         android:layout_alignParentBottom = "true"
         android:showDividers = "middle"
         android:dividerPadding = "12.0dip" >
        < ImageButton
            android:id = "@+id/status_bar_prev"
            android:background = "?android:selectableItemBackground"
            android:padding = "10.0dip"
            android:layout_width = "0.0dip"
            android:layout_height = "@dimen/play_controls_notification"
            android:src = "@drawable/apollo_holo_dark_prev"
            android:scaleType = "fitCenter"
            android:layout_weight = "1.0" />
        < ImageButton
            android:id = "@+id/status_bar_play"
            android:background = "?android:selectableItemBackground"
            android:padding = "10.0dip"
            android:layout_width = "0.0dip"
            android:layout_height = "@dimen/play_controls_notification"
            android:src = "@drawable/apollo_holo_dark_play"
            android:scaleType = "fitCenter"
            android:layout_weight = "1.0" />
        < ImageButton android:id = "@+id/status_bar_next"
            android:background = "?android:selectableItemBackground"
            android:padding = "10.0dip"
            android:layout_width = "0.0dip"
            android:layout_height = "@dimen/play_controls_notification"
            android:src = "@drawable/apollo_holo_dark_next"
            android:scaleType = "fitCenter"
            android:layout_weight = "1.0" />
     </ LinearLayout >
     < ImageView
         android:background = "?android:dividerHorizontal"
         android:layout_width = "wrap_content"
         android:layout_height = "1.0px"
         android:layout_toRightOf = "@id/status_bar_album_art"
         android:layout_above = "@+id/buttons"
         android:layout_alignParentRight = "true" />
     < ImageButton
         android:id = "@id/status_bar_collapse"
         android:background = "?android:selectableItemBackground"
         android:padding = "8.0dip"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:src = "@drawable/apollo_holo_dark_notifiation_bar_collapse"
         android:layout_alignParentTop = "true"
         android:layout_alignParentRight = "true" />
     < LinearLayout
         android:layout_gravity = "center_vertical"
         android:orientation = "vertical"
         android:id = "@+id/textarea"
         android:paddingLeft = "@dimen/notification_padding"
         android:paddingTop = "8.0dip"
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content"
         android:layout_toLeftOf = "@id/status_bar_collapse"
         android:layout_toRightOf = "@id/status_bar_album_art"
         android:layout_alignParentTop = "true" >
         < TextView
            android:ellipsize = "marquee"
            android:layout_gravity = "left"
            android:id = "@+id/status_bar_track_name"
            android:focusable = "true"
            android:fadingEdge = "horizontal"
            android:layout_width = "fill_parent"
            android:layout_height = "wrap_content"
            android:singleLine = "true"
             />
         < TextView
            android:ellipsize = "marquee"
            android:layout_gravity = "left"
            android:id = "@+id/status_bar_artist_name"
            android:fadingEdge = "horizontal"
            android:layout_width = "fill_parent"
            android:layout_height = "wrap_content"
            android:maxLines = "1"
             />
         < TextView
            android:ellipsize = "marquee"
            android:layout_gravity = "left"
            android:id = "@+id/status_bar_album_name"
            android:fadingEdge = "horizontal"
            android:layout_width = "fill_parent"
            android:layout_height = "wrap_content"
            android:maxLines = "1"
             />
     </ LinearLayout >
</ RelativeLayout >

 

You will see many errors in each of the files we created but don’t worry, we will resolve all of them.
Create a folder named drawable inside /res directory of your android project and copy the following file:

status_bg.xml

<? xml version = "1.0" encoding = "utf-8" ?>
< bitmap xmlns:android = "http://schemas.android.com/apk/res/android"
     android:src = "@drawable/notify_panel_notification_icon_bg"
     android:tileMode = "repeat" />

 
Now copy the following three files in /res/values directory in your project.

strings.xml:

<? xml version = "1.0" encoding = "utf-8" ?>
< resources xmlns:xliff = "urn:oasis:names:tc:xliff:document:1.2" >
 
     <!-- App name -->
     < string name = "app_name" >Music Notification</ string >
     < string name = "app_version_number" >1.0</ string >
     < string name = "menu_settings" >Settings</ string >
 
     < string name = "cd_repeat" >Repeat one or all</ string >
     < string name = "cd_previous" >Skip backwards</ string >
     < string name = "cd_play" >Play and pause</ string >
     < string name = "cd_next" >Skip forwards</ string >
 
</ resources >

colors.xml

<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
 
     <!-- A transparent black -->
     < color name = "transparent_black" >#aa000000</ color >
 
     <!-- selected tab text -->
     < color name = "selected_tabtext" >#bb000000</ color >
 
     <!-- non selected tab text -->
     < color name = "unselected_tabtext" >#77000000</ color >
     < color name = "shuffle_grey" >#ffdedede</ color >
     < color name = "background_grey" >#ffdedede</ color >
 
     <!-- Transparent -->
     < color name = "transparent" >#00000000</ color >
 
     <!-- Black -->
     < color name = "black" >#ff000000</ color >
 
     <!-- White -->
     < color name = "white" >#ffffffff</ color >
 
</ resources >

dimens.xml

<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
 
     <!-- Text sizes -->
     < dimen name = "text_size_extra_micro" >10sp</ dimen >
     < dimen name = "text_size_micro" >12sp</ dimen >
     < dimen name = "text_size_small" >14sp</ dimen >
     < dimen name = "text_size_medium" >16sp</ dimen >
     < dimen name = "text_size_large" >18sp</ dimen >
     
     <!-- Nofication bar button -->
     < dimen name = "status_bar_button_width_height" >48dp</ dimen >
     < dimen name = "status_bar_album_art" >64dp</ dimen >
     < dimen name = "status_bar_button_info_container_padding_left" >11dp</ dimen >
     < dimen name = "notification_expanded_height" >128.0dip</ dimen >
     < dimen name = "play_controls_notification" >48.0dip</ dimen >
     < dimen name = "notification_padding" >8.0dip</ dimen >
 
</ resources >

Copy these image files into /res/drawable-hdpi folder your project.
notify_panel_notification_icon_bg

apollo_holo_dark_prev

apollo_holo_dark_play

apollo_holo_dark_pause

apollo_holo_dark_notifiation_bar_collapse

apollo_holo_dark_next

default_album_art

ic_launcher
 
Now modify the AndroidManifest.xml as follows:

<? xml version = "1.0" encoding = "utf-8" ?>
< manifest xmlns:android = "http://schemas.android.com/apk/res/android"
     package = "com.tutorialsface.customnotification"
     android:versionCode = "1"
     android:versionName = "1.0" >
 
     < uses-sdk
         android:minSdkVersion = "8"
         android:targetSdkVersion = "21" />
 
     < application
         android:allowBackup = "true"
         android:icon = "@drawable/ic_launcher"
         android:label = "@string/app_name"
         android:theme = "@style/AppTheme" >
         < activity
             android:name = "com.tutorialsface.customnotification.MainActivity"
             android:label = "@string/app_name" >
             < intent-filter >
                 < action android:name = "android.intent.action.MAIN" />
 
                 < category android:name = "android.intent.category.LAUNCHER" />
             </ intent-filter >
         </ activity >
 
         < service android:name = "com.tutorialsface.customnotification.NotificationService" />
     </ application >
 
</ manifest >

Now run the application.

The Screenshot for the final app displaying custom Notification for a Music Player:

Music Player cutome notification

Music Player custom notification

转载于:https://www.cnblogs.com/qianyukun/p/9045229.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值