package com.simplecity.amp_library.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Build;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import com.simplecity.amp_library.BuildConfig;
import com.simplecity.amp_library.R;
import com.simplecity.amp_library.ShuttleApplication;
import com.simplecity.amp_library.constants.Config;
import com.simplecity.amp_library.model.BaseFileObject;
import com.simplecity.amp_library.model.Query;
import com.simplecity.amp_library.model.Song;
import com.simplecity.amp_library.sql.SqlUtils;
import com.simplecity.amp_library.sql.providers.PlayCountTable;
import java.io.File;
import java.util.List;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* General helpers
*/
public final class ShuttleUtils {
//Arguments supplied to various bundles
public static final String ARG_ALBUM_ARTIST = "album_artist";
public static final String ARG_ARTIST = "artist";
public static final String ARG_ALBUM = "album";
public static final String ARG_SONG = "song";
public static final String ARG_PLAYLIST = "playlist";
public static final String ARG_GENRE = "genre";
private final static String TAG = "ShuttleUtils";
public static final int NEW_ALBUM_PHOTO = 100;
public static final int NEW_ARTIST_PHOTO = 200;
public static void openShuttleLink(Activity activity, String appPackageName) {
if (activity == null || appPackageName == null) {
return;
}
try {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(ShuttleUtils.getShuttleMarketUri(appPackageName))));
} catch (android.content.ActivityNotFoundException ignored) {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(ShuttleUtils.getShuttleWebUri(appPackageName))));
}
}
public static boolean isAmazonBuild() {
return BuildConfig.FLAVOR.equals("amazonFree") || BuildConfig.FLAVOR.equals("amazonPaid");
}
public static String getShuttleMarketUri(String packageName) {
String uri;
if (isAmazonBuild()) {
uri = "amzn://apps/android?p=" + packageName;
} else {
uri = "market://details?id=" + packageName;
}
return uri;
}
public static String getShuttleWebUri(String packageName) {
String uri;
if (isAmazonBuild()) {
uri = "http://www.amazon.com/gp/mas/dl/android?p=" + packageName;
} else {
uri = "https://play.google.com/store/apps/details?id=" + packageName;
}
return uri;
}
/**
* Execute an {@link AsyncTask} on a thread pool
*
* @param task Task to execute
* @param args Optional arguments to pass to{@link AsyncTask#execute(Object[])}
* @param <T> Task argument type
*/
@SuppressLint("NewApi")
public static <T> void execute(AsyncTask<T, ?, ?> task, T... args) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, args);
}
/**
* Method setRingtone.
*
* @param context context
* @param song Song
*/
public static void setRingtone(final Context context, final Song song) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.System.canWrite(context)) {
new AlertDialog.Builder(context)
.setTitle(R.string.dialog_title_set_ringtone)
.setMessage(R.string.dialog_message_set_ringtone)
.setPositiveButton(R.string.button_ok, (dialog, which) -> {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + ShuttleApplication.getInstance().getPackageName()));
context.startActivity(intent);
}).setNegativeButton(R.string.cancel, null)
.show();
return;
}
}
Observable.fromCallable(() -> {
boolean success = false;
final ContentResolver resolver = context.getContentResolver();
// Set the flag in the database to mark this as a ringtone
final Uri ringUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.id);
try {
final ContentValues values = new ContentValues(2);
values.put(MediaStore.Audio.AudioColumns.IS_RINGTONE, "1");
values.put(MediaStore.Audio.AudioColumns.IS_ALARM, "1");
if (ringUri != null) {
resolver.update(ringUri, values, null, null);
}
} catch (final UnsupportedOperationException ex) {
// most likely the card just got unmounted
Log.e(TAG, "couldn't set ringtone flag for song " + song);
return false;
}
Query query = new Query.Builder()
.uri(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI)
.projection(new String[]{
BaseColumns._ID,
MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.TITLE
})
.selection(BaseColumns._ID + "=" + song.id)
.build();
final Cursor cursor = SqlUtils.createQuery(context, query);
if (cursor != null) {
try {
if (cursor.getCount() == 1) {
// Set the system setting to make this the current ringtone
cursor.moveToFirst();
if (ringUri != null) {
Settings.System.putString(resolver, Settings.System.RINGTONE, ringUri.toString());
}
success = true;
}
} finally {
cursor.close();
}
}
return success;
}
)
.map(success -> success ? context.getString(R.string.ringtone_set, song.name) : context.getString(R.string.ringtone_set_failed))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(message -> Toast.makeText(context, message, Toast.LENGTH_SHORT).show());
}
/**
* Check whether we have an internet connection
*
* @param careAboutWifiOnly whether we care if the preference 'download via wifi only' is checked
* @return true if we have a connection, false otherwise
*/
public static boolean isOnline(boolean careAboutWifiOnly) {
Context context = ShuttleApplication.getInstance();
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
//Check if we are restricted to download over wifi only
boolean wifiOnly = mPrefs.getBoolean("pref_download_wifi_only", true);
//If we don't care whether wifi is allowed or not, set wifiOnly to false
if (!careAboutWifiOnly) {
wifiOnly = false;
}
final ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
//Check the state of the wifi network
final NetworkInfo wifiNetwork = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (wifiNetwork != null && wifiNetwork.isConnectedOrConnecting()) {
return true;
}
//Check other networks
final NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting() && !wifiOnly;
}
public static boolean isUpgraded() {
if (ShuttleApplication.getInstance().getIsUpgraded()) {
return true;
}
try {
return ShuttleApplication.getInstance().getPackageName().equals(Config.PACKAGE_NAME_PRO);
} catch (Exception ignored) {
}
//If something goes wrong, assume the user has the pro version
return true;
}
/**
* @return true if device is running API >= 17
*/
public static boolean hasJellyBeanMR1() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
}
/**
* @return true if device is running API >= 18
*/
public static boolean hasJellyBeanMR2() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
}
/**
* @return true if device is running API >= 19
*/
public static boolean hasKitKat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
}
/**
* @return true if device is running API >= 20
*/
public static boolean hasAndroidLPreview() {
return Build.VERSION.SDK_INT >= 20;
}
/**
* @return true if device is running API >= 21
*/
public static boolean hasLollipop() {
return Build.VERSION.SDK_INT >= 21;
}
/**
* @return true if device is running API >= 22
*/
public static boolean hasLollipopMR1() {
return Build.VERSION.SDK_INT >= 22;
}
/**
* @return true if device is running API >= 23
*/
public static boolean hasMarshmallow() {
return Build.VERSION.SDK_INT >= 23;
}
/**
* @return true if device is running API >= 24
*/
public static boolean hasNougat() {
return Build.VERSION.SDK_INT >= 24;
}
/**
* @return true if device is running API >= 24
*/
public static boolean hasNougatMR1() {
return Build.VERSION.SDK_INT >= 25;
}
public static boolean isLandscape() {
final int orientation = ShuttleApplication.getInstance().getResources().getConfiguration().orientation;
return orientation == Configuration.ORIENTATION_LANDSCAPE;
}
public static boolean isTablet() {
return ShuttleApplication.getInstance().getResources().getBoolean(R.bool.isTablet);
}
static Observable<List<Song>> getSongsForFileObjects(List<BaseFileObject> fileObjects) {
List<Observable<List<Song>>> observables = Stream.of(fileObjects)
.map(fileObject -> FileHelper.getSongList(new File(fileObject.path), true, false))
.collect(Collectors.toList());
return Observable.concat(observables).reduce((songs, songs2) -> {
songs.addAll(songs2);
return songs;
});
}
public static void incrementPlayCount(Context context, Song song) {
if (song == null) {
return;
}
ContentValues values = new ContentValues();
values.put(PlayCountTable.COLUMN_ID, song.id);
values.put(PlayCountTable.COLUMN_PLAY_COUNT, song.getPlayCount(context) + 1);
values.put(PlayCountTable.COLUMN_TIME_PLAYED, System.currentTimeMillis());
try {
if (context.getContentResolver().update(PlayCountTable.URI, values, PlayCountTable.COLUMN_ID + " ='" + song.id + "'", null) < 1) {
context.getContentResolver().insert(PlayCountTable.URI, values);
}
} catch (IllegalArgumentException e) {
Log.e(TAG, "Failed to increment play count: " + e.toString());
}
}
public static String getIpAddr() {
@SuppressLint("WifiManagerLeak")
int i = ((WifiManager) ShuttleApplication.getInstance().getSystemService(Context.WIFI_SERVICE)).getConnectionInfo().getIpAddress();
Object[] arrayOfObject = new Object[4];
arrayOfObject[0] = i & 0xFF;
arrayOfObject[1] = 0xFF & i >> 8;
arrayOfObject[2] = 0xFF & i >> 16;
arrayOfObject[3] = 0xFF & i >> 24;
return String.format("%d.%d.%d.%d", arrayOfObject);
}
}