熊猫儿 发表于 2016-9-29 16:03

http://img.blog.csdn.net/20150929234028400?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

view plain copy



[*]<?xml version="1.0" encoding="utf-8"?>
[*]<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
[*]    android:layout_width="match_parent"
[*]    android:layout_height="match_parent"
[*]    android:orientation="vertical" >
[*]
[*]    <ImageView
[*]      android:id="@+id/image"
[*]      android:layout_width="match_parent"
[*]      android:layout_height="wrap_content"
[*]      android:src="@drawable/nightfall_starlight_panoramic9"
[*]      android:scaleType="centerCrop" />
[*]
[*]    <LinearLayout
[*]      android:layout_width="match_parent"
[*]      android:layout_height="wrap_content"
[*]      android:gravity="center_horizontal"
[*]      android:orientation="vertical"
[*]      android:padding="10dp"
[*]      android:visibility="visible" >
[*]
[*]      <TextView
[*]            android:layout_width="wrap_content"
[*]            android:layout_height="wrap_content"
[*]            android:text="色相"
[*]            android:textAppearance="?android:attr/textAppearanceSmall" />
[*]
[*]      <SeekBar
[*]            android:id="@+id/hue"
[*]            android:layout_width="match_parent"
[*]            android:layout_height="wrap_content"
[*]            android:layout_marginBottom="10dp" />
[*]
[*]      <TextView
[*]            android:layout_width="wrap_content"
[*]            android:layout_height="wrap_content"
[*]            android:text="饱和度"
[*]            android:textAppearance="?android:attr/textAppearanceSmall" />
[*]
[*]      <SeekBar
[*]            android:id="@+id/saturation"
[*]            android:layout_width="match_parent"
[*]            android:layout_height="wrap_content"
[*]            android:layout_marginBottom="10dp" />
[*]
[*]      <TextView
[*]            android:layout_width="wrap_content"
[*]            android:layout_height="wrap_content"
[*]            android:text="明度"
[*]            android:textAppearance="?android:attr/textAppearanceSmall" />
[*]
[*]      <SeekBar
[*]            android:id="@+id/lum"
[*]            android:layout_width="match_parent"
[*]            android:layout_height="wrap_content" />
[*]    </LinearLayout>
[*]
[*]    <LinearLayout
[*]      android:layout_width="match_parent"
[*]      android:layout_height="wrap_content"
[*]      android:gravity="center_horizontal" >
[*]
[*]      <Button
[*]            android:layout_width="wrap_content"
[*]            android:layout_height="wrap_content"
[*]            android:onClick="start"
[*]            android:text="start"
[*]            android:visibility="visible" />
[*]
[*]      <Button
[*]            android:layout_width="wrap_content"
[*]            android:layout_height="wrap_content"
[*]            android:onClick="reset"
[*]            android:text="reset"
[*]            android:visibility="visible" />
[*]
[*]      <Button
[*]            android:layout_width="wrap_content"
[*]            android:layout_height="wrap_content"
[*]            android:onClick="stop"
[*]            android:text="stop"
[*]            android:visibility="visible" />
[*]    </LinearLayout>
[*]
[*]</LinearLayout>


熊猫儿 发表于 2016-9-30 16:46

贴实现代码:
view plain copy



