Java tutorial
/* * Copyright (c) 2015 Matthieu Harl * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package fr.shywim.antoinedaniel.utils; import android.content.ContentValues; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Handler; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.RelativeLayout; import com.crashlytics.android.Crashlytics; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.games.Games; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Random; import fr.shywim.antoinedaniel.R; import fr.shywim.antoinedaniel.provider.ProviderConstants; import fr.shywim.antoinedaniel.provider.ProviderContract; import fr.shywim.antoinedaniel.sync.AppState; public class Utils { public GoogleApiClient apiClient; public final String SKU_DONATE = "donate100"; public int totalSoundCount = 0; public int downloadedSoundCount = 0; public boolean animEnabled = true; public boolean taskRunning = false; public boolean soundPlaying = false; public boolean looping = false; public boolean explicitlySignedOut = false; public boolean signInFlowStarted = false; // Animations public static final RotateAnimation ventiloRotate = new RotateAnimation(0f, -359f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); static { ventiloRotate.setRepeatMode(Animation.RESTART); ventiloRotate.setRepeatCount(Animation.INFINITE); ventiloRotate.setDuration(1000); ventiloRotate.setInterpolator(new LinearInterpolator()); } public static final AlphaAnimation fadeInAnim = new AlphaAnimation(0f, 1f); static { fadeInAnim.setDuration(200); fadeInAnim.setFillAfter(true); fadeInAnim.setInterpolator(new LinearInterpolator()); } public static final AlphaAnimation fadeOutAnim = new AlphaAnimation(1f, 0f); static { fadeOutAnim.setDuration(200); fadeOutAnim.setFillAfter(true); fadeOutAnim.setInterpolator(new LinearInterpolator()); } public Random random = new Random(); private static final Utils INSTANCE = new Utils(); private Utils() { } public static Utils getInstance() { return INSTANCE; } /** * First part of the click animation. * * @param context Any context. * @param v View who will have the effect. * @param isRoot Whether the passed view is the ViewGroup parent. */ public static void clickAnimDown(Context context, View v, boolean isRoot) { RelativeLayout root; if (isRoot) root = (RelativeLayout) v; else root = (RelativeLayout) v.getParent(); final View rectView = new View(context); rectView.setId(R.id.rect_view_id); rectView.setVisibility(View.GONE); rectView.setBackgroundResource(R.drawable.square); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(v.getMeasuredWidth(), v.getMeasuredHeight()); params.addRule(RelativeLayout.ALIGN_TOP, v.getId()); rectView.setLayoutParams(params); AlphaAnimation rectAnim = new AlphaAnimation(0f, 0.4f); rectAnim.setFillAfter(true); rectAnim.setInterpolator(new AccelerateInterpolator()); rectAnim.setDuration(150); rectAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { rectView.setVisibility(View.VISIBLE); } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } }); root.addView(rectView); rectView.startAnimation(rectAnim); } /** * Second part of the click animation. * * @param v View who will have the effect. * @param isRoot Whether the passed view is the ViewGroup parent. */ public static void clickAnimUp(View v, boolean isRoot) { RelativeLayout root; if (isRoot) root = (RelativeLayout) v; else root = (RelativeLayout) v.getParent(); final View rectView = root.findViewById(R.id.rect_view_id); if (rectView != null) { AlphaAnimation rectAnim = new AlphaAnimation(0.4f, 0f); rectAnim.setFillAfter(true); rectAnim.setInterpolator(new DecelerateInterpolator()); rectAnim.setDuration(150); rectAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { new Handler().post(new Runnable() { @Override public void run() { ViewGroup parent = (ViewGroup) rectView.getParent(); rectView.setVisibility(View.GONE); if (parent != null) parent.removeView(rectView); } }); } @Override public void onAnimationRepeat(Animation animation) { } }); rectView.clearAnimation(); rectView.startAnimation(rectAnim); } } /** * Delete the application's cache directory. * * @param context application's context * @return whether the directory has been successfully deleted or not */ public static boolean deleteCacheDir(Context context) { try { File dir = context.getCacheDir(); if (dir != null && dir.isDirectory()) { return deleteDir(dir); } } catch (Exception e) { Crashlytics.logException(e); } return false; } /** * Delete a directory. * * @param dir the directory to delete * @return whether the directory has been successfully deleted or not */ @SuppressWarnings("ObjectAllocationInLoop") public static boolean deleteDir(File dir) { String[] children = dir.list(); if (children != null) { for (String aChildren : children) { File file = new File(dir, aChildren); //noinspection ResultOfMethodCallIgnored file.delete(); } } return dir.delete(); } /** * Copy a file from one place (src) to another (dst). * * @param src Source File. * @param dst Destination File. * @throws IOException */ public static void copy(File src, File dst) throws IOException { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); } public static boolean getInformationFromCdn(Context context, String soundname, String page, boolean force) { List<NameValuePair> nameValuePairs = new ArrayList<>(1); nameValuePairs.add(new BasicNameValuePair("sound_id", soundname)); nameValuePairs.add(new BasicNameValuePair("page", page)); String paramString = URLEncodedUtils.format(nameValuePairs, "utf-8"); String url = context.getResources().getString(R.string.api_get_one_sound) + '?' + paramString; final HttpClient httpclient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); try { HttpResponse response = httpclient.execute(httpGet); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { String result = EntityUtils.toString(response.getEntity()); JSONObject jo = new JSONObject(result); if (!prepareDownloadFromCdn(context, jo.getString("soundname"), jo.getString("imagename"), jo.getString("description"), jo.getString("link"), Integer.parseInt(jo.getString("version")), force)) { return false; } else jo.getString("version"); } } catch (IOException | JSONException e) { Crashlytics.logException(e); } return true; } public static boolean prepareDownloadFromCdn(Context context, String soundName, String imageName, String description, String link, int version, boolean force) throws IOException { String extImgPath = context.getExternalFilesDir(null) + "/img/"; String extSndPath = context.getExternalFilesDir(null) + "/snd/"; File sndDir = new File(context.getExternalFilesDir(null) + "/snd"); if (!sndDir.exists()) if (!sndDir.mkdirs()) return false; File imgDir = new File(context.getExternalFilesDir(null) + "/img"); if (!imgDir.exists()) if (!imgDir.mkdirs()) return false; File file = new File(extSndPath + soundName + ".ogg"); if (!downloadFileFromCdn(context, file, soundName, "snd/", ".ogg", force)) { //noinspection ResultOfMethodCallIgnored file.delete(); return false; } file = new File(extImgPath + imageName + ".jpg"); if (!downloadFileFromCdn(context, file, imageName, "img/", ".jpg", force)) { //noinspection ResultOfMethodCallIgnored file.delete(); return false; } Uri uri = Uri.withAppendedPath(ProviderConstants.SOUND_NAME_URI, soundName); ContentValues cv = new ContentValues(); cv.put(ProviderContract.SoundEntry.COLUMN_SOUND_NAME, soundName); cv.put(ProviderContract.SoundEntry.COLUMN_IMAGE_NAME, imageName); cv.put(ProviderContract.SoundEntry.COLUMN_DESC, description); cv.put(ProviderContract.SoundEntry.COLUMN_LINK, link); cv.put(ProviderContract.SoundEntry.COLUMN_NAME_VERSION, version); if (uri != null) { context.getContentResolver().update(uri, cv, null, null); return true; } else return false; } /** * Download a file from the CDN server. * (Note to self: all last three params could be determined by {@link java.io.File#getPath}) * @param context Any context. * @param dst Local {@link java.io.File} to save. * @param fileName Name of the distant file to download. * @param folder Folder of the distant file to download. * @param ext Extension of the distant file to download. * @return true if file has been successfully downloaded, false in any other case. */ public static boolean downloadFileFromCdn(Context context, File dst, String fileName, String folder, String ext, boolean force) throws IOException { int count; InputStream input; FileOutputStream output; final String cdnLink = context.getResources().getString(R.string.cdn_link); if (force || !dst.exists()) { if (force || dst.createNewFile()) { URL url = new URL(cdnLink + folder + fileName + ext); input = new BufferedInputStream(url.openStream(), 4096); byte data[] = new byte[2048]; output = new FileOutputStream(dst); while ((count = input.read(data)) != -1) { output.write(data, 0, count); } output.flush(); input.close(); output.close(); } else { return false; } } return true; } /** * Check if an internet connection is available * * @param context activity's context * @return true if a connection is available */ public static boolean isNetworkAvailable(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting(); } /** * Unlock an achievement if it is not already unlocked * * @param context Any context. * @param resid Achievement's id. */ public void unlockAchievement(Context context, int resid) { String id = context.getString(resid); if (apiClient != null && this.apiClient.isConnected()) { AnalyticsUtils.sendEvent(context.getString(R.string.ana_cat_game), context.getString(R.string.ana_act_unique_achiev), id); Games.Achievements.unlock(apiClient, id); } } /** * Increment an achievement. * * @param context Any context. * @param resid Achievement's id. */ public void incrementAchievement(Context context, int resid) { String id = context.getString(resid); if (apiClient != null && apiClient.isConnected()) { Games.Achievements.increment(apiClient, id, 1); } } /** * Send a score only if it beats the user's best. * * @param context Any context. * @param resid Leaderboard's id. * @param score Player's score. */ public void sendScore(Context context, int resid, long score) { AppState appState = AppState.getInstance(); String id = context.getString(resid); if (apiClient != null && this.apiClient.isConnected() && (!AppState.getInstance().bestScores.containsKey(id) || (Long.parseLong(AppState.getInstance().bestScores.get(id)) < score))) { appState.bestScores.put(id, Long.toString(score)); appState.changed = true; Games.Leaderboards.submitScore(apiClient, id, score); } } /** * @return Application's version code from the {@code PackageManager}. */ public static int getAppVersion(Context context) { try { PackageManager manager = context.getPackageManager(); PackageInfo packageInfo = null; if (manager != null) packageInfo = manager.getPackageInfo(context.getPackageName(), 0); int version = 0; if (packageInfo != null) version = packageInfo.versionCode; return version; } catch (PackageManager.NameNotFoundException e) { // should never happen throw new RuntimeException("Could not get package name: " + e); } } }