说明:

demo要求是录屏后上传视频到服务器。

demo下载地址:点击打开链接

1、重要代码

1.0、先加上权限申请

 <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.RECORD_AUDIO"/>

1.1、申请视频和存储权限

//请求视频和存储权限private void requestPermission() {if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_REQUEST_CODE);}if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECORD_AUDIO}, AUDIO_REQUEST_CODE);}}
  @Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == STORAGE_REQUEST_CODE || requestCode == AUDIO_REQUEST_CODE) {if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {finish();}}}

1.2、申请录屏和建立录屏服务

Intent intent = new Intent(this, RecordService.class);bindService(intent, connection, BIND_AUTO_CREATE);
 //录屏权限同意后返回@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {mediaProjection = projectionManager.getMediaProjection(resultCode, data);recordService.setMediaProject(mediaProjection);recordService.startRecord();startBtn.setText(R.string.stop_record);//设置文字countTimer();//开始计时openZFB();//打开支付宝luPinStatus = true;//设置录屏状态为true}}
 //建立录屏服务private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName className, IBinder service) {DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);RecordService.RecordBinder binder = (RecordService.RecordBinder) service;recordService = binder.getRecordService();recordService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);startBtn.setEnabled(true);startBtn.setText(recordService.isRunning() ? R.string.stop_record : R.string.start_record);}@Overridepublic void onServiceDisconnected(ComponentName arg0) {}};

2、完整代码

1、RecordApplication.java

