熊猫儿
发表于 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.等等
欢迎对这方面有兴趣的可以在评论区参与讨论,也有可能是我学的还太少。