[*]package com.sahadev;
[*]
[*]import android.app.Activity;
[*]import android.graphics.Bitmap;
[*]import android.graphics.Canvas;
[*]import android.graphics.ColorMatrix;
[*]import android.graphics.ColorMatrixColorFilter;
[*]import android.graphics.Paint;
[*]import android.os.Bundle;
[*]import android.view.View;
[*]import android.widget.ImageView;
[*]import android.widget.SeekBar;
[*]import android.widget.SeekBar.OnSeekBarChangeListener;
[*]
[*]import com.lidroid.xutils.view.annotation.ViewInject;
[*]
[*]public class MainActivity3 extends Activity implements OnSeekBarChangeListener, Runnable {
[*]    @ViewInject(R.id.hue)
[*]    SeekBar hue;
[*]    @ViewInject(R.id.saturation)
[*]    SeekBar saturation;
[*]    @ViewInject(R.id.lum)
[*]    SeekBar lum;
[*]    @ViewInject(R.id.image)
[*]    ImageView image;
[*]
[*]    // 颜色的最大值255,中间值127
[*]    private final static int MAX_VALUE = 255, MID_VALUE = 127;
[*]    // 临时 色相,饱和度,明度
[*]    private float mHue, mSaturation, mLum;
[*]    // 被处理的图像
[*]    private Bitmap bitmap;
[*]    // 临时变换值
[*]    private int tempValue = MID_VALUE;
[*]    // 运行标志位
[*]    private boolean runFlag;
[*]
[*]    @Override
[*]    protected void onCreate(Bundle savedInstanceState) {
[*]      super.onCreate(savedInstanceState);
[*]      setContentView(R.layout.primary_color);
[*]      com.lidroid.xutils.ViewUtils.inject(this);
[*]
[*]      // 将图片缩放到屏幕的适合尺寸
[*]      bitmap = MainActivity.scaleImage(this, R.drawable.nightfall_starlight_panoramic9);
[*]      // 事件绑定
[*]      hue.setOnSeekBarChangeListener(this);
[*]      saturation.setOnSeekBarChangeListener(this);
[*]      lum.setOnSeekBarChangeListener(this);
[*]
[*]      // 进行初始化状态
[*]      hue.setMax(MAX_VALUE);
[*]      saturation.setMax(MAX_VALUE);
[*]      lum.setMax(MAX_VALUE);
[*]      reset(null);
[*]      image.setImageBitmap(bitmap);
[*]    }


熊猫儿 发表于 2016-9-30 16:46


[*] /*
[*]   * 进行循环任务
[*]   *
[*]   * @see java.lang.Runnable#run()
[*]   */
[*]    @Override
[*]    public void run() {
[*]      hue.setProgress(tempValue++);
[*]      if (tempValue == MAX_VALUE) {
[*]            tempValue = 0;
[*]      }
[*]      if (!runFlag) {
[*]            return;
[*]      }
[*]      image.postDelayed(this, 10);
[*]    }
[*]
[*]    /**
[*]   * 停止循环
[*]   *
[*]   * @param view
[*]   */
[*]    public void stop(View view) {
[*]      runFlag = false;
[*]    }
[*]
[*]    /**
[*]   * 开始循环滚动
[*]   *
[*]   * @param view
[*]   */
[*]    public void start(View view) {
[*]      runFlag = true;
[*]      image.postDelayed(this, 100);
[*]    }
[*]
[*]    /**
[*]   * 重置
[*]   *
[*]   * @param view
[*]   */
[*]    public void reset(View view) {
[*]      hue.setProgress(MID_VALUE);
[*]      saturation.setProgress(MID_VALUE);
[*]      lum.setProgress(MID_VALUE);
[*]      tempValue = MID_VALUE;
[*]    }
[*]
[*]    /*
[*]   * 根据Seekbar的进度控制图片的效果
[*]   */
[*]    @Override
[*]    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
[*]      switch (seekBar.getId()) {
[*]      case R.id.hue:
[*]            mHue = (progress - MID_VALUE) * 1.0f / MID_VALUE * 180;
[*]            break;
[*]      case R.id.saturation:
[*]            mSaturation = progress * 1.0f / MID_VALUE;
[*]            break;
[*]      case R.id.lum:
[*]            mLum = progress * 1.0f / MID_VALUE;
[*]            break;

熊猫儿 发表于 2016-9-30 16:47




[*]      default:
[*]            break;
[*]      }
[*]      image.setImageBitmap(ImageHelper.handleImageEffect(bitmap, mHue, mSaturation, mLum));
[*]    }
[*]
[*]    @Override
[*]    public void onStartTrackingTouch(SeekBar seekBar) {
[*]
[*]    }
[*]
[*]    @Override
[*]    public void onStopTrackingTouch(SeekBar seekBar) {
[*]
[*]    }
[*]
[*]    public static class ImageHelper {
[*]      /**
[*]         * 处理图像
[*]         *
[*]         * @param bitmap
[*]         *            原图
[*]         * @param degrees
[*]         *            色相值
[*]         * @param sat
[*]         *            饱和度值
[*]         * @param lum
[*]         *            明度值
[*]         * @return 处理后的图像
[*]         *
[*]         */
[*]      public static Bitmap handleImageEffect(Bitmap bitmap, float degrees, float sat, float lum) {
[*]
[*]            Bitmap temp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
[*]
[*]            Canvas canvas = new Canvas(temp);
[*]
[*]            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
[*]
[*]            // 设置色相
[*]            ColorMatrix hueMatrix = new ColorMatrix();
[*]            hueMatrix.setRotate(0, degrees);
[*]            hueMatrix.setRotate(1, degrees);
[*]            hueMatrix.setRotate(2, degrees);
[*]
[*]            // 设置饱和度
[*]            ColorMatrix saturationMatrix = new ColorMatrix();
[*]            saturationMatrix.setSaturation(sat);
[*]
[*]            // 设置明度
[*]            ColorMatrix lumMatrix = new ColorMatrix();
[*]            lumMatrix.setScale(lum, lum, lum, 1);

熊猫儿 发表于 2016-9-30 16:48


[*]    // 融合
[*]            ColorMatrix imageMatrix = new ColorMatrix();
[*]            imageMatrix.postConcat(lumMatrix);
[*]            imageMatrix.postConcat(saturationMatrix);
[*]            imageMatrix.postConcat(hueMatrix);
[*]
[*]            // 给paint设置颜色属性
[*]            paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
[*]
[*]            // 绘制
[*]            canvas.drawBitmap(bitmap, 0, 0, paint);
[*]
[*]            return temp;
[*]
[*]      }
[*]    }
[*]
[*]}
http://static.blog.csdn.net/images/save_snippets.png


