Initial commit retro music app
This commit is contained in:
parent
ab332473bc
commit
fe890632fd
932 changed files with 83126 additions and 0 deletions
|
@ -0,0 +1,41 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
* https://stackoverflow.com/a/33891727
|
||||
*/
|
||||
|
||||
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {
|
||||
|
||||
private State mCurrentState = State.IDLE;
|
||||
|
||||
@Override
|
||||
public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
|
||||
if (i == 0) {
|
||||
if (mCurrentState != State.EXPANDED) {
|
||||
onStateChanged(appBarLayout, State.EXPANDED);
|
||||
}
|
||||
mCurrentState = State.EXPANDED;
|
||||
} else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
|
||||
if (mCurrentState != State.COLLAPSED) {
|
||||
onStateChanged(appBarLayout, State.COLLAPSED);
|
||||
}
|
||||
mCurrentState = State.COLLAPSED;
|
||||
} else {
|
||||
if (mCurrentState != State.IDLE) {
|
||||
onStateChanged(appBarLayout, State.IDLE);
|
||||
}
|
||||
mCurrentState = State.IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
|
||||
|
||||
public enum State {
|
||||
EXPANDED,
|
||||
COLLAPSED,
|
||||
IDLE
|
||||
}
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Implementation of {@link android.support.v4.view.PagerAdapter} that
|
||||
* uses a {@link Fragment} to manage each page. This class also handles
|
||||
* saving and restoring of fragment's state.
|
||||
* <p/>
|
||||
* <p>This version of the pager is more useful when there are a large number
|
||||
* of pages, working more like a list view. When pages are not visible to
|
||||
* the user, their entire fragment may be destroyed, only keeping the saved
|
||||
* state of that fragment. This allows the pager to hold on to much less
|
||||
* memory associated with each visited page as compared to
|
||||
* {@link FragmentPagerAdapter} at the cost of potentially more overhead when
|
||||
* switching between pages.
|
||||
* <p/>
|
||||
* <p>When using FragmentPagerAdapter the host ViewPager must have a
|
||||
* valid ID set.</p>
|
||||
* <p/>
|
||||
* <p>Subclasses only need to implement {@link #getItem(int)}
|
||||
* and {@link #getCount()} to have a working adapter.
|
||||
* <p/>
|
||||
* <p>Here is an example implementation of a pager containing fragments of
|
||||
* lists:
|
||||
* <p/>
|
||||
* {@sample development/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentStatePagerSupport.java
|
||||
* complete}
|
||||
* <p/>
|
||||
* <p>The <code>R.layout.fragment_pager</code> resource of the top-level fragment is:
|
||||
* <p/>
|
||||
* {@sample development/samples/Support13Demos/res/layout/fragment_pager.xml
|
||||
* complete}
|
||||
* <p/>
|
||||
* <p>The <code>R.layout.fragment_pager_list</code> resource containing each
|
||||
* individual fragment's layout is:
|
||||
* <p/>
|
||||
* {@sample development/samples/Support13Demos/res/layout/fragment_pager_list.xml
|
||||
* complete}
|
||||
*/
|
||||
public abstract class CustomFragmentStatePagerAdapter extends android.support.v4.view.PagerAdapter {
|
||||
public static final String TAG = CustomFragmentStatePagerAdapter.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final FragmentManager mFragmentManager;
|
||||
private FragmentTransaction mCurTransaction = null;
|
||||
|
||||
private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
|
||||
private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
|
||||
private Fragment mCurrentPrimaryItem = null;
|
||||
|
||||
public CustomFragmentStatePagerAdapter(FragmentManager fm) {
|
||||
mFragmentManager = fm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Fragment associated with a specified position.
|
||||
*/
|
||||
public abstract Fragment getItem(int position);
|
||||
|
||||
@Override
|
||||
public void startUpdate(ViewGroup container) {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
// If we already have this item instantiated, there is nothing
|
||||
// to do. This can happen when we are restoring the entire pager
|
||||
// from its saved state, where the fragment manager has already
|
||||
// taken care of restoring the fragments we previously had instantiated.
|
||||
if (mFragments.size() > position) {
|
||||
Fragment f = mFragments.get(position);
|
||||
if (f != null) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
if (mCurTransaction == null) {
|
||||
mCurTransaction = mFragmentManager.beginTransaction();
|
||||
}
|
||||
|
||||
Fragment fragment = getItem(position);
|
||||
if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
|
||||
if (mSavedState.size() > position) {
|
||||
Fragment.SavedState fss = mSavedState.get(position);
|
||||
if (fss != null) {
|
||||
fragment.setInitialSavedState(fss);
|
||||
}
|
||||
}
|
||||
while (mFragments.size() <= position) {
|
||||
mFragments.add(null);
|
||||
}
|
||||
fragment.setMenuVisibility(false);
|
||||
fragment.setUserVisibleHint(false);
|
||||
mFragments.set(position, fragment);
|
||||
mCurTransaction.add(container.getId(), fragment);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
Fragment fragment = (Fragment) object;
|
||||
|
||||
if (mCurTransaction == null) {
|
||||
mCurTransaction = mFragmentManager.beginTransaction();
|
||||
}
|
||||
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
|
||||
+ " v=" + ((Fragment) object).getView());
|
||||
while (mSavedState.size() <= position) {
|
||||
mSavedState.add(null);
|
||||
}
|
||||
mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
|
||||
mFragments.set(position, null);
|
||||
|
||||
mCurTransaction.remove(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
Fragment fragment = (Fragment) object;
|
||||
if (fragment != mCurrentPrimaryItem) {
|
||||
if (mCurrentPrimaryItem != null) {
|
||||
mCurrentPrimaryItem.setMenuVisibility(false);
|
||||
mCurrentPrimaryItem.setUserVisibleHint(false);
|
||||
}
|
||||
if (fragment != null) {
|
||||
fragment.setMenuVisibility(true);
|
||||
fragment.setUserVisibleHint(true);
|
||||
}
|
||||
mCurrentPrimaryItem = fragment;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishUpdate(ViewGroup container) {
|
||||
if (mCurTransaction != null) {
|
||||
mCurTransaction.commitAllowingStateLoss();
|
||||
mCurTransaction = null;
|
||||
mFragmentManager.executePendingTransactions();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(View view, Object object) {
|
||||
return ((Fragment) object).getView() == view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable saveState() {
|
||||
Bundle state = null;
|
||||
if (mSavedState.size() > 0) {
|
||||
state = new Bundle();
|
||||
Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
|
||||
mSavedState.toArray(fss);
|
||||
state.putParcelableArray("states", fss);
|
||||
}
|
||||
for (int i = 0; i < mFragments.size(); i++) {
|
||||
Fragment f = mFragments.get(i);
|
||||
if (f != null && f.isAdded()) {
|
||||
if (state == null) {
|
||||
state = new Bundle();
|
||||
}
|
||||
String key = "f" + i;
|
||||
mFragmentManager.putFragment(state, key, f);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState(Parcelable state, ClassLoader loader) {
|
||||
if (state != null) {
|
||||
Bundle bundle = (Bundle) state;
|
||||
bundle.setClassLoader(loader);
|
||||
Parcelable[] fss = bundle.getParcelableArray("states");
|
||||
mSavedState.clear();
|
||||
mFragments.clear();
|
||||
if (fss != null) {
|
||||
for (int i = 0; i < fss.length; i++) {
|
||||
mSavedState.add((Fragment.SavedState) fss[i]);
|
||||
}
|
||||
}
|
||||
Iterable<String> keys = bundle.keySet();
|
||||
for (String key : keys) {
|
||||
if (key.startsWith("f")) {
|
||||
int index = Integer.parseInt(key.substring(1));
|
||||
Fragment f = mFragmentManager.getFragment(bundle, key);
|
||||
if (f != null) {
|
||||
while (mFragments.size() <= index) {
|
||||
mFragments.add(null);
|
||||
}
|
||||
f.setMenuVisibility(false);
|
||||
mFragments.set(index, f);
|
||||
} else {
|
||||
Log.w(TAG, "Bad fragment at key " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Fragment getFragment(int position) {
|
||||
if (position < mFragments.size() && position >= 0) {
|
||||
return mFragments.get(position);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
public abstract class DialogAsyncTask<Params, Progress, Result> extends WeakContextAsyncTask<Params, Progress, Result> {
|
||||
private final int delay;
|
||||
private WeakReference<Dialog> dialogWeakReference;
|
||||
|
||||
private boolean supposedToBeDismissed;
|
||||
|
||||
public DialogAsyncTask(Context context) {
|
||||
this(context, 0);
|
||||
}
|
||||
|
||||
public DialogAsyncTask(Context context, int showDelay) {
|
||||
super(context);
|
||||
this.delay = showDelay;
|
||||
dialogWeakReference = new WeakReference<>(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
if (delay > 0) {
|
||||
new Handler().postDelayed(this::initAndShowDialog, delay);
|
||||
} else {
|
||||
initAndShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void initAndShowDialog() {
|
||||
Context context = getContext();
|
||||
if (!supposedToBeDismissed && context != null) {
|
||||
Dialog dialog = createDialog(context);
|
||||
dialogWeakReference = new WeakReference<>(dialog);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void onProgressUpdate(Progress... values) {
|
||||
super.onProgressUpdate(values);
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null) {
|
||||
onProgressUpdate(dialog, values);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void onProgressUpdate(@NonNull Dialog dialog, Progress... values) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Dialog getDialog() {
|
||||
return dialogWeakReference.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled(Result result) {
|
||||
super.onCancelled(result);
|
||||
tryToDismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Result result) {
|
||||
super.onPostExecute(result);
|
||||
tryToDismiss();
|
||||
}
|
||||
|
||||
private void tryToDismiss() {
|
||||
supposedToBeDismissed = true;
|
||||
try {
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null)
|
||||
dialog.dismiss();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Dialog createDialog(@NonNull Context context);
|
||||
}
|
62
app/src/main/java/code/name/monkey/retromusic/misc/LagTracker.java
Executable file
62
app/src/main/java/code/name/monkey/retromusic/misc/LagTracker.java
Executable file
|
@ -0,0 +1,62 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class LagTracker {
|
||||
private static Map<String, Long> mMap;
|
||||
private static LagTracker mSingleton;
|
||||
private boolean mEnabled = true;
|
||||
|
||||
private LagTracker() {
|
||||
mMap = new HashMap();
|
||||
}
|
||||
|
||||
public static LagTracker get() {
|
||||
if (mSingleton == null) {
|
||||
mSingleton = new LagTracker();
|
||||
}
|
||||
return mSingleton;
|
||||
}
|
||||
|
||||
private void print(String str, long j) {
|
||||
long toMillis = TimeUnit.NANOSECONDS.toMillis(j);
|
||||
Log.d("LagTracker", "[" + str + " completed in]: " + j + " ns (" + toMillis + "ms, " + TimeUnit.NANOSECONDS.toSeconds(j) + "s)");
|
||||
}
|
||||
|
||||
public LagTracker disable() {
|
||||
this.mEnabled = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LagTracker enable() {
|
||||
this.mEnabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void end(String str) {
|
||||
long nanoTime = System.nanoTime();
|
||||
if (this.mEnabled) {
|
||||
if (mMap.containsKey(str)) {
|
||||
print(str, nanoTime - mMap.get(str).longValue());
|
||||
mMap.remove(str);
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("No start time found for " + str);
|
||||
} else if (!mMap.isEmpty()) {
|
||||
mMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void start(String str) {
|
||||
long nanoTime = System.nanoTime();
|
||||
if (this.mEnabled) {
|
||||
mMap.put(str, Long.valueOf(nanoTime));
|
||||
} else if (!mMap.isEmpty()) {
|
||||
mMap.clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
/*Don't delete even if its not showing not using*/
|
||||
public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
|
||||
private static final String TAG = "ScrollingFABBehavior";
|
||||
Handler mHandler;
|
||||
|
||||
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
|
||||
@NonNull FloatingActionButton child,
|
||||
@NonNull View target) {
|
||||
super.onStopNestedScroll(coordinatorLayout, child, target);
|
||||
|
||||
if (mHandler == null)
|
||||
mHandler = new Handler();
|
||||
|
||||
|
||||
mHandler.postDelayed(() -> {
|
||||
child.animate().translationY(0).setInterpolator(new LinearInterpolator()).start();
|
||||
Log.d("FabAnim", "startHandler()");
|
||||
}, 1000);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
|
||||
@NonNull FloatingActionButton child,
|
||||
@NonNull View target,
|
||||
int dxConsumed,
|
||||
int dyConsumed,
|
||||
int dxUnconsumed,
|
||||
int dyUnconsumed) {
|
||||
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
|
||||
|
||||
//child -> Floating Action Button
|
||||
if (dyConsumed > 0) {
|
||||
Log.d("Scrolling", "Up");
|
||||
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
|
||||
int fab_bottomMargin = layoutParams.bottomMargin;
|
||||
child.animate().translationY(child.getHeight() + fab_bottomMargin).setInterpolator(new LinearInterpolator()).start();
|
||||
} else if (dyConsumed < 0) {
|
||||
Log.d("Scrolling", "down");
|
||||
child.animate().translationY(0).setInterpolator(new LinearInterpolator()).start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
|
||||
@NonNull FloatingActionButton child,
|
||||
@NonNull View directTargetChild,
|
||||
@NonNull View target,
|
||||
int nestedScrollAxes) {
|
||||
if (mHandler != null) {
|
||||
mHandler.removeMessages(0);
|
||||
Log.d("Scrolling", "stopHandler()");
|
||||
}
|
||||
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
|
||||
}
|
||||
}
|
||||
/*extends FloatingActionButton.Behavior {
|
||||
|
||||
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onStartNestedScroll(@NonNull final CoordinatorLayout coordinatorLayout,
|
||||
@NonNull final FloatingActionButton child,
|
||||
@NonNull final View directTargetChild,
|
||||
@NonNull final View target,
|
||||
final int nestedScrollAxes) {
|
||||
// Ensure we react to vertical scrolling
|
||||
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
|
||||
|| super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
|
||||
@NonNull FloatingActionButton child,
|
||||
@NonNull View target,
|
||||
int dxConsumed,
|
||||
int dyConsumed,
|
||||
int dxUnconsumed,
|
||||
int dyUnconsumed) {
|
||||
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
|
||||
dyUnconsumed);
|
||||
|
||||
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
|
||||
child.hide();
|
||||
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
|
||||
child.show();
|
||||
}
|
||||
}
|
||||
}*/
|
|
@ -0,0 +1,26 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.animation.Animator;
|
||||
|
||||
|
||||
public abstract class SimpleAnimatorListener implements Animator.AnimatorListener {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.widget.SeekBar;
|
||||
|
||||
|
||||
public abstract class SimpleOnSeekbarChangeListener implements SeekBar.OnSeekBarChangeListener {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public class UpdateToastMediaScannerCompletionListener implements MediaScannerConnection.OnScanCompletedListener {
|
||||
private final String[] toBeScanned;
|
||||
private final String scannedFiles;
|
||||
private final String couldNotScanFiles;
|
||||
private final WeakReference<Activity> activityWeakReference;
|
||||
private int scanned = 0;
|
||||
private int failed = 0;
|
||||
private Toast toast;
|
||||
|
||||
@SuppressLint("ShowToast")
|
||||
public UpdateToastMediaScannerCompletionListener(Activity activity, String[] toBeScanned) {
|
||||
this.toBeScanned = toBeScanned;
|
||||
scannedFiles = activity.getString(R.string.scanned_files);
|
||||
couldNotScanFiles = activity.getString(R.string.could_not_scan_files);
|
||||
toast = Toast.makeText(activity.getApplicationContext(), "", Toast.LENGTH_SHORT);
|
||||
activityWeakReference = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanCompleted(final String path, final Uri uri) {
|
||||
Activity activity = activityWeakReference.get();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(() -> {
|
||||
if (uri == null) {
|
||||
failed++;
|
||||
} else {
|
||||
scanned++;
|
||||
}
|
||||
String text = " " + String.format(scannedFiles, scanned, toBeScanned.length) + (failed > 0 ? " " + String.format(couldNotScanFiles, failed) : "");
|
||||
toast.setText(text);
|
||||
toast.show();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package code.name.monkey.retromusic.misc;
import android.content.Context;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import java.lang.ref.WeakReference;
public abstract class WeakContextAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
private WeakReference<Context> contextWeakReference;
public WeakContextAsyncTask(Context context) {
contextWeakReference = new WeakReference<>(context);
}
@Nullable
protected Context getContext() {
return contextWeakReference.get();
}
}
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
package code.name.monkey.retromusic.misc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
/**
|
||||
* <a href="http://code.google.com/p/android/issues/detail?id=14944">Issue
|
||||
* 14944</a>
|
||||
*
|
||||
* @author Alexander Blom
|
||||
*/
|
||||
public abstract class WrappedAsyncTaskLoader<D> extends AsyncTaskLoader<D> {
|
||||
|
||||
private D mData;
|
||||
|
||||
/**
|
||||
* Constructor of <code>WrappedAsyncTaskLoader</code>
|
||||
*
|
||||
* @param context The {@link Context} to use.
|
||||
*/
|
||||
public WrappedAsyncTaskLoader(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void deliverResult(D data) {
|
||||
if (!isReset()) {
|
||||
this.mData = data;
|
||||
super.deliverResult(data);
|
||||
} else {
|
||||
// An asynchronous query came in while the loader is stopped
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
super.onStartLoading();
|
||||
if (this.mData != null) {
|
||||
deliverResult(this.mData);
|
||||
} else if (takeContentChanged() || this.mData == null) {
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
super.onStopLoading();
|
||||
// Attempt to cancel the current load task if possible
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onReset() {
|
||||
super.onReset();
|
||||
// Ensure the loader is stopped
|
||||
onStopLoading();
|
||||
this.mData = null;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue