模块名称:Adslibrary
广告平台包含:Admob
,Facebook
,Vungle
,Mopub
中介
广告类型:
Admob
的接入的广告类型有:
插屏广告InterstitialAd
,开屏广告(AppOpenAd
),
激励广告RewardedAd
,原生广告UnifiedNativeAd
Facebook
接入的广告类型有:
原生广告NativeAd
,激励广告RewardedVideoAd
Vungle
接入广告类型有:插屏广告
Mopub
接入的广告类型有:原生广告NativeAd
,激励广告MoPubReward
,插屏广告MoPubInterstitial
在APP的build.gradle文件里增加setArchivesBaseName
属性方法代码
productFlavors {
vrecorder {
versionCode rootProject.appCode
versionName rootProject.appVersion
setArchivesBaseName(getOutputBaseName(versionCode, versionName, "vrecorder"))
}
定义getOutputBaseName
方法:
/**
* 设置输出APK别名
*/
String getOutputBaseName(versionCode, versionName, appName) {
log("setOutputName:")
//修改文件名
def fileName = appName + "_V${versionName}_${versionCode}_Svn${getSvnRevision()}_${getReleaseTime()}"
log("ArchivesBaseName = [" + fileName + "]")
return fileName
}
private log(msg) {
logger.log(LogLevel.ERROR, msg)
}
不再使用就的setOutput()的android.productFlavors.all { flavor -> …}遍历方案,因为生成的APK没有实时的更新APK名称,还会导致编译生成APK时容易第一次出错,需要clear项目再编译才行的问题。
增加Google gradle插件:在根级(项目级)Gradle 文件 (
build.gradle
)
buildscript {
repositories {
// Check that you have the following line (if not, add it):
google() // Google's Maven repository
}
dependencies {
// ...
// Add the following line:
classpath 'com.google.gms:google-services:4.3.3' // Google Services plugin
}
}
allprojects {
// ...
repositories {
// Check that you have the following line (if not, add it):
google() // Google's Maven repository
// ...
}
}
VRecorder
涉及到的前台服务VRecorder
targetSDK
已经是28(Android P,API 9)FloatWindowService.java
应用打开后,创建悬浮球依赖的前台服务,同时会在通知栏创建前台服务通知。
/**
* 没有开始录制则会开启foreground通知栏
*/
private void startForegroundServiceAndNotification() {
if (!Prefs.getIsRecordStart(getApplicationContext())) {
StartRecordNotifications notifications = new StartRecordNotifications(getApplicationContext());
if (Build.MANUFACTURER.equals("OPPO") || Build.BRAND.equalsIgnoreCase("Xiaomi")) {
//判断是否是oppo手机
//判断是否是小米手机
startForeground(StartRecordNotifications.NOTIFICATION_ID, notifications.getXiaoMiNotification());
} else {
startForeground(StartRecordNotifications.NOTIFICATION_ID, notifications.getNormalNotification());
}
}
}
因为是target 28,所有Manifest里配置了权限前台服务权限
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
StartRecorderService.java
该服务是录制时打开的后台服务,在Android P以下没有独立打开通知,不属于前台服务。
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
if (intent != null) {
if (intent.getBooleanExtra(VIDEO_EXIT_APP, false)) {
//退出录制
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();//关闭所有通知
}
...
//关闭所有APP打开的任务
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (activityManager != null) {
List<ActivityManager.AppTask> appTasks = activityManager.getAppTasks();
for (int i = 0; i < appTasks.size(); i++) {
appTasks.get(i).finishAndRemoveTask();
}
}
//关闭自身服务
stopSelf();
return START_NOT_STICKY;
}
StartRecordNotifications.java
录制通知栏专属类创建该类的时候就一并创建通知渠道id和渠道名称
public StartRecordNotifications(Context context) {
this.context = context;
createNotificationChannel();
}
创建渠道id和名称
public static final String RECORD_CHANNEL_ID = "record_channel_id";
public static final String RECORD_CHANNEL = "record channel";
public static final String RECORD_NOTIFICATION_DESCRIPTION = "record notification";
private void createNotificationChannel() {
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(RECORD_CHANNEL_ID, RECORD_CHANNEL, importance);
channel.setDescription(RECORD_NOTIFICATION_DESCRIPTION);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
mNotificationManager.createNotificationChannel(channel);
}
mBuilder = new NotificationCompat.Builder(context.getApplicationContext(), RECORD_CHANNEL_ID);
//创建通知:
mBuilder.setOngoing(true)//设置是否常驻,true为常驻
.setContentTitle(context.getString(R.string.string_notification_start_recording))
// .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setSmallIcon(R.mipmap.ic_launcher_white)//设置小图标
.setCategory(NotificationCompat.CATEGORY_EVENT)
.setPriority(Notification.PRIORITY_LOW)//设置优先级
.setWhen(System.currentTimeMillis());//设置展示时间
}
android:foregroundServiceType
属性依然需要前台服务权限声明
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service
android:name=".windowmanager.StartRecorderService"
android:enabled="true"
android:foregroundServiceType="mediaProjection"
android:exported="false" />
<service
android:name=".windowmanager.FloatWindowService"
android:foregroundServiceType="mediaProjection"/>
开启前台服务时需要添加参数foregroundServiceType
使用如下方法
startForeground(int id,Notification notification,int foregroundServiceType)
VRecorder使用案例:在FloatWindowService.java和StartRecorderService.java里都需要调用
public static void startForegroundServiceAndNotification(Service service) {
...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {//Android 10
service.startForeground(StartRecordNotificationUtils.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
} else {//非Android10
service.startForeground(StartRecordNotificationUtils.NOTIFICATION_ID, notification);
}
}
}
在FloatWindowService.java
里退出APP时:
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
if (intent == null) return START_REDELIVER_INTENT;
if (intent.getBooleanExtra(VIDEO_EXIT_APP, false)) {//退出录制
Prefs.setIsRecordStart(getApplicationContext(), false);
MyWindowManager.releaseFloatViews(this);
finishAllTaskAndActivity();//关闭所有activity task
stopRecorderServices();//关闭录制服务
stopForeground(true);//设置true,移除通知
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();
}
stopSelf();
return START_NOT_STICKY;
}
/**
*关闭录制服务
*/
private void stopRecorderServices() {
Intent name = new Intent(this, StartRecorderService.class);
name.putExtra(VIDEO_EXIT_APP, true);
stopService(name);
}
由各个事项定义好的图形对象实现draw方法来画出对应图形。
如下圆形对象的定义:
public class Circle extends ShapeAbstract {
public Circle(Shapable paintTool) {
super(paintTool);
}
@Override
public void draw(Canvas canvas, Paint paint) {
if (canvas==null || paint == null) {
return;
}
super.draw(canvas, paint);
float cx = (x1 + x2)/2;
float cy = (y1+y2)/2;
float radius = (float) Math.sqrt(Math.pow(x1 - x2, 2)
+ Math.pow(y1 - y2, 2))/2;
canvas.drawCircle(cx, cy, radius, paint);
}
@Override
public String toString() {
return " circle";
}
}
其中x1,x2,x2,y2的含义是手势触摸移动的坐标
x1 = firstCurrentPos.firstX;
y1 = firstCurrentPos.firstY;
x2 = firstCurrentPos.currentX;
y2 = firstCurrentPos.currentY;
其他图示类似方法来定义。
五角星需要数学知识计算如何画图形。
通过Canvas对象来画对应的形状:
canvas.drawLine(float startX, float startY, float stopX, float stopY,@NonNull Paint paint) ;//画直线
canvas.drawPath(@NonNull Path path, @NonNull Paint paint) ;//画路径曲线,五角星
canvas.drawOval(@NonNull RectF oval, @NonNull Paint paint);//画椭圆
canvas.drawRect(float left, float top, float right, float bottom, @NonNull Paint paint);//画矩形或正方形
画笔类型分为:
画笔对象:android.graphics.Paint
普通画笔
PlainPen:设置Paint.Style.STROKE
模糊
BlurPen: 设置Paint.Style.STROKE,设置maskFilter
// BlurMaskFilter 指定了一个模糊的样式和半径来处理Paint的边缘。
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
mPenPaint.setMaskFilter(mBlur);
浮雕
EmbossPen :设置Paint.Style.STROKE,设置maskFilter
// EmbossMaskFilter 指定了光源的方向和环境光强度来添加浮雕效果。
mEmboss = new EmbossMaskFilter(new float[] {
1, 1, 1
}, 0.4f, 6, 3.5f);
mPenPaint.setMaskFilter(mEmboss);
橡皮擦
Eraser:设置PorterDuffXfermode为PorterDuff.Mode.DST_OUT
mEraserPaint
.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
结合手势move坐标创建Path然后画贝塞尔曲线
// 画出贝塞尔曲线
private void drawBeziercurve(float x, float y) {
mPath.quadTo(mCurrentX, mCurrentY, (x + mCurrentX) / 2,
(y + mCurrentY) / 2);
}
之后画橡皮曲线
@Override
public void draw(Canvas canvas) {
if (null != canvas) {
canvas.drawPath(mPath, mEraserPaint);
}
}
package com.xvideostudio.videoeditor.paintpadinterfaces
package com.xvideostudio.videoeditor.paintshapes
package com.xvideostudio.videoeditor.painttools
package com.xvideostudio.videoeditor.paintutils
package com.xvideostudio.videoeditor.paintviews