在onCreate方法里刚开始会调用一个scaleImage的方法,该方法可以出门左转参见如何适配APP引导页的文章,有详细介绍。
地址:http://blog.csdn.net/sahadev_/article/details/48475217没想到安卓提供的图片处理效果这么强大,也了解到原来图片处理是通过矩阵来算的,其它知识请自行查阅。
快试一下效果吧!

熊猫儿 发表于 2016-9-30 16:50

从源码角度分析Android系统的异常捕获机制是如何运行的
标签: android异常处理机制Android自定义异常处理
2015-10-10 17:54 352人阅读 评论(0) 收藏 举报

http://static.blog.csdn.net/images/category_icon.jpg 分类:
源码分析(18) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg

版权声明:本文为博主原创文章,未经博主允许不得转载。
我们在开发的时候经常会遇到各种异常,当程序遇到异常,便会将异常信息抛到LogCat中,那这个过程是怎么实现的呢?

我们以一个例子开始:

view plain copy



[*]import android.app.Activity;
[*]import android.os.Bundle;
[*]
[*]public class MainActivity4 extends Activity {
[*]
[*]    @Override
[*]    protected void onCreate(Bundle savedInstanceState) {
[*]      super.onCreate(savedInstanceState);
[*]
[*]      throw new NullPointerException();
[*]    }
[*]}


这个程序一启动便会抛一个异常到Logcat中,就像这样:

view plain copy



