20 | * Created by wangchenlong on 16/2/11. 21 | */ 22 | public class PermissionsActivity extends AppCompatActivity { 23 | public static final int PERMISSIONS_GRANTED = 0; 24 | public static final int PERMISSIONS_DENIED = 1; 25 | 26 | private static final int PERMISSION_REQUEST_CODE = 0; 27 | private static final String EXTRA_PERMISSIONS = "me.chunyu.clwang.permissions.extra_permissions"; 28 | private static final String PACKAGE_URL_SCHEME = "package:"; 29 | 30 | private PermissionsChecker mChecker; // 检查权限 31 | private boolean mRequiresCheck; // 是否检查 32 | 33 | // 启动当前的Activity 34 | public static void startActivityForResult(Activity activity, int requestCode, String... permissions) { 35 | Intent intent = new Intent(activity, PermissionsActivity.class); 36 | intent.putExtra(EXTRA_PERMISSIONS, permissions); 37 | ActivityCompat.startActivityForResult(activity, intent, requestCode, null); 38 | } 39 | 40 | @Override protected void onCreate(@Nullable Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | 43 | if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) { 44 | throw new RuntimeException("当前Activity需要使用静态方法startActivityForResult启动"); 45 | } 46 | 47 | setContentView(R.layout.activity_permissions); 48 | 49 | mChecker = new PermissionsChecker(this); 50 | mRequiresCheck = true; 51 | } 52 | 53 | @Override protected void onResume() { 54 | super.onResume(); 55 | 56 | if (mRequiresCheck) { 57 | String[] permissions = getIntent().getStringArrayExtra(EXTRA_PERMISSIONS); 58 | 59 | if (mChecker.lakesPermissions(permissions)) { 60 | requestPermissions(permissions); 61 | } else { 62 | allPermissionsGranted(); 63 | } 64 | } else { 65 | mRequiresCheck = true; 66 | } 67 | } 68 | 69 | private void requestPermissions(String... permissions) { 70 | ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE); 71 | } 72 | 73 | private void allPermissionsGranted() { 74 | setResult(PERMISSIONS_GRANTED); 75 | finish(); 76 | } 77 | 78 | // 权限管理的返回 79 | @Override 80 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 81 | if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) { 82 | mRequiresCheck = true; 83 | allPermissionsGranted(); 84 | } else { 85 | mRequiresCheck = false; 86 | showMissingPermissionDialog(); 87 | } 88 | 89 | } 90 | 91 | // 判断是否拥有所有权限 92 | private boolean hasAllPermissionsGranted(@NonNull int[] grantResults) { 93 | for (int grantResult : grantResults) { 94 | if (grantResult == PackageManager.PERMISSION_DENIED) { 95 | return false; 96 | } 97 | } 98 | return true; 99 | } 100 | 101 | private void showMissingPermissionDialog() { 102 | AlertDialog.Builder builder = new AlertDialog.Builder(PermissionsActivity.this); 103 | builder.setTitle(R.string.help).setMessage(R.string.string_help_text); 104 | builder.setNegativeButton(R.string.quit, ((dialog, which) -> { 105 | setResult(PERMISSIONS_DENIED); 106 | finish(); 107 | })); 108 | builder.setPositiveButton(R.string.settings, (dialog, which) -> { 109 | startAppSettings(); 110 | }); 111 | builder.show(); 112 | } 113 | 114 | private void startAppSettings() { 115 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 116 | intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName())); 117 | startActivity(intent); 118 | } 119 | } 120 | 121 | 122 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_visualizer_demo/permissions/PermissionsChecker.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_visualizer_demo.permissions; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageManager; 5 | import android.support.v4.content.ContextCompat; 6 | 7 | /** 8 | * 权限检测 9 | *
10 | * Created by wangchenlong on 16/2/11. 11 | */ 12 | public class PermissionsChecker { 13 | private final Context mContext; 14 | 15 | public PermissionsChecker(Context context) { 16 | mContext = context.getApplicationContext(); 17 | } 18 | 19 | // 判断是否缺少权限 20 | public boolean lakesPermissions(String... permissions) { 21 | for (String permission : permissions) { 22 | if (lakesPermission(permission)) 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | private boolean lakesPermission(String permission) { 29 | return ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_DENIED; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_visualizer_demo/visualizers/RendererFactory.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_visualizer_demo.visualizers; 2 | 3 | import android.support.annotation.ColorInt; 4 | 5 | /** 6 | * 工厂模式 7 | *
8 | * Created by wangchenlong on 16/2/12. 9 | */ 10 | public class RendererFactory { 11 | public WaveformRenderer createSimpleWaveformRender(@ColorInt int foreground, @ColorInt int background) { 12 | return SimpleWaveformRenderer.newInstance(background, foreground); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_visualizer_demo/visualizers/SimpleWaveformRenderer.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_visualizer_demo.visualizers; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.graphics.Path; 6 | import android.support.annotation.ColorInt; 7 | 8 | /** 9 | * 波纹渲染逻辑 10 | *
11 | * Created by wangchenlong on 16/2/12. 12 | */ 13 | public class SimpleWaveformRenderer implements WaveformRenderer { 14 | 15 | private static final int Y_FACTOR = 0xFF; // 2的8次方 = 256 16 | private static final float HALF_FACTOR = 0.5f; 17 | 18 | @ColorInt private final int mBackgroundColor; 19 | private final Paint mForegroundPaint; 20 | private final Path mWaveformPath; 21 | 22 | private SimpleWaveformRenderer(@ColorInt int backgroundColor, Paint foregroundPaint, Path waveformPath) { 23 | mBackgroundColor = backgroundColor; 24 | mForegroundPaint = foregroundPaint; 25 | mWaveformPath = waveformPath; 26 | } 27 | 28 | public static SimpleWaveformRenderer newInstance(@ColorInt int backgroundColor, @ColorInt int foregroundColour) { 29 | Paint paint = new Paint(); 30 | paint.setColor(foregroundColour); 31 | paint.setAntiAlias(true); // 抗锯齿 32 | paint.setStrokeWidth(8.0f); // 设置宽度 33 | paint.setStyle(Paint.Style.STROKE); // 填充 34 | 35 | Path waveformPath = new Path(); 36 | 37 | return new SimpleWaveformRenderer(backgroundColor, paint, waveformPath); 38 | } 39 | 40 | @Override public void render(Canvas canvas, byte[] waveform) { 41 | canvas.drawColor(mBackgroundColor); 42 | float width = canvas.getWidth(); 43 | float height = canvas.getHeight(); 44 | 45 | mWaveformPath.reset(); 46 | 47 | // 没有数据 48 | if (waveform != null) { 49 | // 绘制波形 50 | renderWaveform(waveform, width, height); 51 | } else { 52 | // 绘制直线 53 | renderBlank(width, height); 54 | } 55 | 56 | canvas.drawPath(mWaveformPath, mForegroundPaint); 57 | } 58 | 59 | private void renderWaveform(byte[] waveform, float width, float height) { 60 | float xIncrement = width / (float) (waveform.length); // 水平块数 61 | float yIncrement = height / Y_FACTOR; // 竖直块数 62 | int halfHeight = (int) (height * HALF_FACTOR); // 居中位置 63 | mWaveformPath.moveTo(0, halfHeight); 64 | for (int i = 1; i < waveform.length; ++i) { 65 | float yPosition = waveform[i] > 0 ? 66 | height - (yIncrement * waveform[i]) : -(yIncrement * waveform[i]); 67 | mWaveformPath.lineTo(xIncrement * i, yPosition); 68 | } 69 | mWaveformPath.lineTo(width, halfHeight); // 最后的点, 水平居中 70 | } 71 | 72 | // 居中画一条直线 73 | private void renderBlank(float width, float height) { 74 | int y = (int) (height * HALF_FACTOR); 75 | mWaveformPath.moveTo(0, y); 76 | mWaveformPath.lineTo(width, y); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_visualizer_demo/visualizers/WaveformRenderer.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_visualizer_demo.visualizers; 2 | 3 | import android.graphics.Canvas; 4 | 5 | /** 6 | * 音频波纹渲染接口 7 | *
8 | * Created by wangchenlong on 16/2/11. 9 | */ 10 | public interface WaveformRenderer { 11 | void render(Canvas canvas, byte[] waveform); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_visualizer_demo/visualizers/WaveformView.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_visualizer_demo.visualizers; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | 9 | import java.util.Arrays; 10 | 11 | /** 12 | * 音频波纹视图 13 | *
14 | * Created by wangchenlong on 16/2/11.
15 | */
16 | public class WaveformView extends View {
17 |
18 | private WaveformRenderer mRenderer; // 绘制类
19 | private byte[] mWaveform; // 波纹形状
20 |
21 | public WaveformView(Context context) {
22 | super(context);
23 | }
24 |
25 | public WaveformView(Context context, AttributeSet attrs) {
26 | super(context, attrs);
27 | }
28 |
29 | public WaveformView(Context context, AttributeSet attrs, int defStyleAttr) {
30 | super(context, attrs, defStyleAttr);
31 | }
32 |
33 | @TargetApi(21)
34 | public WaveformView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
35 | super(context, attrs, defStyleAttr, defStyleRes);
36 | }
37 |
38 | public void setRenderer(WaveformRenderer renderer) {
39 | mRenderer = renderer;
40 | }
41 |
42 | public void setWaveform(byte[] waveform) {
43 | mWaveform = Arrays.copyOf(waveform, waveform.length); // 数组复制
44 | invalidate(); // 设置波纹之后, 需要重绘
45 | }
46 |
47 | @Override protected void onDraw(Canvas canvas) {
48 | super.onDraw(canvas);
49 | if (mRenderer != null) {
50 | mRenderer.render(canvas, mWaveform);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mic_off.xml:
--------------------------------------------------------------------------------
1 |