- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个用于录制屏幕的应用程序,它在 Android 版本 10 上不起作用。据我了解,这是由于 Android 10 中生效的隐私更改所致。我添加了权限 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
在我的 list 文件中,添加了 android:foregroundServiceType="mediaProjection"
标记服务并调用 startForeground()
方法
Notification.Builder builder = new Notification.Builder(getApplicationContext(), "333")
.setContentTitle(getString(R.string.app_name))
.setContentText("Record")
.setAutoCancel(true);
Notification notification = builder.build();
startForeground(123, notification);
在调用 .getMediaProjection()
之前方法,但我的应用程序仍然准确地抛出错误
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.screen_recording, PID: 9572
java.lang.RuntimeException: Unable to start service com.example.screen_recording.service.RecordService@bb31978 with Intent { cmp=com.example.screen_recording/.service.RecordService (has extras) }: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4105)
at android.app.ActivityThread.access$1800(ActivityThread.java:219)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.os.Parcel.createException(Parcel.java:2071)
at android.os.Parcel.readException(Parcel.java:2039)
at android.os.Parcel.readException(Parcel.java:1987)
at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:231)
at android.media.projection.MediaProjection.<init>(MediaProjection.java:58)
at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:104)
at com.example.screen_recording.service.RecordService.onStartRecord(RecordService.java:117)
at com.example.screen_recording.service.RecordService.onStartCommand(RecordService.java:106)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4087)
at android.app.ActivityThread.access$1800(ActivityThread.java:219)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:476)
at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:135)
at android.os.Binder.execTransactInternal(Binder.java:1021)
at android.os.Binder.execTransact(Binder.java:994)
这是服务代码
public class RecordService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
SharedPreferences p;
WindowManager window;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private boolean isRecord = false;
private String videoUri = "";
private MediaProjectionManager mediaProjectionManager;
private MediaProjection mediaProjection;
private VirtualDisplay virtualDisplay;
private MediaRecorder mediaRecorder;
private int mScreenDensity;
private static int DISPLAY_WIDTH;
private static int DISPLAY_HEIGHT;
private int resultCode;
private Intent resultData;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onCreate() {
super.onCreate();
Notification.Builder builder = new Notification.Builder(getApplicationContext(), "333")
.setContentTitle(getString(R.string.app_name))
.setContentText("Record")
.setAutoCancel(true);
Notification notification = builder.build();
startForeground(123, notification);
p = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
window.getDefaultDisplay().getMetrics(metrics);
mScreenDensity = metrics.densityDpi;
DISPLAY_WIDTH = metrics.widthPixels;
DISPLAY_HEIGHT = metrics.heightPixels;
mediaRecorder = new MediaRecorder();
mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction() == null) {
resultCode = intent.getIntExtra("code", 1337);
resultData = intent.getParcelableExtra("data");
}
onStartRecord();
return (START_NOT_STICKY);
}
@Override
public void onDestroy() {
onStopRecord();
super.onDestroy();
}
private void onStartRecord() {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);
int quality = p.getInt("quality", 1080);
boolean micro = p.getBoolean("micro", false);
int fps = p.getInt("FPS", 60);
initRecorder(quality, micro, fps);
virtualDisplay = createVirtualDisplay();
isRecord = true;
p.edit().putBoolean("isRecord", isRecord).apply();
mediaRecorder.start();
}
private void onStopRecord() {
mediaRecorder.stop();
mediaRecorder.reset();
stopRecordScreen();
isRecord = false;
p.edit().putBoolean("isRecord", isRecord).apply();
}
private VirtualDisplay createVirtualDisplay() {
return mediaProjection.createVirtualDisplay("MainFragment", DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mediaRecorder.getSurface(), null, null);
}
private void initRecorder(int QUALITY, boolean isMicro, int fps) {
try {
int bitrateVideo = 0;
switch (QUALITY) {
case 1080:
bitrateVideo = 7000000;
break;
case 720:
bitrateVideo = 4000000;
break;
default:
bitrateVideo = 2000000;
break;
}
if (isMicro) {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
}
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
if (isMicro) {
mediaRecorder.setAudioSamplingRate(44100);
mediaRecorder.setAudioEncodingBitRate(16 * 44100);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
}
videoUri = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
+ new StringBuilder("/FreeRecord_").append(new SimpleDateFormat("dd-MM-yyyy-hh-mm-ss")
.format(new Date())).append(".mp4").toString();
mediaRecorder.setOutputFile(videoUri);
mediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setVideoEncodingBitRate(bitrateVideo);
mediaRecorder.setCaptureRate(fps);
mediaRecorder.setVideoFrameRate(fps);
int rotation = window.getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation + 90);
mediaRecorder.setOrientationHint(orientation);
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
private void stopRecordScreen() {
if (virtualDisplay == null) {
return;
}
virtualDisplay.release();
destroyMediaProject();
}
private void destroyMediaProject() {
if (mediaProjection != null) {
mediaProjection.stop();
mediaProjection = null;
}
}
}
最佳答案
使用通知 channel 启动前台服务
。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// create notification channel
new NotificationManager(this,11111);
// Create notification builder.
Intent notificationIntent = new Intent();
PendingIntent pendingIntent = PendingIntent.getService(context, 1212, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationManager.CHANNEL_ID);
builder.setSmallIcon(R.drawable.notification);
builder.setColor(ContextCompat.getColor(this, R.color.white));
builder.setContentTitle(getString(title));
builder.setContentIntent(pendingIntent);
Notification notification = builder.build();
startForeground(100000, notification);
Log.d(TAG,"Start foreground service");
}
找到以下链接在前台
启动服务供您引用。 Oreo - Starting a service in the foreground
关于java - 媒体投影需要 ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION 类型的前台服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62004735/
我正在尝试用 C 语言编写一个使用 gstreamer 的 GTK+ 应用程序。 GTK+ 需要 gtk_main() 来执行。 gstreamer 需要 g_main_loop_run() 来执行。
我已经使用 apt-get 安装了 opencv。我得到了以下版本的opencv2,它工作正常: rover@rover_pi:/usr/lib/arm-linux-gnueabihf $ pytho
我有一个看起来像这样的 View 层次结构(基于其他答案和 Apple 的使用 UIScrollView 的高级 AutoLayout 指南): ScrollView 所需的2 个步骤是: 为 Scr
我尝试安装 udev。 udev 在 ./configure 期间给我一个错误 --exists: command not found configure: error: pkg-config and
我正在使用 SQLite 3。我有一个表,forums,有 150 行,还有一个表,posts,有大约 440 万行。每个帖子都属于一个论坛。 我想从每个论坛中选择最新帖子的时间戳。如果我使用 SEL
使用 go 和以下包: github.com/julienschmidt/httprouter github.com/shwoodard/jsonapi gopkg.in/mgo.v2/bson
The database仅包含 2 个表: 钱包(100 万行) 事务(1500 万行) CockroachDB 19.2.6 在 3 台 Ubuntu 机器上运行 每个 2vCPU 每个 8GB R
我很难理解为什么在下面的代码中直接调用 std::swap() 会导致编译错误,而使用 std::iter_swap 编译却没有任何错误. 来自 iter_swap() versus swap() -
我有一个非常简单的 SELECT *用 WHERE NOT EXISTS 查询条款。 SELECT * FROM "BMAN_TP3"."TT_SPLDR_55E63A28_59358" SELECT
我试图按部分组织我的 .css 文件,我需要从任何文件访问文件组中的任何类。在 Less 中,我可以毫无问题地创建一个包含所有文件导入的主文件,并且每个文件都导入主文件,但在 Sass 中,我收到一个
Microsoft.AspNet.SignalR.Redis 和 StackExchange.Redis.Extensions.Core 在同一个项目中使用。前者需要StackExchange.Red
这个问题在这里已经有了答案: Updating from Rails 4.0 to 4.1 gives sass-rails railties version conflicts (4 个答案) 关
我们有一些使用 Azure DevOps 发布管道部署到的现场服务器。我们已经使用这些发布管道几个月了,没有出现任何问题。今天,我们在下载该项目的工件时开始出现身份验证错误。 部署组中的节点显示在线,
Tip: instead of creating indexes here, run queries in your code – if you're missing any indexes, you
你能解释一下 Elm 下一个声明中的意思吗? (=>) = (,) 我在 Elm architecture tutorial 的例子中找到了它 最佳答案 这是中缀符号。实际上,这定义了一个函数 (=>
我需要一个 .NET 程序集查看器,它可以显示低级详细信息,例如元数据表内容等。 最佳答案 ildasm 是 IL 反汇编程序,具有低级托管元数据 token 信息。安装 Visual Studio
我有两个列表要在 Excel 中进行比较。这是一个很长的列表,我需要一个 excel 函数或 vba 代码来执行此操作。我已经没有想法了,因此转向你: **Old List** A
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想要改善这个问题吗?更新问题,以便将其作为on-topi
我正在学习 xml 和 xml 处理。我无法很好地理解命名空间的存在。 我了解到命名空间帮助我们在 xml 中分离相同命名的元素。我们不能通过具有相同名称的属性来区分元素吗?为什么命名空间很重要或需要
我搜索了 Azure 文档、各种社区论坛和 google,但没有找到关于需要在公司防火墙上打开哪些端口以允许 Azure 所有组件(blob、sql、compute、bus、publish)的简洁声明
我是一名优秀的程序员,十分优秀!