如何解决Android 10:android:foregroundServiceType =“ mediaProjection”无法与服务一起使用
媒体投射需要ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION类型的前台服务
我正在尝试使用 MediaProjection API 捕获屏幕,但是我的应用不断崩溃。我尝试过并给出此错误:
java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
我的服务代码:
class RecordService : Service() {
private var mServiceHandler: ServiceHandler? = null
private var mMediaProjection: MediaProjection? = null
private var mVirtualdisplay: Virtualdisplay? = null
private var mMediaRecorder: MediaRecorder? = null
private var resultCode = 0
private var data: Intent? = null
private var mScreenStateReceiver: broadcastReceiver? = null
var isInitialized=false
private inner class ServiceHandler(looper: Looper?) : Handler(looper) {
override fun handleMessage(msg: Message?) {
if (resultCode == RESULT_OK) {
startRecording(resultCode,data)
} else {
}
}
}
override fun onCreate() {
// when the main app is being closed
val notificationIntent = Intent(this,RecordService::class.java)
val pendingIntent = PendingIntent.getActivity(this,notificationIntent,0)
val notification: Notification = Notification.Builder(this)
.setContentTitle("DataRecorder")
.setContentText("Your screen is being recorded and saved to your phone.")
.setSmallIcon(R.drawable.ic_dialog_alert)
.setContentIntent(pendingIntent)
.setTicker("Tickertext")
.build()
isInitialized=true
startForeground(ONGOING_NOTIFICATION_ID,notification)
mScreenStateReceiver = MybroadcastReceiver()
val screenStateFilter = IntentFilter()
screenStateFilter.addAction(Intent.ACTION_SCREEN_ON)
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF)
screenStateFilter.addAction(Intent.ACTION_CONfigURATION_CHANGED)
registerReceiver(mScreenStateReceiver,screenStateFilter)
val thread = HandlerThread(
"ServiceStartArguments",THREAD_PRIORITY_BACKGROUND
)
thread.start()
val mServiceLooper = thread.looper
mServiceHandler = ServiceHandler(mServiceLooper)
}
override fun onStartCommand(intent: Intent,flags: Int,startId: Int): Int {
Toast.makeText(this,"Starting recording service",Toast.LENGTH_SHORT).show()
resultCode = intent.getIntExtra(EXTRA_RESULT_CODE,0)
data = intent.getParcelableExtra(EXTRA_DATA)
check(!(resultCode == 0 || data == null)) { "Result code or data missing." }
val msg = mServiceHandler!!.obtainMessage()
msg.arg1 = startId
mServiceHandler!!.sendMessage(msg)
return START_REDELIVER_INTENT
}
private fun startRecording(resultCode: Int,data: Intent?) {
val mProjectionManager =
applicationContext.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as mediaprojectionmanager
mMediaRecorder = MediaRecorder()
val metrics = displayMetrics()
val wm =
applicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
wm.defaultdisplay.getRealMetrics(metrics)
val mScreenDensity = metrics.densityDpi
val displayWidth = metrics.widthPixels
val displayHeight = metrics.heightPixels
mMediaRecorder!!.setVideoSource(MediaRecorder.VideoSource.SURFACE)
mMediaRecorder!!.setoutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mMediaRecorder!!.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mMediaRecorder!!.setVideoEncodingBitRate(8 * 1000 * 1000)
mMediaRecorder!!.setVideoFrameRate(15)
mMediaRecorder!!.setVideoSize(displayWidth,displayHeight)
val videoDir =
Environment.getExternalStoragePublicDirectory(DIRECTORY_MOVIES)
.absolutePath
val timestamp = System.currentTimeMillis()
var orientation = "portrait"
if (displayWidth > displayHeight) {
orientation = "landscape"
}
val filePathAndName =
videoDir + "/time_" + timestamp.toString() + "_mode_" + orientation + ".mp4"
mMediaRecorder!!.setoutputFile(filePathAndName)
try {
mMediaRecorder!!.prepare()
} catch (e: IllegalStateException) {
e.printstacktrace()
} catch (e: IOException) {
e.printstacktrace()
}
if(isInitialized){
mMediaProjection = mProjectionManager.getMediaProjection(resultCode,data!!)
val surface: Surface = mMediaRecorder!!.surface
mVirtualdisplay = mMediaProjection!!.createVirtualdisplay(
"MainActivity",displayWidth,displayHeight,mScreenDensity,VIRTUAL_disPLAY_FLAG_PRESENTATION,surface,null,null
)
mMediaRecorder!!.start()
Log.v(TAG,"Started recording")
}
}
companion object {
private const val TAG = "RECORDERSERVICE"
private const val EXTRA_RESULT_CODE = "resultcode"
private const val EXTRA_DATA = "data"
private const val ONGOING_NOTIFICATION_ID = 23
}
}
我也确实在清单中添加了android:foregroundServiceType="mediaProjection"
,但是它不起作用。我尝试了其他类似的任务,但问题尚未解决。谢谢
解决方法
您是否将此添加到您的应用清单中?
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
,
终于拿到了钥匙: 您必须首先像下面一样在 onStartCommand 中创建 NotificationChannel ,否则您将 得到“FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION 错误”。
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
LogUtil.d(TAG," onStartCommand intent = " + intent);
createNotificationChannel();
//do MediaProjection things that you want
return START_NOT_STICKY;
}
private void createNotificationChannel() {
Notification.Builder builder = new Notification.Builder(this.getApplicationContext()); //获取一个Notification构造器
Intent nfIntent = new Intent(this,MainActivity.class); //点击后跳转的界面,可以设置跳转数据
builder.setContentIntent(PendingIntent.getActivity(this,nfIntent,0)) // 设置PendingIntent
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),R.mipmap.ic_launcher)) // 设置下拉列表中的图标(大图标)
//.setContentTitle("SMI InstantView") // 设置下拉列表里的标题
.setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标
.setContentText("is running......") // 设置上下文内容
.setWhen(System.currentTimeMillis()); // 设置该通知发生的时间
/*以下是对Android 8.0的适配*/
//普通notification适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId("notification_id");
}
//前台服务notification适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("notification_id","notification_name",NotificationManager.IMPORTANCE_LOW);
notificationManager.createNotificationChannel(channel);
}
Notification notification = builder.build(); // 获取构建好的Notification
notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
startForeground(110,notification);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。