Android 之路75---录音机

导读

1.录音播放及动态权限申请
2.语音聊天室案例

这里写图片描述

这里写图片描述

录音播放及动态权限申请

这里写图片描述
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.recordvoicedemo">

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.BLUETOOTH" />


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" tools:context="com.example.recordvoicedemo.MainActivity">

    <Button
        android:id="@+id/record_btn"
        android:layout_width="0dp" android:layout_height="wrap_content"
        android:text="准备说话" app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHorizontal_bias="0.501"
        app:layout_constraintVertical_bias="1.0" />

</android.support.constraint.ConstraintLayout>

MainActivity.java

package com.example.recordvoicedemo;

import android.Manifest;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;

//按下按钮,开始录制(文本会变为”请大声说话“)
//松开按钮,停止录制(文本复原),播放刚刚录制的声音
public class MainActivity extends AppCompatActivity {

    private Button recordBtn;
    private MediaRecorder recorder;    //录音
    private MediaPlayer player;      //播放声音
    private File voiceFile;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initPermission();
        recordBtn = (Button) findViewById(R.id.record_btn);
        recordBtn.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                try {
                    //录音
                    recorder = new MediaRecorder();
                    //设置声音来源
                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    //设置声音格式,MPEG_4:音频、视频的标准格式
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                    //设置声音编码
                    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
                    //准备文件用于承载录制的声音
                    voiceFile = File.createTempFile("myvoice", "mp3");
                    //设置声音的输出录音为刚刚准备好的文件所在的位置
                    recorder.setOutputFile(voiceFile.getAbsolutePath());

                    //准备
                    recorder.prepare();
                    //开始录制
                    recorder.start();

                    recordBtn.setText("请大声说话...");
                }catch (Exception e){
                    e.printStackTrace();
                }
                return false;
            }
        });

        recordBtn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
                    //手指按下
                    if(granted != PackageManager.PERMISSION_GRANTED){
                        Toast.makeText(MainActivity.this,"您不具备录制音频的权限",Toast.LENGTH_SHORT).show();
                        return true;
                    }
                }
                if(granted == PackageManager.PERMISSION_GRANTED &&motionEvent.getAction() == MotionEvent.ACTION_UP){
                    //手指松开,停止录音并播放
                    recorder.stop();        //停止
                    recorder.release();     //释放资源

                    recordBtn.setText("准备录音");

                    try {
                        //初始化
                        player = new MediaPlayer();
                        //设置播放源
                        player.setDataSource(voiceFile.getAbsolutePath());
                        //准备
                        player.prepare();
                        //开始播放
                        player.start();

                        player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaPlayer mediaPlayer) {
                                //停止播放,释放资源,删除录音文件
                                player.stop();
                                player.release();
                                voiceFile.delete();
                            }
                        });
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                return false;
            }
        });
    }

    private void initPermission() {
        //检查程序是否拥有这个权限
//        ContextCompat.checkSelfPermission()
        //请求权限
//        ActivityCompat.requestPermissions();
        //是否要像用户解释请求权限的行为
//        ActivityCompat.shouldShowRequestPermissionRationale()

        //1.获取程序是否具备该项权限
        //如果是6.0一下的手机,该方法的返回值会始终为PERMISSION_GRANTED
        //因此你并不需要动态申请权限,直接做你想做的
        //如果是6.0以上的手机,情况就分为两种
        //如果是noramal权限,该方法的返回值会始终为PERMISSION_GRANTED
        //如果是dangerous权限,动态请求
        int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
        Log.e("TAG","是否具备这项权限:" + permission);
//        PackageManager.PERMISSION_GRANTED       //权限被授予
//        PackageManager.PERMISSION_DENIED    //权限被拒绝
        //2.判断,如果不具备权限,则申请权限
        if(permission != PackageManager.PERMISSION_GRANTED ) {
            //第一次运行时返回值为false
            boolean should = ActivityCompat.
                    shouldShowRequestPermissionRationale(this,Manifest.permission.RECORD_AUDIO);
            Log.e("TAG","是否需要向用户解释:" + should);
            if(should){
                explainDialog();
                return;
            }
            //参数1:activity对象
            //参数2:需要被授权的权限
            //参数3:请求吗
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECORD_AUDIO},1);
        }
    }

    private void explainDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this)
                .setMessage("录音操作必须要录制音频的权限,是否授权?")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //请求权限
                        ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.RECORD_AUDIO},1);
                    }
                })
                .setNegativeButton("取消",null);
                builder.show();
    }

    private int granted;    //用于保存权限是否被授予的凭证
    /**
     * 请求权限后的回调方法
     * @param requestCode 是指在requestPermissions()传递的请求码
     * @param permissions  是指在requestPermissions()传递的需要请求的权限
     * @param grantResults  是指申请权限后返回的结果
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode == 1) {
            granted = grantResults[0];
        }
    }
}

语音聊天室案例

这里写图片描述

AndroidManifest.xml与上边一样

to_msg.xml

<?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:gravity="right|center_vertical"
    android:orientation="horizontal" >

    <!-- 发送 -->

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="right" >

        <TextView
            android:id="@+id/msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@mipmap/chat_to_bg_normal"
            android:text="这是我发出去的"
            android:layout_marginLeft="18dp" />
    </LinearLayout>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/smiley_6" />

</LinearLayout>

from_msg.xml

<?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="horizontal"
    android:gravity="center_vertical">

    <!-- 接受 -->

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/smiley_7" />

    <TextView
        android:id="@+id/msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="18dp"
        android:background="@mipmap/chat_from_bg_normal"
        android:text="这是对方发给我的" />

</LinearLayout>

activity_chatting.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.recordvoicedemo.ChattingActivity"
    android:background="@mipmap/bg">

    <ListView
        android:id="@+id/msg_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@null"
        android:layout_weight="1"
        android:dividerHeight="4dp"></ListView>

    <Button
        android:id="@+id/vice_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按住说话"/>
</LinearLayout>

ChattingActivity.java

package com.example.recordvoicedemo;

import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ChattingActivity extends AppCompatActivity {

    private Button voiceBtn;
    private ListView msgList;
    private ChattingAdapter adapter;
    private List<Msg> datas = new ArrayList<>();
    private MediaRecorder recorder;
    private List<File> voices = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chatting);

   //     initData();
        initView();
    }

    private void initView() {
        voiceBtn = (Button) findViewById(R.id.vice_btn);
        msgList = (ListView) findViewById(R.id.msg_list);
        adapter = new ChattingAdapter(datas,this);
        msgList.setAdapter(adapter);

        //长按按钮,开始录音,松开按钮,录音结束
        //发送语音的效果
        //未来在点击了聊天气泡后才播放对应的语音
        voiceBtn.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                voiceBtn.setText("请开始说话...");
                //录音
                //一系列特性的设置
                try {
                    recorder = new MediaRecorder();
                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
                    //指定语音文件
                    File tempFile = File.createTempFile("temp","mp3");
                    recorder.setOutputFile(tempFile.getAbsolutePath());

                    //保存语音文件
                    voices.add(tempFile);

                    //开始录音
                    recorder.prepare();
                    recorder.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return false;
            }
        });
        voiceBtn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if(motionEvent.getAction() == MotionEvent.ACTION_UP) {
                    voiceBtn.setText("按住说话");
                    //停止录音
                    recorder.stop();
                    recorder.release();
                    //更新聊天界面
                    datas.add(new Msg("           ",voices.get(voices.size()-1),1));
                    datas.add(new Msg("哈哈哈哈IMOOC",null,-1));        //伪造一条跟随着的收到的信息
                    adapter.notifyDataSetChanged();
                    msgList.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
                }
                return false;
            }
        });

        msgList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Msg m = datas.get(i);
                try {
                    if (m.getFlag() == 1) {
                        final MediaPlayer player = new MediaPlayer();
                        player.setDataSource(m.getF().getAbsolutePath());
                        player.prepare();
                        player.start();

                        player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaPlayer mediaPlayer) {
                                player.stop();
                                player.release();
                            }
                        });
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
    }

    private void initData() {
        Msg m1 = new Msg("您好",null,1);
        Msg m2 = new Msg("您也好",null,-1);
        Msg m3 = new Msg("在干嘛",null,1);
        Msg m4 = new Msg("在看慕课网的视频",null,-1);
        Msg m5 = new Msg("好看吗",null,1);
        Msg m6 = new Msg("倍好看",null,-1);
        Msg m7 = new Msg("推荐个网址呗",null,1);
        Msg m8 = new Msg("www.imooc.com",null,-1);

        datas.add(m1);
        datas.add(m2);
        datas.add(m3);
        datas.add(m4);
        datas.add(m5);
        datas.add(m6);
        datas.add(m7);
        datas.add(m8);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        for(int i = 0 ; i < voices.size() ; i++){
            voices.get(i).delete();
        }
    }
}

ChattingAdapter.java

package com.example.recordvoicedemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

//适配器:处理聊天记录样式
public class ChattingAdapter extends BaseAdapter {
    private List<Msg> data;
    private Context ctx;

    public ChattingAdapter(List<Msg> data,Context ctx) {
        this.data = data;
        this.ctx = ctx;
    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        Msg g = data.get(i);
//        if(view == null){ }
            if(g.getFlag() == 1) {
                view = LayoutInflater.from(ctx).inflate(R.layout.to_msg,null);
            }else{
                view = LayoutInflater.from(ctx).inflate(R.layout.from_msg,null);
            }

        TextView msg = (TextView) view.findViewById(R.id.msg);
        msg.setText(g.getTxt());
        return view;
    }
}

Msg.java

package com.example.recordvoicedemo;


import java.io.File;

public class Msg {
    //内容、涉及到 语音、发送/接受的标志
    private String txt;
    private File f;
    private int flag;   //1:本人   -1:对方

    public Msg(String txt, File f, int flag) {
        this.txt = txt;
        this.f = f;
        this.flag = flag;
    }

    public String getTxt() {
        return txt;
    }

    public void setTxt(String txt) {
        this.txt = txt;
    }

    public File getF() {
        return f;
    }

    public void setF(File f) {
        this.f = f;
    }

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值