Added AppMsg library to the librarys-folder

This commit is contained in:
Daniel Haß
2014-02-20 22:53:47 +01:00
parent 4839172f5b
commit 15757a2a32
11 changed files with 1430 additions and 0 deletions

View File

@@ -0,0 +1,587 @@
/*
* Copyright 2012 Evgeny Shishkin
*
* 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 com.devspark.appmsg;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.TextView;
/**
* In-layout notifications. Based on {@link android.widget.Toast} notifications
* and article by Cyril Mottier (http://android.cyrilmottier.com/?p=773).
*
* @author e.shishkin
*/
public class AppMsg {
/**
* Show the view or text notification for a short period of time. This time
* could be user-definable. This is the default.
*
* @see #setDuration
*/
public static final int LENGTH_SHORT = 3000;
/**
* Show the view or text notification for a long period of time. This time
* could be user-definable.
*
* @see #setDuration
*/
public static final int LENGTH_LONG = 5000;
/**
* <p>Show the view or text notification for an undefined amount of time
* -Usually until an invocation of {@link #cancel()}, {@link #cancelAll(android.app.Activity)},
* {@link #cancelAll()} or {@link android.app.Activity#onDestroy()}-,
* stacking on top of any other {@link com.devspark.appmsg.AppMsg} with this duration.</p>
*
* <p><b>Note</b>: You are responsible
* for calling {@link #cancel()} on such {@link com.devspark.appmsg.AppMsg}.</p>
*
* @see #setDuration
*/
public static final int LENGTH_STICKY = -1;
/**
* Lowest priority, messages with this priority will be showed after all messages with priority
* {@link #PRIORITY_HIGH} and {@link #PRIORITY_NORMAL} have been shown.
*
* @see #setPriority(int)
*/
public static final int PRIORITY_LOW = Integer.MIN_VALUE;
/**
* Normal priority, messages with this priority will be showed after all messages with priority
* {@link #PRIORITY_HIGH} but before {@link #PRIORITY_LOW} have been shown.
*
* @see #setPriority(int)
*/
public static final int PRIORITY_NORMAL = 0;
/**
* Highest priority, messages with this priority will be showed before any other message.
*
* @see #setPriority(int)
*/
public static final int PRIORITY_HIGH = Integer.MAX_VALUE;
/**
* Show the text notification for a long period of time with a negative style.
*/
public static final Style STYLE_ALERT = new Style(LENGTH_LONG, R.color.alert);
/**
* Show the text notification for a short period of time with a positive style.
*/
public static final Style STYLE_CONFIRM = new Style(LENGTH_SHORT, R.color.confirm);
/**
* Show the text notification for a short period of time with a neutral style.
*/
public static final Style STYLE_INFO = new Style(LENGTH_SHORT, R.color.info);
private final Activity mActivity;
private int mDuration = LENGTH_SHORT;
private View mView;
private ViewGroup mParent;
private LayoutParams mLayoutParams;
private boolean mFloating;
Animation mInAnimation, mOutAnimation;
int mPriority = PRIORITY_NORMAL;
/**
* Construct an empty AppMsg object. You must call {@link #setView} before
* you can call {@link #show}.
*
* @param activity {@link android.app.Activity} to use.
*/
public AppMsg(Activity activity) {
mActivity = activity;
}
/**
* Make a {@link AppMsg} that just contains a text view.
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param text The text to show. Can be formatted text.
* @param style The style with a background and a duration.
*/
public static AppMsg makeText(Activity context, CharSequence text, Style style) {
return makeText(context, text, style, R.layout.app_msg);
}
/**
* @author mengguoqiang 扩展支持设置字体大小
* Make a {@link AppMsg} that just contains a text view.
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param text The text to show. Can be formatted text.
* @param style The style with a background and a duration.
*/
public static AppMsg makeText(Activity context, CharSequence text, Style style, float textSize) {
return makeText(context, text, style, R.layout.app_msg, textSize);
}
/**
* Make a {@link AppMsg} with a custom layout. The layout must have a {@link TextView} com id {@link android.R.id.message}
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param text The text to show. Can be formatted text.
* @param style The style with a background and a duration.
*/
public static AppMsg makeText(Activity context, CharSequence text, Style style, int layoutId) {
LayoutInflater inflate = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflate.inflate(layoutId, null);
return makeText(context, text, style, v, true);
}
/**
* @author mengguoqiang 扩展支持字体大小
* Make a {@link AppMsg} with a custom layout. The layout must have a {@link TextView} com id {@link android.R.id.message}
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param text The text to show. Can be formatted text.
* @param style The style with a background and a duration.
*/
public static AppMsg makeText(Activity context, CharSequence text, Style style, int layoutId, float textSize) {
LayoutInflater inflate = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflate.inflate(layoutId, null);
return makeText(context, text, style, v, true, textSize);
}
/**
* Make a non-floating {@link AppMsg} with a custom view presented inside the layout.
* It can be used to create non-floating notifications if floating is false.
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param customView
* View to be used.
* @param text The text to show. Can be formatted text.
* @param style The style with a background and a duration.
*/
public static AppMsg makeText(Activity context, CharSequence text, Style style, View customView) {
return makeText(context, text, style, customView, false);
}
/**
* Make a {@link AppMsg} with a custom view. It can be used to create non-floating notifications if floating is false.
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param view
* View to be used.
* @param text The text to show. Can be formatted text.
* @param style The style with a background and a duration.
* @param floating true if it'll float.
*/
private static AppMsg makeText(Activity context, CharSequence text, Style style, View view, boolean floating) {
return makeText(context, text, style, view, floating, 0);
}
/**
*
* @author mengguoqiang 扩展支持设置字体大小
* Make a {@link AppMsg} with a custom view. It can be used to create non-floating notifications if floating is false.
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param view
* View to be used.
* @param text The text to show. Can be formatted text.
* @param style The style with a background and a duration.
* @param floating true if it'll float.
*/
private static AppMsg makeText(Activity context, CharSequence text, Style style, View view, boolean floating, float textSize) {
AppMsg result = new AppMsg(context);
view.setBackgroundResource(style.background);
TextView tv = (TextView) view.findViewById(android.R.id.message);
if(textSize > 0) tv.setTextSize(textSize);
tv.setText(text);
result.mView = view;
result.mDuration = style.duration;
result.mFloating = floating;
return result;
}
/**
* Make a {@link AppMsg} with a custom view. It can be used to create non-floating notifications if floating is false.
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param resId The resource id of the string resource to use. Can be
* formatted text.
* @param style The style with a background and a duration.
* @param floating true if it'll float.
*/
public static AppMsg makeText(Activity context, int resId, Style style, View customView, boolean floating) {
return makeText(context, context.getResources().getText(resId), style, customView, floating);
}
/**
* Make a {@link AppMsg} that just contains a text view with the text from a
* resource.
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param resId The resource id of the string resource to use. Can be
* formatted text.
* @param style The style with a background and a duration.
* @throws Resources.NotFoundException if the resource can't be found.
*/
public static AppMsg makeText(Activity context, int resId, Style style)
throws Resources.NotFoundException {
return makeText(context, context.getResources().getText(resId), style);
}
/**
* Make a {@link AppMsg} with a custom layout using the text from a
* resource. The layout must have a {@link TextView} com id {@link android.R.id.message}
*
* @param context The context to use. Usually your
* {@link android.app.Activity} object.
* @param resId The resource id of the string resource to use. Can be
* formatted text.
* @param style The style with a background and a duration.
* @throws Resources.NotFoundException if the resource can't be found.
*/
public static AppMsg makeText(Activity context, int resId, Style style, int layoutId)
throws Resources.NotFoundException {
return makeText(context, context.getResources().getText(resId), style, layoutId);
}
/**
* Show the view for the specified duration.
*/
public void show() {
MsgManager manager = MsgManager.obtain(mActivity);
manager.add(this);
}
/**
* @return <code>true</code> if the {@link AppMsg} is being displayed, else <code>false</code>.
*/
public boolean isShowing() {
if (mFloating) {
return mView != null && mView.getParent() != null;
} else {
return mView.getVisibility() == View.VISIBLE;
}
}
/**
* Close the view if it's showing, or don't show it if it isn't showing yet.
* You do not normally have to call this. Normally view will disappear on its own
* after the appropriate duration.
*/
public void cancel() {
MsgManager.obtain(mActivity).clearMsg(this);
}
/**
* Cancels all queued {@link AppMsg}s, in all Activities. If there is a {@link AppMsg}
* displayed currently, it will be the last one displayed.
*/
public static void cancelAll() {
MsgManager.clearAll();
}
/**
* Cancels all queued {@link AppMsg}s, in given {@link android.app.Activity}.
* If there is a {@link AppMsg} displayed currently, it will be the last one displayed.
* @param activity
*/
public static void cancelAll(Activity activity) {
MsgManager.release(activity);
}
/**
* Return the activity.
*/
public Activity getActivity() {
return mActivity;
}
/**
* Set the view to show.
*
* @see #getView
*/
public void setView(View view) {
mView = view;
}
/**
* Return the view.
*
* @see #setView
*/
public View getView() {
return mView;
}
/**
* Set how long to show the view for.
*
* @see #LENGTH_SHORT
* @see #LENGTH_LONG
*/
public void setDuration(int duration) {
mDuration = duration;
}
/**
* Return the duration.
*
* @see #setDuration
*/
public int getDuration() {
return mDuration;
}
/**
* Update the text in a AppMsg that was previously created using one of the makeText() methods.
*
* @param resId The new text for the AppMsg.
*/
public void setText(int resId) {
setText(mActivity.getText(resId));
}
/**
* Update the text in a AppMsg that was previously created using one of the makeText() methods.
*
* @param s The new text for the AppMsg.
*/
public void setText(CharSequence s) {
if (mView == null) {
throw new RuntimeException("This AppMsg was not created with AppMsg.makeText()");
}
TextView tv = (TextView) mView.findViewById(android.R.id.message);
if (tv == null) {
throw new RuntimeException("This AppMsg was not created with AppMsg.makeText()");
}
tv.setText(s);
}
/**
* Gets the crouton's layout parameters, constructing a default if necessary.
*
* @return the layout parameters
*/
public LayoutParams getLayoutParams() {
if (mLayoutParams == null) {
mLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
return mLayoutParams;
}
/**
* Sets the layout parameters which will be used to display the crouton.
*
* @param layoutParams The layout parameters to use.
* @return <code>this</code>, for chaining.
*/
public AppMsg setLayoutParams(LayoutParams layoutParams) {
mLayoutParams = layoutParams;
return this;
}
/**
* Constructs and sets the layout parameters to have some gravity.
*
* @param gravity the gravity of the Crouton
* @return <code>this</code>, for chaining.
* @see android.view.Gravity
*/
public AppMsg setLayoutGravity(int gravity) {
mLayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, gravity);
return this;
}
/**
* Return the value of floating.
*
* @see #setFloating(boolean)
*/
public boolean isFloating() {
return mFloating;
}
/**
* Sets the value of floating.
*
* @param mFloating
*/
public void setFloating(boolean mFloating) {
this.mFloating = mFloating;
}
/**
* Sets the Animations to be used when displaying/removing the Crouton.
* @param inAnimation the Animation resource ID to be used when displaying.
* @param outAnimation the Animation resource ID to be used when removing.
*/
public AppMsg setAnimation(int inAnimation, int outAnimation) {
return setAnimation(AnimationUtils.loadAnimation(mActivity, inAnimation),
AnimationUtils.loadAnimation(mActivity, outAnimation));
}
/**
* Sets the Animations to be used when displaying/removing the Crouton.
* @param inAnimation the Animation to be used when displaying.
* @param outAnimation the Animation to be used when removing.
*/
public AppMsg setAnimation(Animation inAnimation, Animation outAnimation) {
mInAnimation = inAnimation;
mOutAnimation = outAnimation;
return this;
}
/**
* @return
* Current priority
*
* @see #PRIORITY_HIGH
* @see #PRIORITY_NORMAL
* @see #PRIORITY_LOW
*/
public int getPriority() {
return mPriority;
}
/**
* <p>Set priority for this message</p>
* <p><b>Note</b>: This only affects the order in which the messages get shown,
* not the stacking order of the views.</p>
*
* <p>Example: In the queue there are 3 messages [A, B, C],
* all of them with priority {@link #PRIORITY_NORMAL}, currently message A is being shown
* so we add a new message D with priority {@link #PRIORITY_HIGH}, after A goes away, given that
* D has a higher priority than B an the reset, D will be shown, then once that D is gone,
* B will be shown, and then finally C.</p>
*
* @param priority
* A value indicating priority, although you can use any integer value, usage of already
* defined is highly encouraged.
*
* @see #PRIORITY_HIGH
* @see #PRIORITY_NORMAL
* @see #PRIORITY_LOW
*/
public void setPriority(int priority) {
mPriority = priority;
}
/**
* @return
* Provided parent to add {@link #getView()} to using {@link #getLayoutParams()}.
*/
public ViewGroup getParent() {
return mParent;
}
/**
* Provide a different parent than Activity decor view
* @param parent
* Provided parent to add {@link #getView()} to using {@link #getLayoutParams()}.
*
*/
public void setParent(ViewGroup parent) {
mParent = parent;
}
/**
* Provide a different parent than Activity decor view
*
* @param parentId
* Provided parent id to add {@link #getView()} to using {@link #getLayoutParams()}.
*
*/
public void setParent(int parentId) {
setParent((ViewGroup) mActivity.findViewById(parentId));
}
/**
* The style for a {@link AppMsg}.
*
* @author e.shishkin
*/
public static class Style {
private final int duration;
private final int background;
/**
* Construct an {@link AppMsg.Style} object.
*
* @param duration How long to display the message. Either
* {@link #LENGTH_SHORT} or {@link #LENGTH_LONG}
* @param resId resource for AppMsg background
*/
public Style(int duration, int resId) {
this.duration = duration;
this.background = resId;
}
/**
* Return the duration in milliseconds.
*/
public int getDuration() {
return duration;
}
/**
* Return the resource id of background.
*/
public int getBackground() {
return background;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof AppMsg.Style)) {
return false;
}
Style style = (Style) o;
return style.duration == duration
&& style.background == background;
}
}
}