package com.baofu.lupin;import android.app.Application;
import android.content.Context;
import android.content.Intent;/*** Created by BF100165 on 2018/6/21.*/public class RecordApplication extends Application {private static RecordApplication application;@Overrideprotected void attachBaseContext(Context base) {super.attachBaseContext(base);application = this;}@Overridepublic void onCreate() {super.onCreate();// 启动 Marvel servicestartService(new Intent(this, RecordService.class));}public static RecordApplication getInstance() {return application;}
}

2、AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.baofu.lupin"><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.RECORD_AUDIO"/><applicationandroid:name=".RecordApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activityandroid:name=".MainActivity"android:label="@string/app_name"android:theme="@style/AppTheme.NoActionBar"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><service android:name=".RecordService"/></application></manifest>

3、MainActivity.java

package com.baofu.lupin;import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;public class MainActivity extends AppCompatActivity {private static final int RECORD_REQUEST_CODE = 101;private static final int STORAGE_REQUEST_CODE = 102;private static final int AUDIO_REQUEST_CODE = 103;private MediaProjectionManager projectionManager;private MediaProjection mediaProjection;private RecordService recordService;private Button startBtn;private TextView tv_timer;private TextView btn_upload;private CountDownTimer timer;private boolean luPinStatus = false;//录屏状态初始为false@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);setContentView(R.layout.activity_main);Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);setSupportActionBar(toolbar);startBtn = (Button) findViewById(R.id.start_record);tv_timer = (TextView) findViewById(R.id.tv_timer);btn_upload = (TextView) findViewById(R.id.btn_upload);//开始录屏startBtn.setEnabled(false);startBtn.setOnClickListener(new View.OnClickListener() {@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overridepublic void onClick(View v) {if (recordService != null && recordService.isRunning()) {recordService.stopRecord();//结束录屏startBtn.setText(R.string.start_record);timer.cancel();//结束计时luPinStatus = false;//录屏状态为false} else {Intent captureIntent = projectionManager.createScreenCaptureIntent();startActivityForResult(captureIntent, RECORD_REQUEST_CODE);}}});//上传视频btn_upload.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if(luPinStatus) {Toast.makeText(MainActivity.this, "请先结束录屏", Toast.LENGTH_SHORT).show();return;}final String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "ScreenRecord" + "/123456.mp4";File file = new File(filePath);final String url = "http://10.0.19.48/creditApi/video";if(!file.exists()) {Toast.makeText(MainActivity.this, "请先录屏芝麻信用", Toast.LENGTH_SHORT).show();return;}new Thread(new Runnable() {@Overridepublic void run() {try {UploadUtils.uploadFile(MainActivity.this, btn_upload, tv_timer, url, filePath);} catch (Exception e) {e.printStackTrace();}}}).start();}});Intent intent = new Intent(this, RecordService.class);bindService(intent, connection, BIND_AUTO_CREATE);requestPermission();}//请求视频和存储权限private void requestPermission() {if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_REQUEST_CODE);}if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECORD_AUDIO}, AUDIO_REQUEST_CODE);}}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(connection);}//录屏权限同意后返回@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {mediaProjection = projectionManager.getMediaProjection(resultCode, data);recordService.setMediaProject(mediaProjection);recordService.startRecord();startBtn.setText(R.string.stop_record);//设置文字countTimer();//开始计时openZFB();//打开支付宝luPinStatus = true;//设置录屏状态为true}}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == STORAGE_REQUEST_CODE || requestCode == AUDIO_REQUEST_CODE) {if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {finish();}}}//建立录屏服务private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName className, IBinder service) {DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);RecordService.RecordBinder binder = (RecordService.RecordBinder) service;recordService = binder.getRecordService();recordService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);startBtn.setEnabled(true);startBtn.setText(recordService.isRunning() ? R.string.stop_record : R.string.start_record);}@Overridepublic void onServiceDisconnected(ComponentName arg0) {}};//界面倒计时private void countTimer() {/** 倒计时60秒,一次1秒 */timer = new CountDownTimer(60 * 1000, 1000) {@Overridepublic void onTick(long millisUntilFinished) {// TODO Auto-generated method stubtv_timer.setText("还剩" + millisUntilFinished / 1000 + "秒");}@Overridepublic void onFinish() {tv_timer.setText("倒计时完毕了");}}.start();}//打开支付宝private void openZFB() {try {PackageManager packageManager= this.getApplicationContext().getPackageManager();Intent intent = packageManager.getLaunchIntentForPackage("com.eg.android.AlipayGphone");startActivity(intent);} catch (Exception e) {String url = "https://ds.alipay.com/?from=mobileweb";Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse(url));startActivity(intent);}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.menu_main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();//noinspection SimplifiableIfStatementif (id == R.id.action_settings) {return true;}return super.onOptionsItemSelected(item);}
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"app:layout_behavior="@string/appbar_scrolling_view_behavior"tools:context="com.baofu.lupin.MainActivity"tools:showIn="@layout/activity_main"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:orientation="vertical"><TextViewandroid:id="@+id/tv_timer"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="倒计时 - 打开支付宝" /></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:orientation="vertical"><Buttonandroid:id="@+id/btn_upload"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="上传录屏"/><Buttonandroid:id="@+id/start_record"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginBottom="10dp"android:text="@string/start_record"/></LinearLayout>
</RelativeLayout>

strings.xml

<resources><string name="app_name">录屏</string><string name="action_settings">Settings</string><string name="start_record">开始录屏</string><string name="stop_record">停止录屏</string>
</resources>

3、RecordService.java

package com.baofu.lupin;import android.annotation.TargetApi;
import android.app.Service;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.os.HandlerThread;
import android.os.IBinder;
import android.widget.Toast;import java.io.File;
import java.io.IOException;/*** 录屏服务* Created by BF100165 on 2018/6/21.*/public class RecordService extends Service {private MediaProjection mediaProjection;private MediaRecorder mediaRecorder;private VirtualDisplay virtualDisplay;private boolean running;private int width = 720;private int height = 1080;private int dpi;@Overridepublic IBinder onBind(Intent intent) {return new RecordBinder();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return START_STICKY;}@Overridepublic void onCreate() {super.onCreate();HandlerThread serviceThread = new HandlerThread("service_thread",android.os.Process.THREAD_PRIORITY_BACKGROUND);serviceThread.start();running = false;mediaRecorder = new MediaRecorder();}@Overridepublic void onDestroy() {super.onDestroy();}public void setMediaProject(MediaProjection project) {mediaProjection = project;}public boolean isRunning() {return running;}public void setConfig(int width, int height, int dpi) {this.width = width;this.height = height;this.dpi = dpi;}public boolean startRecord() {if (mediaProjection == null || running) {return false;}initRecorder();createVirtualDisplay();mediaRecorder.start();running = true;return true;}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public boolean stopRecord() {if (!running) {return false;}running = false;mediaRecorder.stop();mediaRecorder.reset();virtualDisplay.release();mediaProjection.stop();return true;}@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void createVirtualDisplay() {virtualDisplay = mediaProjection.createVirtualDisplay("MainScreen", width, height, dpi,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);}private void initRecorder() {mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);mediaRecorder.setOutputFile(getsaveDirectory() + "123456" + ".mp4");mediaRecorder.setVideoSize(width, height);mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);mediaRecorder.setVideoFrameRate(30);try {mediaRecorder.prepare();} catch (IOException e) {e.printStackTrace();}}public String getsaveDirectory() {if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {String rootDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "ScreenRecord" + "/";File file = new File(rootDir);if (!file.exists()) {if (!file.mkdirs()) {return null;}}Toast.makeText(getApplicationContext(), rootDir, Toast.LENGTH_SHORT).show();return rootDir;} else {return null;}}public class RecordBinder extends Binder {public RecordService getRecordService() {return RecordService.this;}}
}

