Appearance
使用 MediaRecoder 录音、使用 ExoPlayer 播放本地音频、全屏模式下键盘弹出遮盖内容区。
使用 MediaRecoder 录音
kotlin
// <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
// <uses-permission android:name="android.permission.RECORD_AUDIO"/>
var mRecorder: MediaRecorder? = null
var mFile: File? = null
btnStart.setOnClickListener {
if (Environment.getExternalStorageState() != android.os.Environment.MEDIA_MOUNTED) {
toast("没有内存卡")
return@setOnClickListener
}
mFile = File(Environment.getExternalStorageDirectory().canonicalPath + "/sound.amr")
mRecorder = MediaRecorder()
// 设置录音的声音来源
mRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
// 设置录制的声音的输出格式(必须在设置声音编码格式之前设置)
mRecorder?.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB)
// 设置声音编码的格式
mRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
mRecorder?.setOutputFile(mFile?.absolutePath)
mRecorder?.prepare()
// 开始录音
mRecorder?.start()
}
btnStop.setOnClickListener {
if (mFile != null && (mFile as File).exists()) {
mRecorder?.stop()
mRecorder?.release()
mRecorder = null
}
}
使用 ExoPlayer 播放本地音频
kotlin
private fun initPlayer() {
val bandwidthMeter = DefaultBandwidthMeter()
val factory = AdaptiveTrackSelection.Factory(bandwidthMeter)
val trackSelector = DefaultTrackSelector(factory)
val loadControl = DefaultLoadControl()
mPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl)
mPlayer?.playWhenReady = true
mPlayer?.addListener(object : ExoPlayer.EventListener {
override fun onTracksChanged(trackGroups: TrackGroupArray?,
trackSelections: TrackSelectionArray?) {
warn { "onTracksChanged" }
}
override fun onPlayerError(error: ExoPlaybackException?) {
error?.printStackTrace()
}
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
if (playbackState == ExoPlayer.STATE_ENDED) {
}
}
override fun onLoadingChanged(isLoading: Boolean) {
warn { "isLoading: $isLoading" }
}
override fun onPositionDiscontinuity() {
warn { "onPositionDiscontinuity" }
}
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?) {
warn { "timeline: ${timeline?.isEmpty}" }
}
})
}
private fun getMediaSource(filePath: String): ExtractorMediaSource {
val bandwidthMeter2 = DefaultBandwidthMeter()
val dataSourceFactory = DefaultDataSourceFactory(this,
Util.getUserAgent(this, "com.keng42.lab"), bandwidthMeter2)
val extractorsFactory = DefaultExtractorsFactory()
val mediaSource = ExtractorMediaSource(
Uri.fromFile(File(filePath)),
dataSourceFactory, extractorsFactory, null, null)
return mediaSource
}
private fun playAudio(filePath: String) {
mPlayer?.stop()
val mediaSource = getMediaSource(filePath)
mPlayer?.prepare(mediaSource)
}
// 在不需要的时候调用 mPlayer?.release() 释放资源
全屏模式下键盘弹出遮盖内容区
kotlin
/**
* For more information, see https://code.google.com/p/android/issues/detail?id=5497
* To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
*/
public class AndroidBug5497Workaround {
public static void assistActivity(Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent; // activity_xxx.xml 布局 rootView
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams; // 用于设置 rootView 宽高
private int navBarHeight;
private AndroidBug5497Workaround(Activity activity) {
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
navBarHeight = getNavBarHeight(activity);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
}
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard / 4)) {
// keyboard probably just became visible
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
} else {
// keyboard probably just became hidden
frameLayoutParams.height = usableHeightSansKeyboard - navBarHeight;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return r.bottom;
}
private int getNavBarHeight(Activity activity) {
Resources resources = activity.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height",
"dimen", "android");
if (resourceId > 0) {
return resources.getDimensionPixelSize(resourceId);
}
return 0;
}
}