[*]10-10 16:44:16.200: W/dalvikvm(381): threadid=1: thread exiting with uncaught exception (group=0x41588d58)
[*]10-10 16:44:16.200: W/System.err(381): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sahadev.renren/com.sahadev.activitythemetest.MainActivity4}: java.lang.NullPointerException
[*]10-10 16:44:16.200: W/System.err(381):at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2263)
[*]10-10 16:44:16.200: W/System.err(381):at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2313)
[*]10-10 16:44:16.200: W/System.err(381):at android.app.ActivityThread.access$800(ActivityThread.java:147)
[*]10-10 16:44:16.200: W/System.err(381):at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1226)
[*]10-10 16:44:16.200: W/System.err(381):at android.os.Handler.dispatchMessage(Handler.java:102)
[*]10-10 16:44:16.200: W/System.err(381):at android.os.Looper.loop(Looper.java:136)
[*]10-10 16:44:16.200: W/System.err(381):at android.app.ActivityThread.main(ActivityThread.java:5137)
[*]10-10 16:44:16.200: W/System.err(381):at java.lang.reflect.Method.invokeNative(Native Method)
[*]10-10 16:44:16.200: W/System.err(381):at java.lang.reflect.Method.invoke(Method.java:515)
[*]10-10 16:44:16.200: W/System.err(381):at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:801)
[*]10-10 16:44:16.200: W/System.err(381):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:617)
[*]10-10 16:44:16.200: W/System.err(381):at dalvik.system.NativeStart.main(Native Method)
[*]10-10 16:44:16.200: W/System.err(381): Caused by: java.lang.NullPointerException
[*]10-10 16:44:16.200: W/System.err(381):at com.sahadev.activitythemetest.MainActivity4.onCreate(MainActivity4.java:12)
[*]10-10 16:44:16.200: W/System.err(381):at android.app.Activity.performCreate(Activity.java:5231)
[*]10-10 16:44:16.200: W/System.err(381):at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
[*]10-10 16:44:16.200: W/System.err(381):at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2227)
[*]10-10 16:44:16.200: W/System.err(381):... 11 more



熊猫儿 发表于 2016-10-1 23:01

好,异常信息就会通过Logcat输出出来,接下来我们一起看一下它内部的工作原理:
首先:我们知道通常我们在处理全局自定义异常的时候通常会这么写:
view plain copy



[*]import java.lang.Thread.UncaughtExceptionHandler;
[*]
[*]public class YikaoGlobalCrashHandler implements UncaughtExceptionHandler {
[*]
[*]    public YikaoGlobalCrashHandler() {
[*]      super();
[*]
[*]      Thread.setDefaultUncaughtExceptionHandler(this);
[*]
[*]    }
[*]
[*]    @Override
[*]    public void uncaughtException(Thread thread, Throwable ex) {
[*]
[*]    }
[*]}

通过这样的方式,我们便可以使程序在遇到异常的时候回调我们的对象实例,然后调用我们的uncaughtException方法。我们知道,如果我们不这么设定,系统是会自己处理异常的,那就一定有一个默认的异常处理对象,没错:
view plain copy



[*]Thread.getDefaultUncaughtExceptionHandler();

通过这个方法会返回一个系统默认的UncaughtExceptionHandler对象,那么这个对象是在哪被设置进去的呢?我们从源代码里面找答案:
咱们从Java最基础层面看起,我们的JAVA入口是:com.android.internal.os.RuntimeInit类的main方法,至于main方法在哪被调用,我们以后再讨论:
view plain copy



[*]public static final void main(String[] argv) {
[*]       if (argv.length == 2 && argv.equals("application")) {
[*]         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
[*]         redirectLogStreams();
[*]       } else {
[*]         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
[*]       }
[*]
[*]       commonInit();
[*]
[*]       /*
[*]      * Now that we're running in interpreted code, call back into native code
[*]      * to run the system.
[*]      */
[*]       nativeFinishInit();
[*]
[*]       if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
[*]   }
http://static.blog.csdn.net/images/save_snippets.png



熊猫儿 发表于 2016-10-1 23:01

我们关注的是commonInit方法:

view plain copy