4、UploadUtils.java

package com.baofu.lupin;import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.widget.TextView;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;/*** 上传视频*/
public class UploadUtils {public static String uploadFile(Activity activity, final TextView btn, final TextView content, String serverUrl, final String localFilePath) throws Exception {activity.runOnUiThread(new Runnable() {@Overridepublic void run() {btn.setText("上传中...");Log.e("上传视频", "地址:" + localFilePath);}});File file = new File(localFilePath);Map<String, Object> postDataParams = new HashMap<>();postDataParams.put("api_key", "asdfasf");postDataParams.put("video_type", "android");postDataParams.put("fileName", file.getName());URL url = new URL(serverUrl + "?" + getPostDataString(postDataParams));HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setDoOutput(true);conn.setUseCaches(false);conn.setRequestMethod("POST");conn.setRequestProperty("Content-Type", "text/html");conn.setRequestProperty("Cache-Control", "no-cache");conn.setRequestProperty("Charsert", "UTF-8");conn.connect();conn.setConnectTimeout(20000);DataOutputStream out = new DataOutputStream(conn.getOutputStream());DataInputStream in = new DataInputStream(new FileInputStream(file));int bytes = 0;byte[] bufferOut = new byte[2048];while ((bytes = in.read(bufferOut)) != -1) {out.write(bufferOut, 0, bytes);}in.close();out.flush();out.close();InputStream inputStream = conn.getInputStream();final String respStr = getRespString(inputStream);activity.runOnUiThread(new Runnable() {@Overridepublic void run() {btn.setText("上传完成-点击继续上传");content.setText(respStr);Log.e("上传视频", "返回:" + respStr);}});conn.disconnect();return respStr;}public static String getPostDataString(Map<String, Object> params) throws Exception {StringBuilder result = new StringBuilder();boolean first = true;for (Map.Entry<String, Object> entry : params.entrySet()) {String key = entry.getKey();Object value = entry.getValue();if (first)first = false;elseresult.append("&");result.append(URLEncoder.encode(key, "UTF-8"));result.append("=");result.append(URLEncoder.encode(value.toString(), "UTF-8"));}return result.toString();}public static String getRespString(InputStream is) throws Exception {StringBuffer strBuf = new StringBuffer();byte[] bytes = new byte[4096];int r = 0;while ((r = is.read(bytes)) > 0) {strBuf.append(new String(bytes, 0, r, "UTF-8"));}return strBuf.toString();}}

