de.wikilab.android.friendica01.Max.java Source code

Java tutorial

Introduction

Here is the source code for de.wikilab.android.friendica01.Max.java

Source

package de.wikilab.android.friendica01;

/* 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/. */
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.io.Writer;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONObject;

import de.wikilab.android.friendica01.activity.PreferencesActivity;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

/**
 * this is a historically grown and named class which contains all sorts of static helper functions
 * m(
 */
public class Max {
    private static final String TAG = "Friendica/Max";

    public static final String DATA_DIR = "/sdcard/Android/data/de.wikilab.android.friendica01";
    public static final String IMG_CACHE_DIR = Max.DATA_DIR + "/cache/imgs";

    public static PendingIntent piTimerNotifications;

    public static void initDataDirs() {
        new File(DATA_DIR).mkdirs();
        new File(IMG_CACHE_DIR).mkdirs();

    }

    public static boolean isLarge(Configuration c) {
        return (((c.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE)
                || ((c.screenLayout
                        & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE));
    }

    public static String Hexdump(byte[] data) {
        StringBuffer b = new StringBuffer();
        char[] parts = new char[17];
        int partsloc = 0;
        for (int i = 0; i < data.length; i++) {
            int d = ((int) data[i]) & 0xff;
            if (d == 0) {
                parts[partsloc++] = '.';
            } else if (d < 32 || d >= 127) {
                parts[partsloc++] = '?';
            } else {
                parts[partsloc++] = (char) d;
            }
            if (i % 16 == 0) {
                int start = Integer.toHexString(data.length).length();
                int end = Integer.toHexString(i).length();

                for (int j = start; j > end; j--) {
                    b.append("0");
                }
                b.append(Integer.toHexString(i) + ": ");
            }
            if (d < 16) {
                b.append("0" + Integer.toHexString(d));
            } else {
                b.append(Integer.toHexString(d));
            }
            if ((i & 15) == 15 || i == data.length - 1) {
                b.append("      " + new String(parts) + "\n");
                partsloc = 0;
            } else if ((i & 7) == 7) {
                b.append("  ");
                parts[partsloc++] = ' ';
            } else if ((i & 1) == 1) {
                b.append(" ");
            }
        }
        b.append("\n");
        return b.toString();
    }

    public static void runTimer(Context c) {
        Log.i("Friendica", "try runTimer");
        if (piTimerNotifications != null)
            return;
        AlarmManager a = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
        piTimerNotifications = PendingIntent.getService(c, 1, new Intent(c, NotificationCheckerService.class), 0);
        a.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 0, AlarmManager.INTERVAL_FIFTEEN_MINUTES,
                piTimerNotifications);
        Toast.makeText(c, "Friendica: Notif. check timer run", Toast.LENGTH_SHORT).show();
        Log.i("Friendica", "done runTimer");
    }

    public static void cancelTimer(Context c) {
        Log.i("Friendica", "try cancelTimer");
        if (piTimerNotifications == null)
            return;
        AlarmManager a = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
        a.cancel(piTimerNotifications);
        piTimerNotifications = null;
        Toast.makeText(c, "Friendica: Notif. check timer cancel", Toast.LENGTH_SHORT).show();
        Log.i("Friendica", "done cancelTimer");
    }

    public static String readFile(String path) throws IOException {
        FileInputStream stream = new FileInputStream(new File(path));
        try {
            FileChannel fc = stream.getChannel();
            MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
            /* Instead of using default, pass in a decoder. */
            return Charset.defaultCharset().decode(bb).toString();
        } finally {
            stream.close();
        }
    }

    public static String getServer(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getString("login_protocol", null) + "://" + prefs.getString("login_server", null);
    }

    public static File getTempFile() {
        return new File(Max.IMG_CACHE_DIR, "imgUploadTemp_" + System.currentTimeMillis() + ".jpg");
    }

    /**
    * Calls the api method <code>verify_credentials</code> with the login data
     * saved in the <code>SharedPreferences</code>. Calls ctx.OnLogin on success,
     * showLoginForm(ctx, "error") on error
    * @param ctx     MUST IMPLEMENT LoginListener !!!
    */
    public static void tryLogin(final Activity ctx) {

        final ProgressDialog pd = new ProgressDialog(ctx);
        pd.setMessage(ctx.getResources().getString(R.string.logging_in));
        pd.show();

        String server = Max.getServer(ctx);
        Log.i(TAG, "tryLogin on server " + server);

        final TwAjax t = new TwAjax(ctx, true, true);
        t.getUrlContent(server + "/api/account/verify_credentials", new Runnable() {
            @Override
            public void run() {
                pd.dismiss();
                try {
                    if (t.isSuccess()) {
                        Log.i(TAG, "... tryLogin - http status: " + t.getHttpCode());
                        if (t.getHttpCode() == 200) {
                            JSONObject r = (JSONObject) t.getJsonResult();
                            String name = r.getString("name");
                            ((TextView) ctx.findViewById(R.id.selected_clipboard)).setText(name);
                            ((LoginListener) ctx).OnLogin();

                            final TwAjax profileImgDl = new TwAjax();
                            final String targetFs = IMG_CACHE_DIR + "/my_profile_pic_" + r.getString("id") + ".jpg";
                            if (new File(targetFs).isFile()) {
                                ((ImageView) ctx.findViewById(R.id.profile_image))
                                        .setImageURI(Uri.parse("file://" + targetFs));
                            } else {
                                profileImgDl.urlDownloadToFile(r.getString("profile_image_url"), targetFs,
                                        new Runnable() {
                                            @Override
                                            public void run() {
                                                ((ImageView) ctx.findViewById(R.id.profile_image))
                                                        .setImageURI(Uri.parse("file://" + targetFs));
                                            }
                                        });
                            }

                        } else {
                            showLoginForm(ctx, "Error: " + t.getResult());
                        }
                    } else {
                        Log.w(TAG, "... tryLogin - request failed");
                        showLoginForm(ctx, "ERR: " + t.getError().toString());
                    }

                } catch (Exception ex) {
                    Log.w(TAG, "... tryLogin - exception:");
                    ex.printStackTrace();
                    showLoginForm(ctx, "ERR2: " + t.getResult() + ex.toString());

                }
            }
        });
    }

    /**
     * displays the login form (layout/loginscreen.xml) as a modal dialog and calls tryLogin
      * when user confirms the form
     * @param ctx     MUST IMPLEMENT LoginListener !!!
     * @param errmes  message which is displayed above the Login form (e.g. "wrong password entered")
     */
    public static void showLoginForm(final Activity ctx, String errmes) {
        Log.v(TAG, "... showLoginForm");
        View myView = ctx.getLayoutInflater().inflate(R.layout.loginscreen, null, false);
        final AlertDialog alert = new AlertDialog.Builder(ctx).setTitle("Login to Friendica").setView(myView)
                .setOnCancelListener(new OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        ctx.finish();
                    }
                }).show();

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        String protocol = prefs.getString("login_protocol", "https");
        String server = prefs.getString("login_server", null);
        String userName = prefs.getString("login_user", null);

