本章没有重点,都是细腻的开发干货,如有需要自行取用(本人把有道云笔记中的东西分享到这)。
android:largeHeap="true"
或者同时开启硬件加速:
android:hardwareAccelerated="true"
可以在RecyclerView设置:
setHasFixedSize(true);
setNestedScrollingEnabled(true);
或者继承RV自定义控件,主动关闭掉外层滑动控件的事件处理,直接交给里面的RV:
RecyclerView默认抢焦点,并设置嵌套滑动开启,即它在被嵌套滑动使用的时候,默认放弃自己的滚动。
这也是导致滑动卡顿、不流畅的原因。
(具体方法的意义,自行去了解,本篇是干货,不做多讲解。)
通话音量:
int max = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL);//获取最大值
int current = mAudioManager.getStreamVolume(STREAM_VOICE_CALL);//获取当前值
媒体音量:
int max = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);//获取最大值
int current = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);//获取当前值
设置通话音量:
AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.setMode(AudioManager.STREAM_MUSIC);
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, volumn, AudioManager.FLAG_PLAY_SOUND);
设置媒体音量:
AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) realVolume, AudioManager.FLAG_PLAY_SOUND);
在这说明两点:
这里直接贴真实可用代码:
//免提
private void speakerPhone(Context context){
AudioManager mAudioManager=(AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.setSpeakerphoneOn(true);
}
//手柄
private void speakHandler(Context context){
AudioManager mAudioManager=(AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.setSpeakerphoneOn(false);
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
}
//第二套切换手柄和免提的方法(兼容方法)
private void changeToincall(boolean on) {
AudioManager mAudioManager=(AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
if (on) {//外放模式
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.setSpeakerphoneOn(true);
tv_satu.setText("外放模式");
} else {//听筒模式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
} else {
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
}
mAudioManager.setSpeakerphoneOn(false);
tv_satu.setText("听筒模式");
}
}
//curr_time 格式:MMddHHmmyyyy.ss 例:020110302018.35
public static void setSystemTime(Context context, String curr_time) {
try {
AlarmManager mAlarmManager = (AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
mAlarmManager.setTimeZone("Asia/Shanghai"); // Asia/Shanghai//GMT+08:00
LogUtils.i("系统设置 开始同步服务器时间");
execSuCmd22("date " + curr_time
+ "\n busybox hwclock -w\n");
} catch (Exception e) {
LogUtils.i("系统设置 同步服务器时间失败");
e.printStackTrace();
}
}
/**
* 执行Android命令
*
* @param cmd 命令
*/
private static void execSuCmd22(String cmd) {
Process process = null;
DataOutputStream os = null;
DataInputStream is = null;
try {
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(cmd + "\n");
os.writeBytes("exit\n");
os.flush();
int aa = process.waitFor();
is = new DataInputStream(process.getInputStream());
byte[] buffer = new byte[is.available()];
is.read(buffer);
String out = new String(buffer);
} catch (Exception e) {
Log.i("88888888", "88888888 同步服务器时间失败");
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
if (is != null) {
is.close();
}
if (process != null) {
process.destroy();
}
} catch (Exception e) {
}
}
LogUtils.i("同步服务器时间成功");
}
如果报权限错误,那可能需要root。目前用雷电模拟器测试过正常,我们自研设备正常。
protected void adbCommond(String command) {
try {
Process process = Runtime.getRuntime().exec(command);
process.waitFor();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
process.waitFor();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
调用方式:adbCommond(“reboot”);
private void exec() {
try {
LogUtils.e("开始执行ADB命令");
PowerManager pManager = (PowerManager) getSystemService(Context.POWER_SERVICE); //重新启动到fastboot模式
pManager.reboot("");
//开始执行ADB命令
// Process process = Runtime.getRuntime().exec(command);
// process.waitFor();
// Process process = Runtime.getRuntime().exec(command);
// BufferedReader reader = new BufferedReader(
// new InputStreamReader(process.getInputStream()));
// int read;
// char[] buffer = new char[4096];
// StringBuffer output = new StringBuffer();
// while ((read = reader.read(buffer)) > 0) {
// output.append(buffer, 0, read);
// }
// reader.close();
// process.waitFor();
// return output.toString();
// } catch (IOException e) {
// throw new RuntimeException(e);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
} catch (Exception e) {
e.printStackTrace();
}
}
在这里介绍一下这个开源播放器,总体感觉很好。
Github: 传送门
它支持多种协议的视频流播放,本篇就以直播流RTSP为例:
public synchronized void rtspPlay(String url){
try{
/**此中内容:优化加载速度,降低延迟*/
VideoOptionModel videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
List list = new ArrayList<>();
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_flags", "prefer_tcp");
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "allowed_media_types", "video"); //根据媒体类型来配置
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 20000);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "buffer_size", 1316);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "infbuf", 1); // 无限读
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 10240);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
list.add(videoOptionModel);
// 关闭播放器缓冲,这个必须关闭,否则会出现播放一段时间后,一直卡主,控制台打印 FFP_MSG_BUFFERING_START
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);
list.add(videoOptionModel);
GSYVideoManager.instance().setOptionModelList(list);
xinChengPlayer.setUp(url, true, "");
xinChengPlayer.setGSYVideoProgressListener(new GSYVideoProgressListener() {
@Override
public void onProgress(int progress, int secProgress, int currentPosition, int duration) {
Log.i("=======","=======progress:"+progress+"====secProgress:"+secProgress+"====currentPosition:"+currentPosition+"====duration:"+duration);
}
});
GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL);
xinChengPlayer.startPlayLogic();
show();
}catch (Exception e){
e.printStackTrace();
}
}
了解更多点传送门哈。
目前采用开源实现(比较好的解决方案):
上Git:
ShapeView
好了,本篇到此结束,都是干活,日后继续补充。有需要自行提取。