From d6697a582b8919434ef4974b2a22f7a3fdc1a6d3 Mon Sep 17 00:00:00 2001 From: clock <1084991652clock@gmail.com> Date: Wed, 8 Jun 2016 15:55:32 +0800 Subject: [PATCH 01/38] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug=EF=BC=8C=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=85=BC=E5=AE=B9=E9=97=AE=E9=A2=98=EF=BC=8C=E8=AF=A6?= =?UTF-8?q?=E8=A7=81README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- build.gradle | 12 ++ .../study/activity/CapturePhotoActivity.java | 122 ++++++++++++++++-- .../clock/study/manager/FolderManager.java | 7 + src/main/res/values/strings.xml | 4 + 5 files changed, 137 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 03deee0..48fcbd4 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ - 本库libs下有个**AndroidUtils.aar**的依赖包,是由[AndroidUtils](https://github.com/D-clock/AndroidUtils)代码编译生成; - 想要查看**AndroidUtils.aar**中的源代码,可以参考[这里](https://github.com/D-clock/Doc/blob/master/Android/%E4%B8%AA%E4%BA%BA%E6%94%B6%E8%97%8F/%E5%A6%82%E4%BD%95%E6%9F%A5%E7%9C%8Baar%E7%9A%84%E6%BA%90%E4%BB%A3%E7%A0%81.md) -## 最新更新(编辑于2016-05-27) +## 最新更新(编辑于2016-06-08) -- 优化拍照实现; -- 优化项目导入体验; +- 兼容处理 Android M 版本的 Runtime Permission ; +- 优化 build.gradle ,提高导入 moudle 体验; ## 归档文章 diff --git a/build.gradle b/build.gradle index 29a1179..d52e2a3 100644 --- a/build.gradle +++ b/build.gradle @@ -32,3 +32,15 @@ dependencies { //compile project(":AndroidUtils") compile 'com.android.support:appcompat-v7:23.2.1' } + + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.1.0' + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} \ No newline at end of file diff --git a/src/main/java/com/clock/study/activity/CapturePhotoActivity.java b/src/main/java/com/clock/study/activity/CapturePhotoActivity.java index 9cbe5d1..f0d813b 100644 --- a/src/main/java/com/clock/study/activity/CapturePhotoActivity.java +++ b/src/main/java/com/clock/study/activity/CapturePhotoActivity.java @@ -1,10 +1,20 @@ package com.clock.study.activity; +import android.Manifest; +import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.provider.Settings; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; +import android.widget.Toast; import com.clock.study.R; import com.clock.study.helper.CapturePhotoHelper; @@ -23,6 +33,11 @@ public class CapturePhotoActivity extends AppCompatActivity implements View.OnCl private final static String TAG = CapturePhotoActivity.class.getSimpleName(); private final static String EXTRA_RESTORE_PHOTO = "extra_restore_photo"; + /** + * 运行时权限申请码 + */ + private final static int RUNTIME_PERMISSION_REQUEST_CODE = 0x1; + private CapturePhotoHelper mCapturePhotoHelper; private File mRestorePhotoFile; @@ -32,8 +47,6 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera_take_photo); - mCapturePhotoHelper = new CapturePhotoHelper(this, FolderManager.getPhotoFolder()); - findViewById(R.id.iv_take_photo).setOnClickListener(this); } @@ -42,29 +55,62 @@ protected void onCreate(Bundle savedInstanceState) { protected void onSaveInstanceState(Bundle outState) { Log.i(TAG, "onSaveInstanceState"); super.onSaveInstanceState(outState); - mRestorePhotoFile = mCapturePhotoHelper.getPhoto(); - Log.i(TAG, "onSaveInstanceState , mRestorePhotoFile: " + mRestorePhotoFile); - if (mRestorePhotoFile != null) { - outState.putSerializable(EXTRA_RESTORE_PHOTO, mRestorePhotoFile); + if (mCapturePhotoHelper != null) { + mRestorePhotoFile = mCapturePhotoHelper.getPhoto(); + Log.i(TAG, "onSaveInstanceState , mRestorePhotoFile: " + mRestorePhotoFile); + if (mRestorePhotoFile != null) { + outState.putSerializable(EXTRA_RESTORE_PHOTO, mRestorePhotoFile); + } } - } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { Log.i(TAG, "onRestoreInstanceState"); super.onRestoreInstanceState(savedInstanceState); - mRestorePhotoFile = (File) savedInstanceState.getSerializable(EXTRA_RESTORE_PHOTO); - Log.i(TAG, "onRestoreInstanceState , mRestorePhotoFile: " + mRestorePhotoFile); - mCapturePhotoHelper.setPhoto(mRestorePhotoFile); + if (mCapturePhotoHelper != null) { + mRestorePhotoFile = (File) savedInstanceState.getSerializable(EXTRA_RESTORE_PHOTO); + Log.i(TAG, "onRestoreInstanceState , mRestorePhotoFile: " + mRestorePhotoFile); + mCapturePhotoHelper.setPhoto(mRestorePhotoFile); + } } @Override public void onClick(View v) { int viewId = v.getId(); if (viewId == R.id.iv_take_photo) { - mCapturePhotoHelper.capture(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //Android M 处理Runtime Permission + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {//检查是否有写入SD卡的授权 + Log.i(TAG, "granted permission!"); + turnOnCamera(); + } else { + Log.i(TAG, "denied permission!"); + if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + Log.i(TAG, "should show request permission rationale!"); + } + requestPermission(); + } + } else { + turnOnCamera(); + } + } + } + + /** + * 开启相机 + */ + private void turnOnCamera() { + if (mCapturePhotoHelper == null) { + mCapturePhotoHelper = new CapturePhotoHelper(this, FolderManager.getPhotoFolder()); } + mCapturePhotoHelper.capture(); + } + + /** + * 申请写入sd卡的权限 + */ + private void requestPermission() { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RUNTIME_PERMISSION_REQUEST_CODE); } @Override @@ -88,4 +134,58 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == RUNTIME_PERMISSION_REQUEST_CODE) { + for (int index = 0; index < permissions.length; index++) { + String permission = permissions[index]; + if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission)) { + if (grantResults[index] == PackageManager.PERMISSION_GRANTED) { + Log.i(TAG, "onRequestPermissionsResult: permission is granted!"); + turnOnCamera(); + + } else { + showMissingPermissionDialog(); + + } + } + } + } + } + + /** + * 显示打开权限提示的对话框 + */ + private void showMissingPermissionDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.help); + builder.setMessage(R.string.help_content); + + builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Toast.makeText(CapturePhotoActivity.this, R.string.camera_open_error, Toast.LENGTH_SHORT).show(); + finish(); + } + }); + + builder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + turnOnSettings(); + } + }); + + builder.show(); + } + + /** + * 启动系统权限设置界面 + */ + private void turnOnSettings() { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + getPackageName())); + startActivity(intent); + } } diff --git a/src/main/java/com/clock/study/manager/FolderManager.java b/src/main/java/com/clock/study/manager/FolderManager.java index 34f1851..19038e8 100644 --- a/src/main/java/com/clock/study/manager/FolderManager.java +++ b/src/main/java/com/clock/study/manager/FolderManager.java @@ -1,6 +1,13 @@ package com.clock.study.manager; +import android.Manifest; +import android.app.AlertDialog; +import android.content.Context; +import android.content.pm.PackageManager; import android.os.Environment; +import android.support.v4.app.ActivityCompat; + +import com.clock.study.R; import java.io.File; diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 881bb1d..de587c7 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -5,4 +5,8 @@ TakePhoto 显示到相册 未指定存储目录 + 帮助 + 当前权限被禁用,建议到设置界面开启权限! + 取消 + 设置 From 20154c4ea402afa38e396e69d08741d4e13ec6f7 Mon Sep 17 00:00:00 2001 From: clock <1084991652clock@gmail.com> Date: Sun, 12 Jun 2016 12:57:02 +0800 Subject: [PATCH 02/38] update build.gradle --- build.gradle | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index d52e2a3..4f16e25 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,14 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.1.2' + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + apply plugin: 'com.android.application' android { @@ -31,16 +42,4 @@ dependencies { compile(name: 'AndroidUtils', ext: 'aar') //compile project(":AndroidUtils") compile 'com.android.support:appcompat-v7:23.2.1' -} - - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } } \ No newline at end of file From 7063149f3914dfc03961b5bd40a53d3d3b279eb4 Mon Sep 17 00:00:00 2001 From: clock <1084991652clock@gmail.com> Date: Wed, 22 Jun 2016 12:03:10 +0800 Subject: [PATCH 03/38] =?UTF-8?q?=E6=B7=BB=E5=8A=A0RecyclerView=E5=A4=A7?= =?UTF-8?q?=E5=85=A8.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...erView \344\275\277\347\224\250\345\244\247\345\205\250.md" | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 "notes/RecyclerView \344\275\277\347\224\250\345\244\247\345\205\250.md" diff --git "a/notes/RecyclerView \344\275\277\347\224\250\345\244\247\345\205\250.md" "b/notes/RecyclerView \344\275\277\347\224\250\345\244\247\345\205\250.md" new file mode 100644 index 0000000..2712705 --- /dev/null +++ "b/notes/RecyclerView \344\275\277\347\224\250\345\244\247\345\205\250.md" @@ -0,0 +1,3 @@ +# RecyclerView 使用大全 + +整理罗列想要写的知识点 \ No newline at end of file From 307275224a3615631ef027ab56e93d97e660fd18 Mon Sep 17 00:00:00 2001 From: clock <1084991652clock@gmail.com> Date: Fri, 1 Jul 2016 21:30:31 +0800 Subject: [PATCH 04/38] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=A4=E7=AF=87?= =?UTF-8?q?=E6=96=B0=E7=9A=84=E6=96=87=E7=AB=A0md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...47\232\204\345\217\221\345\261\225\346\274\224\350\277\233.md" | 0 ...6\267\261\345\205\245\344\275\277\347\224\250 RecyclerView.md" | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 "notes/Android\345\212\250\347\224\273\347\232\204\345\217\221\345\261\225\346\274\224\350\277\233.md" rename "notes/RecyclerView \344\275\277\347\224\250\345\244\247\345\205\250.md" => "notes/\346\267\261\345\205\245\344\275\277\347\224\250 RecyclerView.md" (100%) diff --git "a/notes/Android\345\212\250\347\224\273\347\232\204\345\217\221\345\261\225\346\274\224\350\277\233.md" "b/notes/Android\345\212\250\347\224\273\347\232\204\345\217\221\345\261\225\346\274\224\350\277\233.md" new file mode 100644 index 0000000..e69de29 diff --git "a/notes/RecyclerView \344\275\277\347\224\250\345\244\247\345\205\250.md" "b/notes/\346\267\261\345\205\245\344\275\277\347\224\250 RecyclerView.md" similarity index 100% rename from "notes/RecyclerView \344\275\277\347\224\250\345\244\247\345\205\250.md" rename to "notes/\346\267\261\345\205\245\344\275\277\347\224\250 RecyclerView.md" From 74dc69bdb80c0319b315d004ac958c337f33cc49 Mon Sep 17 00:00:00 2001 From: clock <1084991652clock@gmail.com> Date: Mon, 4 Jul 2016 18:15:48 +0800 Subject: [PATCH 05/38] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Android=20Animation?= =?UTF-8?q?=20=E4=BD=BF=E7=94=A8=E6=A0=97=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/AndroidManifest.xml | 1 + .../study/activity/AndroidAnimActivity.java | 97 +++++++++++++++++++ .../clock/study/activity/MainActivity.java | 4 + src/main/res/layout/activity_android_anim.xml | 40 ++++++++ src/main/res/layout/activity_main.xml | 9 +- 5 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/clock/study/activity/AndroidAnimActivity.java create mode 100644 src/main/res/layout/activity_android_anim.xml diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 794c2b8..a270a85 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -29,6 +29,7 @@ android:name=".activity.PhotoPreviewActivity" android:label="@string/photo_preview" android:screenOrientation="portrait" /> + \ No newline at end of file diff --git a/src/main/java/com/clock/study/activity/AndroidAnimActivity.java b/src/main/java/com/clock/study/activity/AndroidAnimActivity.java new file mode 100644 index 0000000..32608e1 --- /dev/null +++ b/src/main/java/com/clock/study/activity/AndroidAnimActivity.java @@ -0,0 +1,97 @@ +package com.clock.study.activity; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.RotateAnimation; +import android.view.animation.ScaleAnimation; +import android.view.animation.TranslateAnimation; +import android.widget.Button; + +import com.clock.study.R; + +/** + * Android动画效果实现复习 + */ +public class AndroidAnimActivity extends AppCompatActivity implements View.OnClickListener { + + private Button mBtnTranslate; + private Button mBtnScale; + private Button mBtnRotate; + private Button mBtnAlpha; + private Button mBtnSet; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_android_anim); + + mBtnTranslate = (Button) findViewById(R.id.btn_translate); + mBtnTranslate.setOnClickListener(this); + + mBtnScale = (Button) findViewById(R.id.btn_scale); + mBtnScale.setOnClickListener(this); + + mBtnRotate = (Button) findViewById(R.id.btn_rotate); + mBtnRotate.setOnClickListener(this); + + mBtnAlpha = (Button) findViewById(R.id.btn_alpha); + mBtnAlpha.setOnClickListener(this); + + mBtnSet = (Button) findViewById(R.id.btn_set); + mBtnSet.setOnClickListener(this); + + } + + @Override + public void onClick(View v) { + int viewId = v.getId(); + if (viewId == R.id.btn_translate) {//偏移动画 + //TranslateAnimation translateAnim = new TranslateAnimation(0, 500, 0, 500); + /*TranslateAnimation translateAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 500, Animation.ABSOLUTE, 0, + Animation.ABSOLUTE, 500);*/ + TranslateAnimation translateAnim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 1.0f, Animation.RELATIVE_TO_PARENT, 0, + Animation.RELATIVE_TO_PARENT, 1.0f); + translateAnim.setDuration(2000); + mBtnTranslate.startAnimation(translateAnim); + //translateAnim.setFillAfter(true);//保持动画效果 + + } else if (viewId == R.id.btn_scale) {//缩放动画 + + //ScaleAnimation scaleAnim = new ScaleAnimation(0.5f, 1, 0.5f, 1); + //ScaleAnimation scaleAnim = new ScaleAnimation(0.5f, 1, 0.5f, 1, 300, 300); + ScaleAnimation scaleAnim = new ScaleAnimation(0.5f, 1, 0.5f, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + scaleAnim.setDuration(1000); + mBtnScale.startAnimation(scaleAnim); + + } else if (viewId == R.id.btn_rotate) {//旋转动画 + + //RotateAnimation rotateAnim = new RotateAnimation(0, 360); + //RotateAnimation rotateAnim = new RotateAnimation(0, 360, 100, 100); + RotateAnimation rotateAnim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnim.setDuration(2000); + mBtnRotate.startAnimation(rotateAnim); + + } else if (viewId == R.id.btn_alpha) {//透明度动画 + + AlphaAnimation alphaAnim = new AlphaAnimation(0, 1); + alphaAnim.setDuration(2000); + mBtnAlpha.startAnimation(alphaAnim); + + } else if (viewId == R.id.btn_set) {//动画合集 + + AnimationSet animSet = new AnimationSet(true); + animSet.setDuration(2000); + RotateAnimation rotateAnim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + animSet.addAnimation(rotateAnim); + AlphaAnimation alphaAnim = new AlphaAnimation(0, 1); + animSet.addAnimation(alphaAnim); + mBtnSet.startAnimation(animSet); + + } + + } +} diff --git a/src/main/java/com/clock/study/activity/MainActivity.java b/src/main/java/com/clock/study/activity/MainActivity.java index 0637f11..3c26506 100644 --- a/src/main/java/com/clock/study/activity/MainActivity.java +++ b/src/main/java/com/clock/study/activity/MainActivity.java @@ -15,6 +15,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); findViewById(R.id.btn_camera_take_photo).setOnClickListener(this); + findViewById(R.id.btn_android_anim).setOnClickListener(this); } @Override @@ -23,6 +24,9 @@ public void onClick(View v) { if (viewId == R.id.btn_camera_take_photo) { Intent takePhotoIntent = new Intent(this, CapturePhotoActivity.class); startActivity(takePhotoIntent); + } else if (viewId == R.id.btn_android_anim) { + Intent androidAnimIntent = new Intent(this, AndroidAnimActivity.class); + startActivity(androidAnimIntent); } } } diff --git a/src/main/res/layout/activity_android_anim.xml b/src/main/res/layout/activity_android_anim.xml new file mode 100644 index 0000000..1804f66 --- /dev/null +++ b/src/main/res/layout/activity_android_anim.xml @@ -0,0 +1,40 @@ + + + +