        if (errmes != null) {
            ((TextView) myView.findViewById(R.id.lblInfo)).setText(errmes);
        }

        final Spinner selProtocol = (Spinner) myView.findViewById(R.id.selProtocol);
        selProtocol.setSelection(protocol.equals("https") ? 1 : 0); //HACK !!!

        final EditText edtServer = (EditText) myView.findViewById(R.id.edtServer);
        edtServer.setText(server);

        final EditText edtUser = (EditText) myView.findViewById(R.id.edtUser);
        edtUser.setText(userName);

        final EditText edtPassword = (EditText) myView.findViewById(R.id.edtPassword);

        ((TextView) myView.findViewById(R.id.proxy_settings)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ctx.startActivity(new Intent(ctx, PreferencesActivity.class));
            }
        });

        ((Button) myView.findViewById(R.id.button1)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences.Editor prefs = PreferenceManager.getDefaultSharedPreferences(ctx).edit();
                prefs.putString("login_protocol", selProtocol.getSelectedItem().toString());
                String server = edtServer.getText().toString();
                server = server.replaceAll("^https?://", "");
                prefs.putString("login_server", server);
                prefs.putString("login_user", edtUser.getText().toString());
                prefs.putString("login_password", edtPassword.getText().toString());
                prefs.commit();

                alert.dismiss();

                tryLogin(ctx);
            }
        });
    }

    //warum muss das in Android so kompliziert sein???
    public static void resizeImage(String pathOfInputImage, String pathOfOutputImage, int dstWidth, int dstHeight) {
        try {
            int inWidth = 0;
            int inHeight = 0;

            InputStream in = new FileInputStream(pathOfInputImage);

            // decode image size (decode metadata only, not the whole image)
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, options);
            in.close();
            in = null;

            // save width and height
            inWidth = options.outWidth;
            inHeight = options.outHeight;

            // decode full image pre-resized
            in = new FileInputStream(pathOfInputImage);
            options = new BitmapFactory.Options();
            // calc rought re-size (this is no exact resize)
            options.inSampleSize = Math.max(inWidth / dstWidth, inHeight / dstHeight);
            // decode full image
            Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);

            // calc exact destination size
            Matrix m = new Matrix();
            RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
            RectF outRect = new RectF(0, 0, dstWidth, dstHeight);
            m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
            float[] values = new float[9];
            m.getValues(values);

            // resize bitmap
            Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap,
                    (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);

            // save image
            try {
                FileOutputStream out = new FileOutputStream(pathOfOutputImage);
                resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
            } catch (Exception e) {
                Log.e("Image", e.getMessage(), e);
            }
        } catch (IOException e) {
            Log.e("Image", e.getMessage(), e);
        }
    }

    private static final int IO_BUFFER_SIZE = 4 * 1024;

    /**
    * Copy the content of the input stream into the output stream, using a temporary 
    * byte array buffer whose size is defined by {@link #IO_BUFFER_SIZE}.
    * 
    * @param in The input stream to copy from. 
    * @param out The output stream to copy to. 
    * 
    * @throws IOException If any error occurs during the copy. 
    */
    public static void copy(InputStream in, OutputStream out) throws IOException {
        byte[] b = new byte[IO_BUFFER_SIZE];
        int read;
        while ((read = in.read(b)) != -1) {
            out.write(b, 0, read);
        }
    }

    public static String getBaseName(String fileSpec) {
        if (fileSpec == null)
            return null;
        int pos = fileSpec.lastIndexOf("/");
        if (pos == -1)
            return fileSpec;
        else
            return fileSpec.substring(pos + 1);
    }

    public static String getBaseNameWithoutExtension(String fileSpec) {
        if (fileSpec == null)
            return null;
        return getBaseName(fileSpec).replaceFirst("[.][^.]+$", "");
    }

    public static String getFileExtension(String fileSpec) {
        if (fileSpec == null)
            return null;
        int pos = fileSpec.lastIndexOf(".");
        if (pos == -1)
            return fileSpec;
        else
            return fileSpec.substring(pos + 1);
    }

    public static String getRealPathFromURI(Context ctx, Uri contentUri) {
        Log.i("FileTypes", "URI = " + contentUri + ", scheme = " + contentUri.getScheme());
        if (contentUri.getScheme().equals("file")) {
            return contentUri.getPath();
        } else {
            String[] proj = { MediaStore.Images.Media.DATA };
            Cursor cursor = ctx.getContentResolver().query(contentUri, proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            String res = cursor.getString(column_index);
            cursor.close();
            return res;
        }
    }

    public static String cleanFilename(String url) {
        return url.replaceAll("[^a-z0-9.-]", "_");

    }

    public static Matcher regeximatch(String pattern, String string) {
        return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(string);
    }

    public static void alert(Context ctx, String text) {
        alert(ctx, text, null, "OK");
    }

    public static void alert(Context ctx, String text, String title) {
        alert(ctx, text, title, "OK");
    }

    public static void alert(Context ctx, String text, String title, String okButtonText) {
        AlertDialog ad = new AlertDialog.Builder(ctx).create();
        ad.setCancelable(false); // This blocks the 'BACK' button  
        ad.setMessage(Html.fromHtml(text));
        ad.setTitle(title);
        ad.setButton(okButtonText, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        ad.show();
        ((TextView) ad.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
    }

    /*
     Return Throwable stacktrace as String
    */
    public static String getStackTrace(Throwable aThrowable) {
        final Writer result = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(result);
        aThrowable.printStackTrace(printWriter);
        return result.toString();
    }

}