Android - 录屏+上传视频相关推荐

  1. android 录屏工具,安卓手机上最好的录屏软件在这里

    今天的这款软件真的是推荐,谁说只有电脑可以录屏,现在手机屏幕也可以录屏啦!最好用的录屏大师软件小编是找了很久今天才和大家分享的,纯属自己个人喜欢哦!想知道是什么软件的宝宝可以和小编一起往下看啦! 录屏 ...

  2. 抖音上传视频(纯前端实现霸屏软件的功能)进店转发视频功能,详情搜索抖音霸屏软件

    抖音霸屏软件 抖音霸屏介绍 先来介绍一下吧,嫌啰嗦的可以直接跳转>>>思路分析 ↓ 抖音开发文档 思路分析 步骤 抖音霸屏介绍 先来介绍一下吧,嫌啰嗦的可以直接跳转>>& ...

  3. Android 调用优酷SDK上传视频

    最近在研究用优酷的SDK来进行视频上传的功能,由于优酷的SDK只是提供了一个上传的sample code,没有涉及到授权的过程,对于新手来说,可能非常棘手,现在分享一下我的思路: 程序实现前我们先要到 ...

  4. Android调用优酷SDK实现上传视频到优酷

    程序实现前我们先要到优酷开放平台下载SDK(下载地址:http://open.youku.com/down),下载好后我们将压缩包解压,下面以Eclipse为开发工具进行讲解: 首先我们要获得优酷sd ...

  5. Android 调用优酷SDK上传视频获取Token与code步骤

    我们在做优酷上传视频的时候发现没有获取code与token这个过程,这可能会让些编程新手感到棘手,所以为了方便大家简单分享下我的思路: 程序实现前我们先要到优酷开放平台下载SDK(下载地址:http: ...

  6. android 拍 上传视频无法播放,【报Bug】input type=file时无法使用相机拍摄视频

    详细问题描述 需要上传视频,使用input type=file,在浏览器环境可以调起摄像头拍摄视频 ,在安卓app使用webview加载该页面时,没有拍摄视频选项. [内容] 重现步骤 [步骤] ht ...

  7. Android 录屏服务使用(源码)

    Android 录屏服务使用(源码) 从Android 5.0开始,可以对手机进行录屏,使用场景:如错误场景的视频上传,简单屏幕获取等,下面贴出使用用例和对使用的类一个简单的介绍 - MediaPro ...

  8. Android录屏并利用FFmpeg转换成gif(一)录屏

    Android录屏并利用FFmpeg转换成gif(一) 录屏 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲 ...

  9. android 录屏自动运行,app自动化--Android通过adb录屏

    使用背景 adb shell可正常使用 仅适用于Android4.4(API level 19)以上 .mp4格式 支持指定时长与分辨率 使用方法 官话: 白话 白话快速上手版: # 开始录制 adb ...

最新文章

  1. EI:天大王灿+昆士兰郭建华揭示生物气溶胶是猪场耐药基因的重要传播途径
  2. java中,字符串和集合判断是否为空
  3. redis-集群分片
  4. 服务器图片(绝对地址) 客户端显示问题
  5. ------shell学习
  6. 【数论】挖掘机技术哪家强(jzoj 3858)
  7. idea maven项目的移除添加
  8. 开发者如何区分 5G 和 LTE 技术?
  9. import MySQLdb UserWarning
  10. 【PL/SQL】九九乘法口诀表
  11. Nginx+Tomcat负载平衡
  12. PMP不报培训班的通过率高吗?
  13. Cannot access a disposed object. A common cause of this error is disposing a context that was resolv
  14. 组合导航(九):三维简化的INS/GPS组合导航系统
  15. Gini Index vs Information Entropy
  16. windows实用键盘快捷键
  17. Python入门学习笔记(五)——文件、文件系统
  18. DAVIS Driving Dataset 2020 (DDD20) 【转载】
  19. 枚举报错 No enum constant XX 处理方法
  20. zzulioj :2020新生赛:花海

热门文章

  1. dsy 1002 轮状病毒
  2. 模拟电子技术最终章——直流电源:整流+滤波+稳压(知识点归纳总结及例题详细分析)LDO与DCDC详解
  3. iOS界面横屏竖屏随意切换
  4. 如何让Excel表使用一次后即自我销毁?
  5. Idea 插件SDK 配置
  6. 大专生适合做测试工程师吗?
  7. 什么是准双向口,双向口?
  8. vue2与vue3的diff算法区别
  9. 设置SQLSERVER的混合身份验证模式(SA账号)
  10. 攒了个程序员笔记本,做个记录