View File

@@ -0,0 +1,340 @@
/*
* Copyright 2012 Evgeny Shishkin
*
* 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 com.devspark.appmsg;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.WeakHashMap;
import static android.app.Application.ActivityLifecycleCallbacks;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
import static com.devspark.appmsg.AppMsg.LENGTH_STICKY;
/**
* @author Evgeny Shishkin
*/
class MsgManager extends Handler implements Comparator<AppMsg> {
private static final int MESSAGE_DISPLAY = 0xc2007;
private static final int MESSAGE_ADD_VIEW = 0xc20074dd;
private static final int MESSAGE_REMOVE = 0xc2007de1;
private static WeakHashMap<Activity, MsgManager> sManagers;
private static ReleaseCallbacks sReleaseCallbacks;
private final Queue<AppMsg> msgQueue;
private final Queue<AppMsg> stickyQueue;
private MsgManager() {
msgQueue = new PriorityQueue<AppMsg>(1, this);
stickyQueue = new LinkedList<AppMsg>();
}
/**
* @return A {@link MsgManager} instance to be used for given {@link android.app.Activity}.
*/
static synchronized MsgManager obtain(Activity activity) {
if (sManagers == null) {
sManagers = new WeakHashMap<Activity, MsgManager>(1);
}
MsgManager manager = sManagers.get(activity);
if (manager == null) {
manager = new MsgManager();
ensureReleaseOnDestroy(activity);
sManagers.put(activity, manager);
}
return manager;
}
static void ensureReleaseOnDestroy(Activity activity) {
if (SDK_INT < ICE_CREAM_SANDWICH) {
return;
}
if (sReleaseCallbacks == null) {
sReleaseCallbacks = new ReleaseCallbacksIcs();
}
sReleaseCallbacks.register(activity.getApplication());
}
static synchronized void release(Activity activity) {
if (sManagers != null) {
final MsgManager manager = sManagers.remove(activity);
if (manager != null) {
manager.clearAllMsg();
}
}
}
static synchronized void clearAll() {
if (sManagers != null) {
final Iterator<MsgManager> iterator = sManagers.values().iterator();
while (iterator.hasNext()) {
final MsgManager manager = iterator.next();
if (manager != null) {
manager.clearAllMsg();
}
iterator.remove();
}
sManagers.clear();
}
}
/**
* Inserts a {@link AppMsg} to be displayed.
*
* @param appMsg
*/
void add(AppMsg appMsg) {
msgQueue.add(appMsg);
if (appMsg.mInAnimation == null) {
appMsg.mInAnimation = AnimationUtils.loadAnimation(appMsg.getActivity(),
android.R.anim.fade_in);
}
if (appMsg.mOutAnimation == null) {
appMsg.mOutAnimation = AnimationUtils.loadAnimation(appMsg.getActivity(),
android.R.anim.fade_out);
}
displayMsg();
}
/**
* Removes all {@link AppMsg} from the queue.
*/
void clearMsg(AppMsg appMsg) {
if(msgQueue.contains(appMsg) || stickyQueue.contains(appMsg)){
// Avoid the message from being removed twice.
removeMessages(MESSAGE_DISPLAY, appMsg);
removeMessages(MESSAGE_ADD_VIEW, appMsg);
removeMessages(MESSAGE_REMOVE, appMsg);
msgQueue.remove(appMsg);
stickyQueue.remove(appMsg);
removeMsg(appMsg);
}
}
/**
* Removes all {@link AppMsg} from the queue.
*/
void clearAllMsg() {
removeMessages(MESSAGE_DISPLAY);
removeMessages(MESSAGE_ADD_VIEW);
removeMessages(MESSAGE_REMOVE);
clearShowing();
msgQueue.clear();
stickyQueue.clear();
}
void clearShowing() {
final Collection<AppMsg> showing = new HashSet<AppMsg>();
obtainShowing(msgQueue, showing);
obtainShowing(stickyQueue, showing);
for (AppMsg msg : showing) {
clearMsg(msg);
}
}
static void obtainShowing(Collection<AppMsg> from, Collection<AppMsg> appendTo) {
for (AppMsg msg : from) {
if (msg.isShowing()) {
appendTo.add(msg);
}
}
}
/**
* Displays the next {@link AppMsg} within the queue.
*/
private void displayMsg() {
if (msgQueue.isEmpty()) {
return;
}
// First peek whether the AppMsg is being displayed.
final AppMsg appMsg = msgQueue.peek();
final Message msg;
if (!appMsg.isShowing()) {
// Display the AppMsg
msg = obtainMessage(MESSAGE_ADD_VIEW);
msg.obj = appMsg;
sendMessage(msg);
} else if (appMsg.getDuration() != LENGTH_STICKY) {
msg = obtainMessage(MESSAGE_DISPLAY);
sendMessageDelayed(msg, appMsg.getDuration()
+ appMsg.mInAnimation.getDuration() + appMsg.mOutAnimation.getDuration());
}
}
/**
* Removes the {@link AppMsg}'s view after it's display duration.
*
* @param appMsg The {@link AppMsg} added to a {@link ViewGroup} and should be removed.s
*/
private void removeMsg(final AppMsg appMsg) {
clearMsg(appMsg);
final View view = appMsg.getView();
ViewGroup parent = ((ViewGroup) view.getParent());
if (parent != null) {
appMsg.mOutAnimation.setAnimationListener(new OutAnimationListener(appMsg));
view.clearAnimation();
view.startAnimation(appMsg.mOutAnimation);
}
Message msg = obtainMessage(MESSAGE_DISPLAY);
sendMessage(msg);
}
private void addMsgToView(AppMsg appMsg) {
View view = appMsg.getView();
if (view.getParent() == null) { // Not added yet
final ViewGroup targetParent = appMsg.getParent();
final ViewGroup.LayoutParams params = appMsg.getLayoutParams();
if (targetParent != null) {
targetParent.addView(view, params);
} else {
appMsg.getActivity().addContentView(view, params);
}
}
view.clearAnimation();
view.startAnimation(appMsg.mInAnimation);
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
final int duration = appMsg.getDuration();
if (duration != LENGTH_STICKY) {
final Message msg = obtainMessage(MESSAGE_REMOVE);
msg.obj = appMsg;
sendMessageDelayed(msg, duration);
} else { // We are sticky, we don't get removed just yet
stickyQueue.add(msgQueue.poll());
}
}
@Override
public void handleMessage(Message msg) {
final AppMsg appMsg;
switch (msg.what) {
case MESSAGE_DISPLAY:
displayMsg();
break;
case MESSAGE_ADD_VIEW:
appMsg = (AppMsg) msg.obj;
addMsgToView(appMsg);
break;
case MESSAGE_REMOVE:
appMsg = (AppMsg) msg.obj;
removeMsg(appMsg);
break;
default:
super.handleMessage(msg);
break;
}
}
@Override
public int compare(AppMsg lhs, AppMsg rhs) {
return inverseCompareInt(lhs.mPriority, rhs.mPriority);
}
static int inverseCompareInt(int lhs, int rhs) {
return lhs < rhs ? 1 : (lhs == rhs ? 0 : -1);
}
private static class OutAnimationListener implements Animation.AnimationListener {
private final AppMsg appMsg;
private OutAnimationListener(AppMsg appMsg) {
this.appMsg = appMsg;
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
final View view = appMsg.getView();
if (appMsg.isFloating()) {
final ViewGroup parent = ((ViewGroup) view.getParent());
if (parent != null) {
parent.post(new Runnable() { // One does not simply removeView
@Override
public void run() {
parent.removeView(view);
}
});
}
} else {
view.setVisibility(View.GONE);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
interface ReleaseCallbacks {
void register(Application application);
}
@TargetApi(ICE_CREAM_SANDWICH)
static class ReleaseCallbacksIcs implements ActivityLifecycleCallbacks, ReleaseCallbacks {
private WeakReference<Application> mLastApp;
public void register(Application app) {
if (mLastApp != null && mLastApp.get() == app) {
return; // Already registered with this app
} else {
mLastApp = new WeakReference<Application>(app);
}
app.registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityDestroyed(Activity activity) {
release(activity);
}
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override public void onActivityStarted(Activity activity) {}
@Override public void onActivityResumed(Activity activity) {}
@Override public void onActivityPaused(Activity activity) {}
@Override public void onActivityStopped(Activity activity) {}
@Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
}
}