[*]private static final void commonInit() {
[*]    if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
[*]
[*]    /* set default handler; this applies to all threads in the VM */
[*]    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
[*]
[*]    /*
[*]   * Install a TimezoneGetter subclass for ZoneInfo.db
[*]   */
[*]    TimezoneGetter.setInstance(new TimezoneGetter() {
[*]      @Override
[*]      public String getId() {
[*]            return SystemProperties.get("persist.sys.timezone");
[*]      }
[*]    });
[*]    TimeZone.setDefault(null);
[*]
[*]    /*
[*]   * Sets handler for java.util.logging to use Android log facilities.
[*]   * The odd "new instance-and-then-throw-away" is a mirror of how
[*]   * the "java.util.logging.config.class" system property works. We
[*]   * can't use the system property here since the logger has almost
[*]   * certainly already been initialized.
[*]   */
[*]    LogManager.getLogManager().reset();
[*]    new AndroidConfig();
[*]
[*]    /*
[*]   * Sets the default HTTP User-Agent used by HttpURLConnection.
[*]   */
[*]    String userAgent = getDefaultUserAgent();
[*]    System.setProperty("http.agent", userAgent);
[*]
[*]    /*
[*]   * Wire socket tagging to traffic stats.
[*]   */
[*]    NetworkManagementSocketTagger.install();
[*]
[*]    /*
[*]   * If we're running in an emulator launched with "-trace", put the
[*]   * VM into emulator trace profiling mode so that the user can hit
[*]   * F9/F10 at any time to capture traces.This has performance
[*]   * consequences, so it's not something you want to do always.
[*]   */
[*]    String trace = SystemProperties.get("ro.kernel.android.tracing");
[*]    if (trace.equals("1")) {
[*]      Slog.i(TAG, "NOTE: emulator trace profiling enabled");
[*]      Debug.enableEmulatorTraceOutput();
[*]    }
[*]
[*]    initialized = true;
[*]}


熊猫儿 发表于 2016-10-1 23:04

在我们代码的第二行看到:Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());那这个UncaughtHandler类在哪被定义呢?我们还可以在RuntimeInit.java中找到答案:

view plain copy



[*]/**
[*] * Use this to log a message when a thread exits due to an uncaught
[*] * exception.The framework catches these for the main threads, so
[*] * this should only matter for threads created by applications.
[*] */
[*]private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
[*]    public void uncaughtException(Thread t, Throwable e) {
[*]      try {
[*]            // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
[*]            if (mCrashing) return;
[*]            mCrashing = true;
[*]
[*]            if (mApplicationObject == null) {
[*]                Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
[*]            } else {
[*]                StringBuilder message = new StringBuilder();
[*]                message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
[*]                final String processName = ActivityThread.currentProcessName();
[*]                if (processName != null) {
[*]                  message.append("Process: ").append(processName).append(", ");
[*]                }
[*]                message.append("PID: ").append(Process.myPid());
[*]                Clog_e(TAG, message.toString(), e);
[*]            }
[*]
[*]            // Bring up crash dialog, wait for it to be dismissed
[*]            ActivityManagerNative.getDefault().handleApplicationCrash(
[*]                  mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
[*]      } catch (Throwable t2) {
[*]            try {
[*]                Clog_e(TAG, "Error reporting crash", t2);
[*]            } catch (Throwable t3) {
[*]                // Even Clog_e() fails!Oh well.
[*]            }
[*]      } finally {
[*]            // Try everything to make sure this process goes away.
[*]            Process.killProcess(Process.myPid());
[*]            System.exit(10);
[*]      }
[*]    }
[*]}


熊猫儿 发表于 2016-10-1 23:06

我们看到代码中使用StringBuilder的message对象对基本信息进行了组合,然后调用Clog_e方法,Clog_e方法通过Log.println_native(Log.LOG_ID_CRASH, Log.ERROR, tag,msg + '\n' + Log.getStackTraceString(tr));将Log日志输出到控制台。接下来会调用 view plain copy



[*]// Bring up crash dialog, wait for it to be dismissed
[*]ActivityManagerNative.getDefault().handleApplicationCrash(mApplicationObject, new ApplicationErrorReport.CrashInfo(e));

方法将我们的崩溃的Dialog显示出来,就像这样:
http://img.blog.csdn.net/20151010174504153?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast最终它还会将我们的程序杀死退出:
view plain copy



[*]// Try everything to make sure this process goes away.
[*]Process.killProcess(Process.myPid());
[*]System.exit(10);


好这就是系统为我们提供的默认异常处理方法,接下来当然还有不少疑问:
1.RuntimeInit类的main方法是在哪被调用的。2.throw new NullPointerException();这部分是怎么执行的。3.Thread的defaultUncaughtHandler属性又是在哪被调用的。4.等等
欢迎对这方面有兴趣的可以在评论区参与讨论,也有可能是我学的还太少。
页: 29 30 31 32 33 34 35 36 37 38 [39] 40 41 42 43 44 45 46 47 48
查看完整版本: 【Android的一些重要知识6。。。。】