Java tutorial
/* * Copyright (C) 2014 Accelerated I/O, Inc. * * 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.acceleratedio.pac_n_zoom; import android.app.Activity; import android.app.ProgressDialog; import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Path; import android.graphics.PathMeasure; import android.graphics.Rect; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.SoundPool; import android.media.ThumbnailUtils; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.support.v4.view.MotionEventCompat; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; import android.view.animation.Animation.AnimationListener; import android.view.animation.RotateAnimation; import android.view.Display; import android.view.View; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.Button; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.Toast; import com.acceleratedio.pac_n_zoom.DrawSVG; import com.acceleratedio.pac_n_zoom.PickAnmActivity; import com.acceleratedio.pac_n_zoom.R; import com.acceleratedio.pac_n_zoom.SaveAnmActivity; import com.acceleratedio.pac_n_zoom.SelectImageActivity; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.lang.Runnable; import java.lang.Thread; import java.util.ArrayList; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; /** * Created by clive on 03-Jun-14. * www.101apps.co.za * Modified by Accelerated I/O, Inc. */ public class AnimActivity extends Activity { public static LoadSVG.SVGData svg_data; ArrayList<ImageView> anmViews; public static String orgnlImageWdth; public static String orgnlImageHght; private int frm_mbr; private Thread anmThread; ImageView anim_view = null; float[] initScl; private PathMeasure pth_len; // Path length private float stp_len; // Length of animation step final Path path = new Path(); AnimationDrawable animatn = new AnimationDrawable(); public static ProgressDialog progress; private Context crt_ctx; Handler DrwHandler; ImageView orgnlImageView; public static String animFileName; private static int orgnl_iv_wdth; private static int orgnl_iv_hght; private static int bgn_top; private static int bgn_lft; private static int msr_wdth; private static int msr_hght; private static RelativeLayout.LayoutParams orlp = null; private ScaleGestureDetector scaleGestureDetector; private static boolean flgInScale = false; public static float scaleFactor = 1; private float aPosX; private float aPosY; private float bgn_hrz; private float bgn_vrt; private Button sav_anm_btn; // The button that saves the animation private int onClickFlg = 0; private LoadSVG loadSVG; //animation step private static int iMaxAnimationStep = 120; private int iCurStep = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_anm); orgnlImageView = (ImageView) findViewById(R.id.imageView); orgnlImageView.setMaxHeight(800); orgnlImageView.setMaxWidth(600); crt_ctx = this; BitmapFactory.Options bmp_opt = new BitmapFactory.Options(); bmp_opt.inTargetDensity = DisplayMetrics.DENSITY_DEFAULT; // - Now we need to set the GUI ImageView data with data read from the picked file. DcodRszdBmpFil dcodRszdBmpFil = new DcodRszdBmpFil(); Bitmap bmp = dcodRszdBmpFil.DcodRszdBmpFil(SelectImageActivity.orgFil, bmp_opt); // Now we need to set the GUI ImageView data with the orginal file selection. orgnlImageView.setImageBitmap(bmp); orgnl_iv_wdth = bmp.getWidth(); orgnl_iv_hght = bmp.getHeight(); final RelativeLayout rel_anm_lo = (RelativeLayout) findViewById(R.id.activity_anm_lo); scaleGestureDetector = new ScaleGestureDetector(this, new simpleOnScaleGestureListener()); orgnlImageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getPointerCount() > 1 || flgInScale) { scaleGestureDetector.onTouchEvent(event); return true; } int end_hrz; int end_vrt; final int pointerIndex; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: pointerIndex = MotionEventCompat.getActionIndex(event); bgn_hrz = (int) MotionEventCompat.getX(event, pointerIndex); bgn_vrt = (int) MotionEventCompat.getY(event, pointerIndex); String log_str = "Beginning coordinates: Horz = " + String.valueOf(bgn_hrz) + "; Vert = " + String.valueOf(bgn_vrt); Log.d("OnTouchListener", log_str); orlp = (RelativeLayout.LayoutParams) orgnlImageView.getLayoutParams(); bgn_top = (int) orlp.topMargin; bgn_lft = (int) orlp.leftMargin; // To prevent an initial jump of the magnifier, aposX and aPosY must // have the values from the magnifier frame if (aPosX == 0) aPosX = orgnlImageView.getX(); if (aPosY == 0) aPosY = orgnlImageView.getY(); break; case MotionEvent.ACTION_MOVE: pointerIndex = MotionEventCompat.getActionIndex(event); float crt_hrz = MotionEventCompat.getX(event, pointerIndex); float crt_vrt = MotionEventCompat.getY(event, pointerIndex); final float dx = crt_hrz - bgn_hrz; final float dy = crt_vrt - bgn_vrt; aPosX += dx; aPosY += dy; orgnlImageView.setX(aPosX); orgnlImageView.setY(aPosY); log_str = "Current Position: Horz = " + String.valueOf(crt_hrz) + "; Vert = " + String.valueOf(crt_vrt); Log.d("OnTouchListener", log_str); break; case MotionEvent.ACTION_UP: pointerIndex = MotionEventCompat.getActionIndex(event); end_hrz = (int) MotionEventCompat.getX(event, pointerIndex); end_vrt = (int) MotionEventCompat.getY(event, pointerIndex); } rel_anm_lo.invalidate(); return true; } }); sav_anm_btn = (Button) findViewById(R.id.sav_btn); sav_anm_btn.setOnClickListener(new View.OnClickListener() { public void onClick(View vw) { onClickFlg = 1; RelativeLayout rel_anm_lo = (RelativeLayout) findViewById(R.id.activity_anm_lo); rel_anm_lo.removeView(vw); Bitmap tnBmp = getWrtBmp("thumbnail", rel_anm_lo, 40); tnBmp.recycle(); int vw_nmbr = anmViews.size(); for (int vw_mbr = 1; vw_mbr < vw_nmbr; vw_mbr += 1) { anim_view = anmViews.get(vw_mbr); if (anim_view != null) { Animation crt_anm = anim_view.getAnimation(); if (crt_anm != null) crt_anm.cancel(); anim_view.setAnimation(null); rel_anm_lo.removeView(anim_view); // Garbage collect the bitmap Drawable drawable = anim_view.getDrawable(); if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; Bitmap anim_bmp = bitmapDrawable.getBitmap(); anim_bmp.recycle(); } } } Bitmap orgnlImageBmp = getWrtBmp("bgimg", rel_anm_lo, 90); orgnlImageWdth = Integer.toString(orgnlImageBmp.getWidth()); orgnlImageHght = Integer.toString(orgnlImageBmp.getHeight()); anmViews.clear(); unbindDrawables(rel_anm_lo); ((RelativeLayout) rel_anm_lo).removeAllViews(); orgnlImageBmp.recycle(); crt_ctx = null; orgnlImageView = null; Intent intent = new Intent(AnimActivity.this, com.acceleratedio.pac_n_zoom.SaveAnmActivity.class); startActivity(intent); } }); progress = ProgressDialog.show(crt_ctx, "Loading the animation", "dialog message", true); GetRequest get_svg_img = new GetRequest(); get_svg_img.execute(""); } private void unbindDrawables(View view) { if (view.getBackground() != null) view.getBackground().setCallback(null); if (view instanceof ViewGroup && !(view instanceof AdapterView)) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { unbindDrawables(((ViewGroup) view).getChildAt(i)); } ((ViewGroup) view).removeAllViews(); } } public Bitmap getWrtBmp(String bmp_id, View view, int qlty) { int bmp_wdth = view.getWidth(); int bmp_hght = view.getHeight(); Bitmap bmpCaptured = Bitmap.createBitmap(bmp_wdth, bmp_hght, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bmpCaptured); view.draw(canvas); File sdCard = Environment.getExternalStorageDirectory(); File dir = new File(sdCard.getAbsolutePath() + "/acceleratedio/pacnzoom"); dir.mkdirs(); try { File file = new File(dir, "/" + bmp_id + ".jpg"); FileOutputStream fStrm = new FileOutputStream(file); bmpCaptured.compress(Bitmap.CompressFormat.JPEG, qlty, fStrm); fStrm.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return bmpCaptured; } public class simpleOnScaleGestureListener extends SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { Log.d("ScaleListener", "onScale"); scaleFactor *= detector.getScaleFactor(); // prevent our view from becoming too small // scaleFactor = (scaleFactor < 0.3 ? 0.3f : scaleFactor); // Change precision to help with jitter when user just rests their fingers // scaleFactor = ((float) ((int) (scaleFactor * 100))) / 100; orgnlImageView.setScaleX(scaleFactor); orgnlImageView.setScaleY(scaleFactor); orgnlImageView.invalidate(); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { Log.d("MytextView", "onScaleBegin"); flgInScale = true; return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { Log.d("MytextView", "onScaleEnd"); flgInScale = false; } } public class GetRequest extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... urls) { String result = "fail"; int position = getIntent().getIntExtra("position", -1); String httpAddrs = "http://www.pnzanimate.me/Droid/db_rd.php?"; animFileName = PickAnmActivity.fil_nams[position].replace('/', '?') + ".svg"; httpAddrs += animFileName; animFileName = PickAnmActivity.fil_nams[position]; BufferedReader inStream = null; try { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpRequest = new HttpGet(httpAddrs); HttpResponse response = httpClient.execute(httpRequest); inStream = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); StringBuffer buffer = new StringBuffer(""); String line = ""; String NL = System.getProperty("line.separator"); while ((line = inStream.readLine()) != null) { buffer.append(line + NL); } inStream.close(); result = buffer.toString(); progress.dismiss(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); progress.dismiss(); } finally { progress.dismiss(); if (inStream != null) { try { inStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } protected void onPostExecute(String response) { super.onPostExecute(response); anim_svg(response); } } private void anim_svg(String svg_fil) { Toast.makeText(this, "Parsing and Drawing Animation", Toast.LENGTH_SHORT).show(); loadSVG = new LoadSVG(); svg_data = loadSVG.LoadSVG(svg_fil); Log.d("anim_svg", "Return from LoadSVG"); RelativeLayout rel_anm_lo = (RelativeLayout) findViewById(R.id.activity_anm_lo); RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); DrawSVG drw_svg = new DrawSVG(); anmViews = drw_svg.DrawSVG(crt_ctx, orgnlImageView, rel_anm_lo); initScl = svg_data.svg.initScl; /* try { android.os.Debug.dumpHprofData("/sdcard/dump.hprof"); } catch (IOException e) { e.printStackTrace(); } */ // - Loop through the views int vw_nmbr = anmViews.size(); for (int vw_mbr = 1; vw_mbr < vw_nmbr; vw_mbr += 1) { anim_view = anmViews.get(vw_mbr); anim_view.setLayoutParams(rlp); anim_view.setBackgroundColor(Color.TRANSPARENT); rel_anm_lo.addView(anim_view); disableClipOnParents(anim_view); } setContentView(rel_anm_lo); frm_mbr = -1; mainAnmLoop(); } public static void ld_scl_pth_pnts(ArrayList<Integer[]> pnts, Path path) { Integer[] crt_pnt = pnts.get(0); int pnt_nmbr = pnts.size(); int min_x = crt_pnt[0]; int max_x = crt_pnt[0]; int min_y = crt_pnt[1]; int max_y = crt_pnt[1]; // Loop through the points of a path for (int pnt_mbr = 1; pnt_mbr < pnt_nmbr; pnt_mbr += 1) { crt_pnt = pnts.get(pnt_mbr); if (crt_pnt[0] < min_x) min_x = crt_pnt[0]; if (crt_pnt[0] > max_x) max_x = crt_pnt[0]; if (crt_pnt[1] < min_y) min_y = crt_pnt[1]; if (crt_pnt[1] > max_y) max_y = crt_pnt[1]; } float x_dif = (float) (max_x - min_x) / orgnl_iv_wdth; float y_dif = (float) (max_y - min_y) / orgnl_iv_hght; float crt_scl; float ivWdth; float ivHght; if (orgnl_iv_wdth > 480) ivWdth = 480; else ivWdth = orgnl_iv_wdth; if (orgnl_iv_hght > 680) ivHght = 680; else ivHght = orgnl_iv_hght; if (x_dif >= y_dif) crt_scl = (float) ivWdth / svg_data.svg.width * svg_data.g_scl; else crt_scl = (float) ivHght / svg_data.svg.height * svg_data.g_scl; crt_pnt = pnts.get(0); float x_scl = crt_pnt[0] * crt_scl; float y_scl = crt_pnt[1] * crt_scl; path.moveTo(x_scl, y_scl); for (int pnt_mbr = 1; pnt_mbr < pnt_nmbr; pnt_mbr += 1) { crt_pnt = pnts.get(pnt_mbr); x_scl = crt_pnt[0] * crt_scl; y_scl = crt_pnt[1] * crt_scl; path.lineTo(x_scl, y_scl); } } public void disableClipOnParents(View v) { if (v.getParent() == null) return; if (v instanceof ViewGroup) { ((ViewGroup) v).setClipChildren(false); ((ViewGroup) v).setClipToPadding(false); } if (v.getParent() instanceof View) disableClipOnParents((View) v.getParent()); } private void mainAnmLoop() { AnimationSet anmSet = null; if (onClickFlg == 1) { if (anmSet != null) { anmSet.cancel(); anmSet.reset(); } return; } // --- Loop through the frames int frm_nmbr = svg_data.frm.size(); if (++frm_mbr >= frm_nmbr) frm_mbr = 0; // -- You need to turn the sprites on and off for the current frame LoadSVG.frame crt_frm = svg_data.frm.get(frm_mbr); String crt_frm_ordr = crt_frm.frm_ordr; ArrayList<String> sprt_ordr = svg_data.svg.ordr; int crt_dur = crt_frm.end - crt_frm.bgn; // - Loop through the sprites int sprt_nmbr = sprt_ordr.size(); int frm_sprt_mbr = 0; for (int sprt_mbr = 0; sprt_mbr < sprt_nmbr; sprt_mbr += 1) { String sprt_id = sprt_ordr.get(sprt_mbr); int sym_mbr = Integer.parseInt(sprt_id.substring(1, sprt_id.indexOf('_'))) - 2; if (sym_mbr >= 0) { // not g1 which is not loaded LoadSVG.symbol crt_sym = svg_data.symbl.get(sym_mbr); if (crt_frm_ordr.indexOf(sprt_id) >= 0) { // Sprite is present if (crt_sym.aud_id != null && !crt_sym.aud_id.equals("")) { // The sprite is audio SoundPool mSoundPool = loadSVG.getMSoundPool(); int streamId = mSoundPool.play(svg_data.soundId[sym_mbr], 1.0f, 1.0f, 1, 0, 1.0f); mSoundPool.setLoop(streamId, -1); } else { // The sprite is graphic anim_view = anmViews.get(sprt_mbr); anim_view.setAlpha(1f); int xfm_idx = crt_frm.xfm_idx[frm_sprt_mbr]; if (xfm_idx >= 0) { // An animation tag is present anmSet = new AnimationSet(false); LoadSVG.xfrm crt_xfm = svg_data.xfm.get(xfm_idx); ArrayList<Integer[]> pnts = crt_xfm.mov_path; int init_scl = (int) (initScl[sprt_mbr] * 100); if (pnts.size() > 0) { final Path path = new Path(); ld_scl_pth_pnts(pnts, path); PathAnimation pthAnm = new PathAnimation(path); pthAnm.setDuration(crt_dur); pthAnm.setInterpolator(new LinearInterpolator()); pthAnm.setFillAfter(true); // Needed to keep the result of the animation anmSet.addAnimation(pthAnm); } if (crt_xfm.scl_bgn != init_scl) { float crt_scl = crt_xfm.scl_bgn / init_scl; float end_scl = crt_scl; if (crt_xfm.scl_end != crt_xfm.scl_bgn) end_scl = crt_xfm.scl_end / init_scl; ScaleAnimation sclAnm = new ScaleAnimation(crt_scl, end_scl, crt_scl, end_scl, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sclAnm.setDuration(crt_dur); anmSet.addAnimation(sclAnm); } if (crt_xfm.rot_bgn != 0) { float crt_rot = crt_xfm.rot_bgn; float end_rot = crt_rot; if (crt_xfm.rot_end != crt_xfm.rot_bgn) end_rot = crt_xfm.rot_end; RotateAnimation rotAnm = new RotateAnimation(crt_rot, end_rot, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotAnm.setDuration(crt_dur); anmSet.addAnimation(rotAnm); } anim_view.startAnimation(anmSet); //start animation } } frm_sprt_mbr++; } else { // The sprite is not present if (!(crt_sym.aud_id != null && !crt_sym.aud_id.equals(""))) { // The sprite is graphic anim_view = anmViews.get(sprt_mbr); anim_view.setAlpha(0f); } } } else { // g1 if (crt_frm_ordr.indexOf(sprt_id) >= 0) frm_sprt_mbr++; } } waitDur(crt_dur); } void waitDur(int dur) { class DurSleep implements Runnable { int dur; Thread thread; DurSleep(int crt_dur, Thread thread) { dur = crt_dur; thread = anmThread; } @Override public void run() { try { thread.sleep(dur); runOnUiThread(new Runnable() // start actions in UI thread { @Override public void run() { mainAnmLoop(); // this action has to be in UI thread } }); } catch (InterruptedException e) { Log.d("DurSleep", "Sleep Problem"); } } } anmThread = new Thread(new DurSleep(dur, anmThread)); anmThread.start(); } }