package me.shouheng.utils.app; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.AnimRes; import android.support.annotation.NonNull; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.app.Fragment; import android.support.v4.util.Pair; import android.view.View; import java.io.Serializable; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import me.shouheng.utils.R; import me.shouheng.utils.UtilsApp; import me.shouheng.utils.constant.ActivityDirection; /** * ActivityUtils is a helper class used to start your activity defined in your manifest or * start other activities by intent. You can easily prepare the values by the builder and connect * all the methods like a chain, which is rather elegant than using the raw intent. * * @author shouh * @version $Id: ActivityUtils, v 0.1 2018/11/17 17:29 shouh Exp$ */ public final class ActivityUtils { private static List<Activity> activities = new LinkedList<>(); /** * Judge is given activity exists. * * @param pkg the package name * @param cls the class name * @return true if exists */ public static boolean isActivityExists(@NonNull final String pkg, @NonNull final String cls) { Intent intent = new Intent(); intent.setClassName(pkg, cls); PackageManager pm = UtilsApp.getApp().getPackageManager(); return pm.resolveActivity(intent, 0) != null && intent.resolveActivity(pm) != null && pm.queryIntentActivities(intent, 0).size() != 0; } /*---------------------------------- Starter --------------------------------------*/ /** * Start given activity. * * @param context the context to start activity * @param activity the destination activity */ public static void start(@NonNull Context context, @NonNull Class<? extends Activity> activity) { context.startActivity(new Intent(context, activity)); } public static void start(@NonNull Context context, @NonNull Class<? extends Activity> activity, @ActivityDirection int direction) { context.startActivity(new Intent(context, activity)); if (context instanceof Activity) { overridePendingTransition((Activity) context, direction); } } /** * Start activity. * * @param activity starter activity * @param activityClass target activity * @param requestCode the request code */ public static void start(@NonNull Activity activity, @NonNull Class<? extends Activity> activityClass, int requestCode) { activity.startActivityForResult(new Intent(activity, activityClass), requestCode); } public static void start(@NonNull Activity activity, @NonNull Class<? extends Activity> activityClass, int requestCode, @ActivityDirection int direction) { start(activity, activityClass, requestCode, direction, false); } public static void start(@NonNull Activity activity, @NonNull Class<? extends Activity> activityClass, int requestCode, @ActivityDirection int direction, boolean finishLast) { activity.startActivityForResult(new Intent(activity, activityClass), requestCode); if (finishLast) activity.finish(); overridePendingTransition(activity, direction); } /** * Start activity. * * @param fragment starter fragment * @param activityClass the target activity * @param requestCode the request code */ public static void start(@NonNull Fragment fragment, @NonNull Class<? extends Activity> activityClass, int requestCode) { fragment.startActivityForResult(new Intent(fragment.getContext(), activityClass), requestCode); } public static void start(@NonNull Fragment fragment, @NonNull Class<? extends Activity> activityClass, int requestCode, @ActivityDirection int direction) { fragment.startActivityForResult(new Intent(fragment.getContext(), activityClass), requestCode); overridePendingTransition(fragment.getActivity(), direction); } /** * Start home activity. * * @param context the context */ public static void startHomeActivity(Context context) { Intent i = new Intent(Intent.ACTION_MAIN); i.addCategory(Intent.CATEGORY_HOME); context.startActivity(i); } public static void overridePendingTransition(Activity activity, @ActivityDirection int direction) { if (direction == ActivityDirection.ANIMATE_FORWARD) { activity.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left); } else if (direction == ActivityDirection.ANIMATE_BACK) { activity.overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right); } else if (direction == ActivityDirection.ANIMATE_EASE_IN_OUT) { activity.overridePendingTransition(R.anim.ease_in, R.anim.ease_out); } else if (direction == ActivityDirection.ANIMATE_SLIDE_TOP_FROM_BOTTOM) { activity.overridePendingTransition(R.anim.slide_bottom_to_top, R.anim.slide_none_medium_time); } else if (direction == ActivityDirection.ANIMATE_SLIDE_BOTTOM_FROM_TOP) { activity.overridePendingTransition(R.anim.slide_none_medium_time, R.anim.slide_top_to_bottom); } else if (direction == ActivityDirection.ANIMATE_SCALE_IN) { activity.overridePendingTransition(R.anim.popup_scale_in, R.anim.slide_none); } else if (direction == ActivityDirection.ANIMATE_SCALE_OUT) { activity.overridePendingTransition(R.anim.slide_none, R.anim.popup_scale_out); } else if (direction == ActivityDirection.ANIMATE_NONE) { // do nothing } else { activity.overridePendingTransition(R.anim.magnify_fade_in, R.anim.fade_out); } } /*---------------------------------- Finisher --------------------------------------*/ /** * Finish given activity with default animation. * * @param activity the activity to finish */ public static void finishActivity(@NonNull Activity activity) { activity.finish(); } public static void finishActivity(@NonNull Activity activity, @ActivityDirection int direction) { activity.finish(); overridePendingTransition(activity, direction); } /** * Finish activity with given animation * * @param activity the activity to finish * @param enterAnim the enter animation * @param exitAnim the exit animation */ public static void finishActivity(@NonNull Activity activity, @AnimRes final int enterAnim, @AnimRes final int exitAnim) { activity.finish(); activity.overridePendingTransition(enterAnim, exitAnim); } /*---------------------------------- Launcher --------------------------------------*/ /** Get an {@link Builder} instance used to build the intent to start an activity. * * @param activity the destination activity * @param <T> the activity type * @return the builder */ public static <T extends Activity> Builder<T> open(Class<T> activity) { return new Builder<>(activity); } /** * Get an builder to build an intent to start an third part activity * * @return the builder used to build intent */ public static Builder open() { return new Builder(); } /** * A builder used to build intent to start activity * * @param <T> the activity type */ public static class Builder<T extends Activity> { @AnimRes private int enterAnim; @AnimRes private int exitAnim; @ActivityDirection private int direction; private View[] sharedElements; private Bundle options; private Class<T> clz; private Intent intent = new Intent(); /** * Builder with no params used to open the third part activity by intent. */ Builder() {} /** * Builder with given type activity used to open the activity defined in your manifest * * @param clz the activity to launch */ Builder(Class<T> clz) { this.clz = clz; } public Builder<T> setClass(Context packageContext, Class<T> clz) { intent.setClass(packageContext, clz); return this; } public Builder<T> setAction(String action) { intent.setAction(action); return this; } public Builder<T> setData(Uri data) { intent.setData(data); return this; } public Builder<T> setFlags(int flags) { intent.setFlags(flags); return this; } public Builder<T> setType(String type) { intent.setType(type); return this; } public Builder<T> addCategory(String category) { intent.addCategory(category); return this; } public Builder<T> put(String key, byte b) { intent.putExtra(key, b); return this; } public Builder<T> put(String key, char c) { intent.putExtra(key, c); return this; } public Builder<T> put(String key, short s) { intent.putExtra(key, s); return this; } public Builder<T> put(String key, int i) { intent.putExtra(key, i); return this; } public Builder<T> put(String key, long l) { intent.putExtra(key, l); return this; } public Builder<T> put(String key, float f) { intent.putExtra(key, f); return this; } public Builder<T> put(String key, double d) { intent.putExtra(key, d); return this; } public Builder<T> put(String key, String s) { intent.putExtra(key, s); return this; } public Builder<T> put(String key, CharSequence cs) { intent.putExtra(key, cs); return this; } public Builder<T> put(String key, Serializable s) { intent.putExtra(key, s); return this; } public Builder<T> put(String key, Parcelable p) { intent.putExtra(key, p); return this; } public Builder<T> put(String key, boolean[] bs) { intent.putExtra(key, bs); return this; } public Builder<T> put(String key, byte[] bs) { intent.putExtra(key, bs); return this; } public Builder<T> put(String key, short[] ss) { intent.putExtra(key, ss); return this; } public Builder<T> put(String key, char[] cs) { intent.putExtra(key, cs); return this; } public Builder<T> put(String key, int[] is) { intent.putExtra(key, is); return this; } public Builder<T> put(String key, long[] ls) { intent.putExtra(key, ls); return this; } public Builder<T> put(String key, float[] fs) { intent.putExtra(key, fs); return this; } public Builder<T> put(String key, double[] ds) { intent.putExtra(key, ds); return this; } public Builder<T> put(String key, String[] ss) { intent.putExtra(key, ss); return this; } public Builder<T> put(String key, CharSequence[] css) { intent.putExtra(key, css); return this; } public Builder<T> put(String key, Bundle bundle) { intent.putExtra(key, bundle); return this; } public Builder<T> put(String key, Parcelable[] ps) { intent.putExtra(key, ps); return this; } public Builder<T> putParcelableList(String key, ArrayList<? extends Parcelable> pl) { intent.putParcelableArrayListExtra(key, pl); return this; } public Builder<T> putIntegerList(String key, ArrayList<Integer> il) { intent.putIntegerArrayListExtra(key, il); return this; } public Builder<T> putStringList(String key, ArrayList<String> sl) { intent.putStringArrayListExtra(key, sl); return this; } public Builder<T> putCharSequenceList(String key, ArrayList<CharSequence> csl) { intent.putCharSequenceArrayListExtra(key, csl); return this; } public Builder<T> withAnim(@AnimRes final int enterAnim, @AnimRes final int exitAnim) { this.enterAnim = enterAnim; this.exitAnim = exitAnim; return this; } public Builder<T> withDirection(@ActivityDirection final int direction) { this.direction = direction; return this; } public Builder<T> wishSharedElements(View[] sharedElements) { this.sharedElements = sharedElements; return this; } public Builder<T> withOptions(Bundle options) { this.options = options; return this; } public Intent getIntent(Context context) { if (clz != null) { intent.setClass(context, clz); } return intent; } public void launch(@NonNull Context context) { Intent i = getIntent(context); if (context instanceof Activity) { if (options == null && sharedElements != null) { options = getOptionsBundle((Activity) context, sharedElements); } if (options != null && VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { context.startActivity(i, options); } else { context.startActivity(i); } if (enterAnim != 0 && exitAnim != 0) { ((Activity) context).overridePendingTransition(enterAnim, exitAnim); } if (direction != 0) { overridePendingTransition((Activity) context, direction); } } else { context.startActivity(i); } } public void launch(@NonNull Activity activity, int requestCode) { Intent i = getIntent(activity); if (options == null && sharedElements != null) { options = getOptionsBundle(activity, sharedElements); } if (options != null && VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { activity.startActivityForResult(i, requestCode, options); } else { activity.startActivityForResult(i, requestCode); } if (enterAnim != 0 && exitAnim != 0) { activity.overridePendingTransition(enterAnim, exitAnim); } if (direction != 0) { overridePendingTransition(activity, direction); } } public void launch(@NonNull Fragment f, int requestCode) { Activity a = f.getActivity(); Intent i = getIntent(a); if (options == null && sharedElements != null) { options = getOptionsBundle(a, sharedElements); } if (options != null && VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { f.startActivityForResult(i, requestCode, options); } else { f.startActivityForResult(i, requestCode); } if (enterAnim != 0 && exitAnim != 0 && a != null) { a.overridePendingTransition(enterAnim, exitAnim); } if (direction != 0) { overridePendingTransition(a, direction); } } private Bundle getOptionsBundle(final Activity activity, final View[] sharedElements) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null; if (sharedElements == null) return null; int len = sharedElements.length; if (len <= 0) return null; @SuppressWarnings("unchecked") Pair<View, String>[] pairs = new Pair[len]; for (int i = 0; i < len; i++) { pairs[i] = Pair.create(sharedElements[i], sharedElements[i].getTransitionName()); } return ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs).toBundle(); } } /*---------------------------------- Manager --------------------------------------*/ /** * 将 Activity 添加到列表中,应该在 {@link Activity#onDestroy()} 方法中 * 调用 {@link #removeFromList(Activity)} 从列表中移除,防止内存泄漏 * * @param activity 要添加的 Activity */ public static void addToList(Activity activity) { activities.add(activity); } /** * 将 Activity 从列表中移除 * * @param activity 要移除的 Activity */ public static void removeFromList(Activity activity) { int index = activities.indexOf(activity); if (index != -1) { activities.remove(activity); } } /** * 当前的 Activity,该 Activity 应当曾经调用过 {@link #addToList(Activity)} * * @return 当前 Activity */ public static Activity currentActivity() { return activities.get(0); } /** * 销毁列表中所有的 Activity */ public static void finishAll() { for (Activity activity : activities) { activity.finish(); } } /*---------------------------------- inner methods --------------------------------------*/ private ActivityUtils() { throw new UnsupportedOperationException("u can't initialize me!"); } }