Commit e42dcad0 authored by mengcuiguang's avatar mengcuiguang

代码优化

parent 4f306df4
......@@ -64,8 +64,7 @@ android {
// 不显示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
buildConfigField "String", "AppKeyPre", "\"abcd\""
// buildConfigField "String", "MainIp", DEBUG_URL
buildConfigField "String", "MainIp", RELEASE_URL
buildConfigField "String", "MainIp", DEBUG_URL
//混淆
minifyEnabled false
......@@ -250,6 +249,4 @@ dependencies {
implementation(name: 'tzsdk_reporter-3.0.0-20200807131516-release', ext: 'aar')
// 快手
implementation(name: 'kssdk-ad-3.3.6-publishRelease', ext: 'aar')
// 抖音滑动LayoutManager
implementation(name: 'LayoutManagerGroup', ext: 'aar')
}
......@@ -159,11 +159,6 @@
<activity android:name="com.wenshu.aiyuebao.ui.activitys.XmlyAwardActivity" />
<activity android:name="com.wenshu.aiyuebao.ui.activitys.XmlyPlayActivity" />
<activity android:name="com.wenshu.aiyuebao.ui.activitys.TaskCpdActivity" />
<activity
android:name="com.wenshu.aiyuebao.ui.activitys.KylVideoActivity"
android:configChanges="orientation|screenSize|keyboardHidden" />
<activity android:name="com.wenshu.aiyuebao.call.permission.PermissionActivity" />
<activity android:name="com.wenshu.aiyuebao.call.detail.DetailApplyActivity" />
<service
android:name="com.wenshu.aiyuebao.service.UpdateService"
......@@ -283,24 +278,6 @@
android:resource="@xml/wn_file_paths" />
</provider>
<!-- 来电秀 -->
<service
android:name="com.wenshu.aiyuebao.call.service.PhoneListenService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<provider
android:name="com.wenshu.aiyuebao.call.provider.CallProvider"
android:authorities="com.wenshu.aiyuebao.provider"
android:exported="true"
android:permission="com.wenshu.aiyuebao.permission" />
</application>
</manifest>
\ No newline at end of file
package com.android.internal.telephony;
interface ITelephony {
boolean endCall();
}
package com.wenshu.aiyuebao.call.business;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.media.RingtoneManager;
import android.net.Uri;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.widget.Toast;
import java.io.File;
/**
* Ringtone设置来电秀
* 作者:孟崔广
*/
public class RingtoneHelper {
/**
* 设置铃声为null
*
* @param context
*/
public static void setNoRing(Context context) {
if (context == null) {
return;
}
RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, null);
Toast.makeText(context, "已清除铃声!", Toast.LENGTH_SHORT).show();
}
/**
* 设置系统铃声
*
* @param context
* @param path
*/
public static void setRing(Context context, String path) {
if (context == null || TextUtils.isEmpty(path)) {
return;
}
File sdFile = new File(path);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, sdFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, sdFile.getName());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(sdFile.getAbsolutePath());
if (uri == null) {
return;
}
Uri newUri;
String query = MediaStore.MediaColumns.DATA + "=\"" + sdFile.getAbsolutePath() + "\"";
Cursor cursor = context.getContentResolver().query(uri, null, query, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
String id = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
newUri = Uri.parse(uri.toString() + "/" + id);
} else {
newUri = context.getContentResolver().insert(uri, values);
}
cursor.close();
} else {
newUri = context.getContentResolver().insert(uri, values);
}
RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, newUri);
// ToastUtil.show(context,"设置来电秀成功!");
}
}
package com.wenshu.aiyuebao.call.business;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import com.wenshu.aiyuebao.call.provider.CallProvider;
import com.wenshu.aiyuebao.common.Constant;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 来电秀数据库操作
*
* 作者:孟崔广
*/
public class VideoDBHelper {
public static final String UNKNOWN_NUMBER = "unknown";
private static final String AUTHORITY = "content://" + Constant.wenshu_PKG_NAME + ".provider";
private static final Uri VIDEO_URI = Uri.parse(AUTHORITY);
private VideoDBHelper() {
}
private static class SingleTon {
private static VideoDBHelper sInstance = new VideoDBHelper();
}
public static VideoDBHelper getInstance() {
return SingleTon.sInstance;
}
public void setSelectVideo(Context context, String number, String path) {
ContentValues values = new ContentValues();
values.put(CallProvider.NUMBER, handleNumber(number));
values.put(CallProvider.PATH, path);
if (!TextUtils.isEmpty(queryVideo(context, number))) {
context.getContentResolver().delete(VIDEO_URI, CallProvider.NUMBER + "=\'" + number + "\'", null);
}
context.getContentResolver().insert(VIDEO_URI, values);
}
public String getSelectVideo(Context context, String number) {
String path = queryVideo(context, handleNumber(number));
if (TextUtils.isEmpty(path)) {
path = queryVideo(context, UNKNOWN_NUMBER);
}
Log.d("LLL", "path = " + path);
return path;
}
private String handleNumber(String number) {
if (TextUtils.isEmpty(number) || UNKNOWN_NUMBER.equals(number)) {
return number;
}
String regEx = "[^0-9]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(number);
return m.replaceAll("").trim();
}
private String queryVideo(Context context, String number) {
Cursor cursor = context.getContentResolver().query(VIDEO_URI, null, CallProvider.NUMBER + "=\'" + number + "\'",
null, null);
String path = "";
if (cursor != null && cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(CallProvider.PATH));
cursor.close();
}
return path;
}
}
package com.wenshu.aiyuebao.call.callcore;
import android.app.KeyguardManager;
import android.app.Notification;
import android.content.Context;
import android.text.TextUtils;
import com.wenshu.aiyuebao.call.widget.FloatingView;
import com.wenshu.aiyuebao.call.widget.LockGuideView;
/**
* 来电秀核心设置
* 作者:孟崔广
*/
public abstract class CallCore {
protected static final String TAG = "CallCore";
public static final String SYSTEM_CALL_PKG = "system_call";
protected static final int STATUS_NONE = 0;
protected static final int STATUS_RINGING = 1;
protected int mStatus = STATUS_NONE;
Context mContext;
FloatingView mFloatingView;
Notification.Action[] mActions;
private String mPackage;
private boolean mClicked = false;
CallCore(Context context, String pkg) {
init(context, pkg);
}
private void init(Context context, String pkg) {
if (context == null) {
return;
}
mContext = context;
mPackage = pkg;
mFloatingView = new FloatingView(context);
mFloatingView.setListener(new FloatingView.OnCallListener() {
@Override
public void onGet() {
mClicked = true;
acceptCall();
}
@Override
public void onEnd() {
mClicked = true;
endCall();
}
});
}
public String getPackage() {
return mPackage;
}
public void setPackage(String aPackage) {
mPackage = aPackage;
}
/**
* 有来电时:未接/挂断/通话结束
*/
void showLockGuide() {
if (!mClicked && isLocked()) {
LockGuideView guideView = new LockGuideView(mContext);
guideView.show();
} else {
mClicked = false;
}
}
/**
* 是否锁屏
* 有密码亮屏:isKeyguardLocked = false, isKeyguardSecure = true, isDeviceLocked = false, isDeviceSecure = true
* 无密码亮屏:isKeyguardLocked = false, isKeyguardSecure = false, isDeviceLocked = false, isDeviceSecure = false
* 有密码锁屏:isKeyguardLocked = true, isKeyguardSecure = true, isDeviceLocked = true, isDeviceSecure = true
* 无密码锁屏:isKeyguardLocked = true, isKeyguardSecure = false, isDeviceLocked = false, isDeviceSecure = false
*/
protected boolean isLocked() {
if (mContext != null) {
KeyguardManager manager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
return manager != null && manager.isKeyguardLocked();
}
return false;
}
protected void sendAction(int position) {
if (mActions != null) {
try {
mActions[position].actionIntent.send();
} catch (Exception e) {
e.printStackTrace();
} finally {
mActions = null;
}
}
}
protected abstract void acceptCall();
protected abstract void endCall();
public abstract void onNotificationPosted(Notification notification);
public abstract void onNotificationRemoved(Notification notification);
public abstract void onDestroy();
public static CallCore createCallCore(Context context, String pkg) {
if (context == null || TextUtils.isEmpty(pkg)) {
return null;
}
try {
switch (pkg) {
case SYSTEM_CALL_PKG:
return new SystemCallCore(context, pkg);
default:
return null;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.wenshu.aiyuebao.call.callcore;
import android.Manifest;
import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import com.android.internal.telephony.ITelephony;
import com.wenshu.aiyuebao.call.service.PhoneListenService;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* 监听处理来电
* 作者:孟崔广
*/
public class SystemCallCore extends CallCore {
private static final List<String> mCallPkgs = new ArrayList<>();
private TelecomManager mTelManager;
private BroadcastReceiver mPhoneStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.equals(action, "android.intent.action.PHONE_STATE")) {
if (mFloatingView == null) {
return;
}
String state = intent.getStringExtra("state");
String number = intent.getStringExtra("incoming_number");
Log.d(TAG, this + " state = " + state + ", number = " + number);
if (TelephonyManager.EXTRA_STATE_RINGING.equalsIgnoreCase(state)) {
if (isLocked()) {
mStatus = STATUS_RINGING;
}
mFloatingView.show(number);
} else {
mFloatingView.hide();
if (TelephonyManager.EXTRA_STATE_OFFHOOK.equalsIgnoreCase(state) && mStatus == STATUS_RINGING) {
mStatus = STATUS_NONE;
showLockGuide();
}
}
}
}
};
SystemCallCore(Context context, String pkg) {
super(context, pkg);
init(context);
}
private void init(Context context) {
if (context == null) {
return;
}
mTelManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.PHONE_STATE");
context.registerReceiver(mPhoneStateReceiver, filter);
mCallPkgs.add("com.google.android.dialer");
mCallPkgs.add("com.android.incallui");
}
@Override
protected void acceptCall() {
if (mContext == null) {
return;
}
if (mTelManager != null) {
if (mContext.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
mTelManager.showInCallScreen(false);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mTelManager != null) {
mTelManager.acceptRingingCall();
}
} else {
sendHeadsetHook(true);
}
}
@Override
protected void endCall() {
if (mContext == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (mTelManager != null) {
mTelManager.endCall();
}
} else {
sendHeadsetHook(false);
try {
Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
IBinder binder = (IBinder) method.invoke(null, new Object[]{Context.TELEPHONY_SERVICE});
ITelephony telephony = ITelephony.Stub.asInterface(binder);
telephony.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onNotificationPosted(Notification notification) {
Log.d(TAG, "onNotificationPosted: " + notification);
if (mContext == null || notification == null) {
return;
}
if (!canReadContact()) {
Bundle bundle = notification.extras;
if (bundle != null) {
mFloatingView.setPerson(String.valueOf(bundle.getCharSequence(Notification.EXTRA_TITLE)), null);
}
}
}
@Override
public void onNotificationRemoved(Notification notification) {
Log.d(TAG, "onNotificationRemoved: " + notification);
}
@Override
public void onDestroy() {
if (mContext != null) {
mContext.unregisterReceiver(mPhoneStateReceiver);
}
}
public boolean isCall(StatusBarNotification sbn) {
return sbn != null && sbn.getNotification() != null &&
mCallPkgs.contains(sbn.getPackageName())
&& sbn.getNotification().actions != null;
}
private boolean canReadContact() {
return mContext != null
&& mContext.checkSelfPermission(Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED
&& mContext.checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED;
}
/**
* 通过模拟耳机接听/挂断电话
*
* @param isAnswer: true, 接听; false: 挂断
*/
private void sendHeadsetHook(boolean isAnswer) {
if (mContext == null) {
return;
}
MediaSessionManager sessionManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
if (sessionManager == null) {
return;
}
try {
List<MediaController> controllers = sessionManager.getActiveSessions(new ComponentName(mContext, PhoneListenService.class));
for (MediaController m : controllers) {
if ("com.android.server.telecom".equals(m.getPackageName())) {
if (isAnswer) {
m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
} else {
long now = SystemClock.uptimeMillis();
m.dispatchMediaButtonEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK,
1, 0, KeyCharacterMap.VIRTUAL_KEYBOARD,
0, KeyEvent.FLAG_LONG_PRESS, InputDevice.SOURCE_KEYBOARD));
}
m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
Log.d(TAG, this + " headset sent to tel");
break;
}
}
} catch (Exception e) {
Log.d(TAG, this + " Permission error, Access to notification not granted to the app.");
}
}
}
package com.wenshu.aiyuebao.call.detail;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.wenshu.aiyuebao.R;
import com.wenshu.aiyuebao.call.business.RingtoneHelper;
import com.wenshu.aiyuebao.call.permission.PermissionManager;
import com.wenshu.aiyuebao.ui.activitys.MainActivity;
/**
* 设置成功
* 作者:孟崔广
*/
public class DetailApplyActivity extends AppCompatActivity {
private TextView mRingtoneView;
private boolean mSetRingtone = true;
private String mVideoPath;
public static final String KEY_VIDEO_PATH = "video_path";
public static final String KEY_SET_RINGTONE = "key_set_ringtone";
public static void startSelf(Context context, String path, boolean setRingtone) {
if (context == null) {
return;
}
Intent intent = new Intent(context, DetailApplyActivity.class);
intent.putExtra(DetailApplyActivity.KEY_VIDEO_PATH, path);
intent.putExtra(DetailApplyActivity.KEY_SET_RINGTONE, setRingtone);
if (!(context instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail_apply);
handleIntent();
init();
setRingtone();
}
private void init() {
mRingtoneView = findViewById(R.id.ringtone_apply_tv);
}
private void handleIntent() {
mSetRingtone = getIntent().getBooleanExtra(DetailApplyActivity.KEY_SET_RINGTONE, true);
mVideoPath = getIntent().getStringExtra(DetailApplyActivity.KEY_VIDEO_PATH);
}
private void setRingtone() {
if (PermissionManager.getInstance().isSettingsEnabled(this)) {
if (mSetRingtone) {
RingtoneHelper.setRing(this, mVideoPath);
mRingtoneView.setVisibility(View.VISIBLE);
}
} else {
PermissionManager.getInstance().requestSettings(this);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
PermissionManager.getInstance().onActivityResult(this, requestCode);
if (PermissionManager.getInstance().isSettingsEnabled(this)) {
if (mSetRingtone) {
RingtoneHelper.setRing(this, mVideoPath);
mRingtoneView.setVisibility(View.VISIBLE);
}
}
}
public void tvSucFinish(View view) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
}
package com.wenshu.aiyuebao.call.permission;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.wenshu.aiyuebao.R;
/**
* 权限申请界面
* 作者:孟崔广
*/
public class PermissionActivity extends AppCompatActivity {
private ImageView mSdcardIv;
private ImageView mPhoneIv;
private ImageView mFloatIv;
private ImageView mNotificationIv;
public static void startSelf(Context context) {
if (context == null) {
return;
}
Intent intent = new Intent(context, PermissionActivity.class);
if (!(context instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_permission);
init();
updateUI();
}
private void init() {
mSdcardIv = findViewById(R.id.sdcard_iv);
mPhoneIv = findViewById(R.id.phone_iv);
mFloatIv = findViewById(R.id.float_iv);
mNotificationIv = findViewById(R.id.notification_iv);
}
private void updateUI() {
mSdcardIv.setImageResource(PermissionManager.getInstance().isSdcardEnabled(this)
? R.mipmap.get_permission : R.mipmap.no_permission);
mPhoneIv.setImageResource(PermissionManager.getInstance().isPhoneEnabled(this)
? R.mipmap.get_permission : R.mipmap.no_permission);
mFloatIv.setImageResource(PermissionManager.getInstance().isFloatEnabled(this)
? R.mipmap.get_permission : R.mipmap.no_permission);
mNotificationIv.setImageResource(PermissionManager.getInstance().isNotificationEnabled(this)
? R.mipmap.get_permission : R.mipmap.no_permission);
if (PermissionManager.getInstance().checkEssential(this)) {
finish();
}
}
public void getPermission(View view) {
PermissionManager.getInstance().requestEssential(this);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
updateUI();
PermissionManager.getInstance().onActivityResult(this, requestCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
updateUI();
PermissionManager.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);
}
}
package com.wenshu.aiyuebao.call.permission;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationManagerCompat;
import java.util.Set;
public class PermissionManager {
private static final int REQUEST_ID_PERMISSION = 0;
private static final int REQUEST_ID_NOTIFICATION = 1;
private static final int REQUEST_ID_POPUP = 2;
private static final int REQUEST_ID_CONTACT_PERMISSION = 3;
private static final int REQUEST_ID_SETTINGS_PERMISSION = 4;
/**
* 必需权限:读写sdcard,来电状态,接听/挂断电话,悬浮窗,通知栏
*/
private String[] mEssentialPermissions = new String[]{
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CALL_PHONE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
"",
};
/**
* 联系人权限
*/
private String[] mContactPermissions = new String[]{
Manifest.permission.READ_CALL_LOG,
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS,
};
private PermissionManager() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mEssentialPermissions[4] = Manifest.permission.ANSWER_PHONE_CALLS;
}
}
private static class SingleTon {
private static PermissionManager sInstance = new PermissionManager();
}
public static PermissionManager getInstance() {
return SingleTon.sInstance;
}
public boolean checkEssential(Context context) {
if (context == null) {
return false;
}
for (String permission : mEssentialPermissions) {
if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return isNotificationEnabled(context) && isFloatEnabled(context);
}
public void requestEssential(Activity activity) {
if (activity == null) {
return;
}
ActivityCompat.requestPermissions(activity, mEssentialPermissions, REQUEST_ID_PERMISSION);
}
public void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions, int[] grantResults) {
if (activity == null || grantResults == null) {
return;
}
if (requestCode == REQUEST_ID_PERMISSION && grantResults.length > 0) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permissions[i])) {
ActivityCompat.requestPermissions(activity, mEssentialPermissions, REQUEST_ID_PERMISSION);
} else {
PermissionUtil.jumpPermissionPage(activity);
}
}
}
openFloatSettings(activity);
openNotificationSettings(activity);
}
}
public void onActivityResult(Activity activity, int requestCode) {
if (activity == null) {
return;
}
}
public boolean isContactEnabled(Context context) {
return isPermissionsEnabled(context, mContactPermissions);
}
public void requestSettings(Activity activity) {
try {
if (isSettingsEnabled(activity)) {
return;
}
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + activity.getPackageName()));
activity.startActivityForResult(intent, REQUEST_ID_SETTINGS_PERMISSION);
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isSdcardEnabled(Context context) {
String[] permissions = new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
};
return isPermissionsEnabled(context, permissions);
}
public boolean isPhoneEnabled(Context context) {
String[] permissions = new String[]{
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CALL_PHONE,
"",
};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
permissions[2] = Manifest.permission.ANSWER_PHONE_CALLS;
}
return isPermissionsEnabled(context, permissions);
}
public boolean isNotificationEnabled(Context context) {
if (context == null) {
return false;
}
Set<String> packageNames = NotificationManagerCompat.getEnabledListenerPackages(context);
return packageNames.contains(context.getPackageName());
}
public boolean isFloatEnabled(Context context) {
if (context == null) {
return false;
}
return Settings.canDrawOverlays(context);
}
public boolean isSettingsEnabled(Context context) {
if (context == null) {
return false;
}
return Settings.System.canWrite(context);
}
private boolean isPermissionsEnabled(Context context, String[] permissions) {
if (context == null || permissions == null) {
return false;
}
for (String permission : permissions) {
if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
private void openNotificationSettings(Activity activity) {
try {
if (isNotificationEnabled(activity)) {
return;
}
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
activity.startActivityForResult(intent, REQUEST_ID_NOTIFICATION);
} catch (Exception e) {
e.printStackTrace();
}
}
private void openFloatSettings(Activity activity) {
try {
if (isFloatEnabled(activity)) {
return;
}
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + activity.getPackageName()));
activity.startActivityForResult(intent, REQUEST_ID_POPUP);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.wenshu.aiyuebao.call.permission;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
/**
* 手机厂商权限兼容
* 作者:孟崔广
*/
public class PermissionUtil {
private static final String sManufacturer = Build.MANUFACTURER.toLowerCase();
private static boolean isIntentIllegal(Context paramContext, Intent paramIntent) {
return paramContext.getPackageManager().queryIntentActivities(paramIntent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
private static Intent getAll(Context paramContext) {
Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", paramContext.getPackageName(), null));
return intent;
}
private static Intent getHuaWei(Context paramContext) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity"));
if (isIntentIllegal(paramContext, intent))
return intent;
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity"));
if (isIntentIllegal(paramContext, intent))
return intent;
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.notificationmanager.ui.NotificationManagmentActivity"));
return intent;
}
private static Intent getXiaoMi(Context paramContext) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.putExtra("extra_pkgname", paramContext.getPackageName());
if (isIntentIllegal(paramContext, intent))
return intent;
intent.setPackage("com.miui.securitycenter");
if (isIntentIllegal(paramContext, intent))
return intent;
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
return intent;
}
private static Intent getOPPO(Context paramContext) {
Intent intent = new Intent();
intent.putExtra("packageName", paramContext.getPackageName());
intent.setClassName("com.color.safecenter", "com.color.safecenter.permission.floatwindow.FloatWindowListActivity");
if (isIntentIllegal(paramContext, intent))
return intent;
intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity");
if (isIntentIllegal(paramContext, intent))
return intent;
intent.setClassName("com.oppo.safe", "com.oppo.safe.permission.PermissionAppListActivity");
return intent;
}
private static Intent getIqoo(Context paramContext) {
Intent intent = new Intent();
intent.setClassName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.FloatWindowManager");
intent.putExtra("packagename", paramContext.getPackageName());
if (isIntentIllegal(paramContext, intent))
return intent;
intent.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.safeguard.SoftPermissionDetailActivity"));
return intent;
}
private static Intent getMeiZu(Context paramContext) {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.putExtra("packageName", paramContext.getPackageName());
intent.setComponent(new ComponentName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity"));
return intent;
}
public static void jumpPermissionPage(Context context) {
if (context == null) {
return;
}
Intent intent;
if (sManufacturer.contains("huawei")) {
intent = getHuaWei(context);
} else if (sManufacturer.contains("xiaomi")) {
intent = getXiaoMi(context);
} else if (sManufacturer.contains("oppo")) {
intent = getOPPO(context);
} else if (sManufacturer.contains("vivo")) {
intent = getIqoo(context);
} else if (sManufacturer.contains("meizu")) {
intent = getMeiZu(context);
} else {
intent = getAll(context);
}
try {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch (Exception exception) {
exception.printStackTrace();
}
}
public static Intent getAutoStartSettingIntent(Context context) throws Exception {
ComponentName componentName = null;
String brand = Build.MANUFACTURER;
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
switch (brand.toLowerCase()) {
case "samsung"://三星
componentName = new ComponentName("com.samsung.android.sm",
"com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity");
break;
case "huawei"://华为
componentName = ComponentName.unflattenFromString("com.huawei.systemmanager/.startupmgr.ui.StartupNormalAppListActivity");
break;
case "xiaomi"://小米
componentName = new ComponentName("com.miui.securitycenter",
"com.miui.permcenter.autostart.AutoStartManagementActivity");
break;
case "vivo"://VIVO
componentName = new ComponentName("com.iqoo.secure",
"com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity");
break;
case "oppo"://OPPO
// componentName = new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity");
componentName = new ComponentName("com.coloros.oppoguardelf",
"com.coloros.powermanager.fuelgaue.PowerUsageModelActivity");
break;
case "yulong":
case "360"://360
componentName = new ComponentName("com.yulong.android.coolsafe",
"com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity");
break;
case "meizu"://魅族
componentName = new ComponentName("com.meizu.safe",
"com.meizu.safe.permission.SmartBGActivity");
break;
case "oneplus"://一加
componentName = new ComponentName("com.oneplus.security",
"com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity");
break;
case "letv"://乐视
intent.setAction("com.letv.android.permissionautoboot");
default://其他
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
break;
}
intent.setComponent(componentName);
return intent;
}
}
package com.wenshu.aiyuebao.call.preference;
import android.net.Uri;
import com.wenshu.aiyuebao.common.Constant;
public class PreferenceUtil {
public static final String AUTHORITY = Constant.wenshu_PKG_NAME;
public static final Uri URI = Uri.parse("content://" + AUTHORITY);
}
package com.wenshu.aiyuebao.call.provider;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* 初始化数据库
* 作者:孟崔广
*/
public class CallProvider extends ContentProvider {
private static final String TAG = "LLL";
public static final String NUMBER = "number";
public static final String PATH = "path";
private SQLiteDatabase mDatabase;
@Override
public boolean onCreate() {
mDatabase = new DataBaseHelper(getContext()).getWritableDatabase();
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder) {
return mDatabase.query(DataBaseHelper.USER_TABLE_NAME, projection, selection, selectionArgs, sortOrder, null, null);
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
Log.d(TAG, "values = " + values);
mDatabase.insert(DataBaseHelper.USER_TABLE_NAME, null, values);
return uri;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return mDatabase.delete(DataBaseHelper.USER_TABLE_NAME, selection, selectionArgs);
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
package com.wenshu.aiyuebao.call.provider;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DataBaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "call.db";
public static final String USER_TABLE_NAME = "video";
private static final int DATABASE_VERSION = 3;
public DataBaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE IF NOT EXISTS " + USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ " number TEXT, path TEXT)";
Log.d("LLL", "sql = " + sql);
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
package com.wenshu.aiyuebao.call.service;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.wenshu.aiyuebao.R;
import com.wenshu.aiyuebao.call.callcore.CallCore;
import com.wenshu.aiyuebao.call.callcore.SystemCallCore;
import com.wenshu.aiyuebao.ui.activitys.MainActivity;
import java.util.HashMap;
import java.util.Map;
/**
* 通知核心
* 作者:孟崔广
*/
public class PhoneListenService extends NotificationListenerService {
public static final String TAG = "PhoneListenService";
private SystemCallCore mSystemCallCore;
private Map<String, CallCore> mCallCores = new HashMap<>();
@Override
public void onCreate() {
super.onCreate();
mSystemCallCore = (SystemCallCore) CallCore.createCallCore(this, CallCore.SYSTEM_CALL_PKG);
}
private Notification buildNotification() {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
return null;
}
String channelId = getString(R.string.app_name);
NotificationChannel notificationChannel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setDescription(channelId);
notificationChannel.setSound(null, null);
notificationManager.createNotificationChannel(notificationChannel);
notification = new Notification.Builder(this, channelId)
.setContentTitle(getString(R.string.app_name))
.setContentText("来电秀")
.setSmallIcon(R.mipmap.ic_launcher_main)
.setContentIntent(contentIntent)
.build();
} else {
notification = new Notification.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setContentText("来电秀")
.setSmallIcon(R.mipmap.ic_launcher_main)
.setContentIntent(contentIntent)
.build();
}
return notification;
}
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
super.onNotificationPosted(sbn);
if (sbn == null) {
return;
}
if (mSystemCallCore.isCall(sbn)) {
mSystemCallCore.onNotificationPosted(sbn.getNotification());
}
CallCore callCore;
if (mCallCores.containsKey(sbn.getPackageName())) {
callCore = mCallCores.get(sbn.getPackageName());
} else {
callCore = CallCore.createCallCore(this, sbn.getPackageName());
if (callCore != null) {
mCallCores.put(callCore.getPackage(), callCore);
}
}
if (callCore != null) {
callCore.onNotificationPosted(sbn.getNotification());
}
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
super.onNotificationRemoved(sbn);
CallCore callCore = mCallCores.get(sbn.getPackageName());
if (callCore != null) {
callCore.onNotificationRemoved(sbn.getNotification());
}
}
@Override
public void onListenerConnected() {
Log.d(TAG, getClass().getSimpleName() + ": onListenerConnected");
super.onListenerConnected();
}
@Override
public void onListenerDisconnected() {
Log.d(TAG, getClass().getSimpleName() + ": onListenerDisconnected");
super.onListenerDisconnected();
}
@Override
public void onDestroy() {
Log.d(TAG, getClass().getSimpleName() + ": onDestroy");
mSystemCallCore.onDestroy();
super.onDestroy();
}
}
package com.wenshu.aiyuebao.call.util;
import android.content.Context;
public class DimensionUtil {
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 根据手机的分辨率从 sp 的单位 转成为 px(像素)
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
package com.wenshu.aiyuebao.call.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.wenshu.aiyuebao.R;
import com.wenshu.aiyuebao.call.util.DimensionUtil;
public class CircleTextView extends View {
private String mCustomText;
private int mCustomColor;
private int mCustomRadius;
private int mFontSize;
private Paint mCirclePaint;
private TextPaint mTextPaint;
public CircleTextView(Context context) {
this(context, null);
}
public CircleTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initCustomAttrs(context, attrs);
}
private void initCustomAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleTextView);
mFontSize = DimensionUtil.sp2px(context, ta.getInteger(R.styleable.CircleTextView_size, 16));
mCustomText = ta.getString(R.styleable.CircleTextView_text);
mCustomColor = ta.getColor(R.styleable.CircleTextView_color, Color.BLUE);
mCustomRadius = DimensionUtil.dip2px(context, ta.getInteger(R.styleable.CircleTextView_radius, 30));
ta.recycle();
mCirclePaint = new Paint();
mCirclePaint.setColor(mCustomColor);
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(2);
mTextPaint = new TextPaint();
mTextPaint.setColor(mCustomColor);
mTextPaint.setTextSize(mFontSize);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
// 在wrap_content的情况下默认长度为200
int minSize = 100;
// 当布局参数设置为wrap_content时,设置默认值
if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT && getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(minSize, minSize);
// 宽 / 高任意一个布局参数为= wrap_content时,都设置默认值
} else if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(minSize, heightSpecSize);
} else if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(widthSpecSize, minSize);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 处理padding属性
final int paddingLeft = getPaddingLeft();
final int paddingTop = getPaddingTop();
final int paddingRight = getPaddingRight();
final int paddingBottom = getPaddingBottom();
int width = 2 * mCustomRadius - paddingLeft - paddingRight;
int height = 2 * mCustomRadius - paddingTop - paddingBottom;
mCustomRadius = Math.min(width, height) / 2;
canvas.drawCircle(width / 2, height / 2, mCustomRadius, mCirclePaint);
// 将坐标原点移到控件中心
canvas.translate(width / 2f, height / 2f);
float textWidth = mTextPaint.measureText(mCustomText);
// 文字baseline在y轴方向的位置
float baseLineY = Math.abs(mTextPaint.ascent() + mTextPaint.descent()) / 2;
canvas.drawText(mCustomText, -textWidth / 2, baseLineY, mTextPaint);
}
}
package com.wenshu.aiyuebao.call.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.VideoView;
public class CustomVideoView extends VideoView {
public CustomVideoView(Context context) {
super(context);
}
public CustomVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(0, widthMeasureSpec);
int height = getDefaultSize(0, heightMeasureSpec);
setMeasuredDimension(width, height);
}
}
package com.wenshu.aiyuebao.call.widget;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.VideoView;
import com.wenshu.aiyuebao.R;
import com.wenshu.aiyuebao.call.business.VideoDBHelper;
public class FloatingView extends FrameLayout {
private Context mContext;
private WindowManager mWindowManager;
private View mView;
private VideoView mVideoView;
private LockSlidingView mAcceptView;
private LockSlidingView mEndCallView;
private TextView mNameView;
private TextView mNumberView;
private ImageView mHeadView;
private OnCallListener mListener;
private boolean mShown = false;
public FloatingView(Context context) {
super(context);
mContext = context;
mView = LayoutInflater.from(context).inflate(R.layout.floating_view, null);
mAcceptView = mView.findViewById(R.id.get_call);
mEndCallView = mView.findViewById(R.id.end_call);
mNameView = mView.findViewById(R.id.name_tv);
mNumberView = mView.findViewById(R.id.number_tv);
mHeadView = mView.findViewById(R.id.head_icon);
mAcceptView.setListener(() -> {
hide();
if (mListener != null) {
mListener.onGet();
}
});
mAcceptView.setOnSingleTapListener(e -> {
hide();
if (mListener != null) {
mListener.onGet();
}
});
mEndCallView.setListener(() -> {
hide();
if (mListener != null) {
mListener.onEnd();
}
});
mEndCallView.setOnSingleTapListener(e -> {
hide();
if (mListener != null) {
mListener.onEnd();
}
});
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mVideoView = mView.findViewById(R.id.video_view);
mVideoView.setOnPreparedListener(mp -> {
mp.start();
mp.setLooping(true);
});
}
public void setPerson(String name, String number) {
if (!TextUtils.isEmpty(name)) {
mNameView.setText(name);
}
if (!TextUtils.isEmpty(number)) {
mNumberView.setText(number);
}
}
public void setHead(Drawable drawable) {
if (drawable != null) {
mHeadView.setImageDrawable(drawable);
}
}
public void setListener(OnCallListener listener) {
this.mListener = listener;
}
public void show(String number) {
// if (!TextUtils.isEmpty(number)) {
// mNameView.setText(number);
// }
mVideoView.setVideoPath(VideoDBHelper.getInstance().getSelectVideo(mContext, number));
mAcceptView.setVisible();
mEndCallView.setVisible();
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
}
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
params.width = LayoutParams.MATCH_PARENT;
params.height = LayoutParams.MATCH_PARENT;
try {
mWindowManager.addView(mView, params);
} catch (Exception e) {
}
mShown = true;
mVideoView.start();
}
public void hide() {
if (mShown) {
try {
mWindowManager.removeView(mView);
mShown = false;
mNameView.setText("");
mNumberView.setText("");
mHeadView.setImageDrawable(null);
mVideoView.pause();
} catch (Exception e) {
}
}
}
public interface OnCallListener {
void onGet();
void onEnd();
}
}
package com.wenshu.aiyuebao.call.widget;
import android.content.Context;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import com.wenshu.aiyuebao.R;
import com.wenshu.aiyuebao.call.permission.PermissionUtil;
public class LockGuideView {
private View mView;
private WindowManager mWindowManager;
private boolean mShown = false;
public LockGuideView(Context context) {
mView = LayoutInflater.from(context).inflate(R.layout.float_lock_guide, null);
mView.findViewById(R.id.close).setOnClickListener(v -> hide());
mView.findViewById(R.id.go_open).setOnClickListener(v -> {
hide();
PermissionUtil.jumpPermissionPage(context);
});
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
public void show() {
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
}
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
try {
mWindowManager.addView(mView, params);
mShown = true;
} catch (Exception e) {
}
}
public void hide() {
if (mShown) {
try {
mWindowManager.removeView(mView);
mShown = false;
} catch (Exception e) {
}
}
}
}
package com.wenshu.aiyuebao.call.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class LockSlidingView extends SlidingFinishView {
private static final String TAG = "LockSlidingView";
private GestureDetector mGestureDetector;
private OnSingleTapListener mOnSingleTapListener;
public LockSlidingView(Context context) {
super(context);
}
public LockSlidingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LockSlidingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
protected void init(Context context) {
super.init(context);
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.d(TAG, "onSingleTapConfirmed()");
if (mOnSingleTapListener != null) {
mOnSingleTapListener.onSingleTapConfirmed(e);
return true;
}
return false;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
public void setOnSingleTapListener(OnSingleTapListener onSingleTapListener) {
this.mOnSingleTapListener = onSingleTapListener;
}
public interface OnSingleTapListener {
void onSingleTapConfirmed(MotionEvent e);
}
}
package com.wenshu.aiyuebao.call.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.RelativeLayout;
public class SlidingFinishView extends RelativeLayout {
private static final String TAG = "SlidingFinishView";
private VelocityTracker mVelocityTracker;
private float mDownY;
private static final int MAX_VELOCITY_DP = 150;
private static final int MIN_FINISH_DIS_DP = 80;
private View mMoveView;
private int mScreenHeight;
private Listener mListener;
private boolean mIsAnimation;
private float mDensity;
private int mMaxVelocityPx;
private int mTouchSlop;
public SlidingFinishView(Context context) {
super(context);
init(context);
}
public SlidingFinishView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SlidingFinishView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
protected void init(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
mScreenHeight = displayMetrics.heightPixels;
mDensity = displayMetrics.density;
mMaxVelocityPx = (int) (MAX_VELOCITY_DP * mDensity);
ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mTouchSlop = viewConfiguration.getScaledTouchSlop();
}
public void setMoveView(View moveView) {
mMoveView = moveView;
}
public void setListener(Listener listener) {
mListener = listener;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mIsAnimation) {
return super.onTouchEvent(event);
}
final float y = event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
} else {
mVelocityTracker.clear();
}
mVelocityTracker.addMovement(event);
mDownY = y;
break;
case MotionEvent.ACTION_MOVE:
if (mVelocityTracker != null) {
mVelocityTracker.addMovement(event);
}
handleMoveView(y);
break;
case MotionEvent.ACTION_UP:
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.addMovement(event);
velocityTracker.computeCurrentVelocity(1000);
int velocityY = (int) velocityTracker.getYVelocity();
velocityTracker.clear();
doTriggerEvent(y, velocityY);
break;
}
return true;
}
private void handleMoveView(float y) {
float disY = y - mDownY;
if (disY > 0) {
disY = 0;
}
Log.d(TAG, "handleMoveView--disY=" + disY);
getMoveView().setTranslationY(disY);
}
private View getMoveView() {
if (mMoveView == null) {
return this;
}
return mMoveView;
}
private void doTriggerEvent(float y, int velocityY) {
float moveY = y - mDownY;//moveY小于0,表示向上滑动
Log.d(TAG, "doTriggerEvent--velocityY=" + velocityY + "|moveY=" + moveY);
if (moveY >= 0 || Math.abs(moveY) < mTouchSlop) {
Log.d(TAG, "doTriggerEvent--moveY >= 0 || Math.abs(moveY) < mTouchSlop");
return;
}
if (-velocityY > mMaxVelocityPx) {
moveView(0, true);
} else if (-moveY > MIN_FINISH_DIS_DP * mDensity) {
moveView(0, true);
} else {
moveView(0, false);
}
}
public void setVisible() {
getMoveView().setVisibility(VISIBLE);
}
private void moveView(float to, final boolean exit) {
mIsAnimation = true;
if (exit) {
getMoveView().setVisibility(INVISIBLE);
}
ObjectAnimator animator = ObjectAnimator.ofFloat(getMoveView(), View.TRANSLATION_Y, to);
int duration = Math.min((int) Math.abs(getMoveView().getTranslationY() - to) / 2, 250);
Log.d(TAG, "moveView--duration=" + duration);
animator.setDuration(duration).start();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mIsAnimation = false;
if (exit) {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
if (mListener != null) {
mListener.onSlidingOut();
}
}
}
});
}
public interface Listener {
void onSlidingOut();
}
}
package com.wenshu.aiyuebao.ui.activitys
import android.Manifest
import android.media.MediaPlayer
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.wenshu.aiyuebao.R
import com.wenshu.aiyuebao.ad.video.VideoAdingManager
import com.wenshu.aiyuebao.call.business.VideoDBHelper
import com.wenshu.aiyuebao.call.detail.DetailApplyActivity
import com.wenshu.aiyuebao.call.permission.PermissionActivity
import com.wenshu.aiyuebao.call.permission.PermissionManager
import com.wenshu.aiyuebao.common.Constant
import com.wenshu.aiyuebao.manager.UserManager
import com.wenshu.aiyuebao.mvp.model.VideoAdingBean
import com.wenshu.aiyuebao.mvp.presenters.KylVideoPresenter
import com.wenshu.aiyuebao.mvp.views.KylVideoView
import com.wenshu.aiyuebao.ui.activitys.base.BaseActivity
import com.wenshu.aiyuebao.utils.MD5
import com.tbruyelle.rxpermissions.RxPermissions
import com.wenshu.aiyuebao.common.AppConfig
import kotlinx.android.synthetic.main.activity_kyl_video.*
/**
* 描述:酷音乐视频
* 作者:孟崔广
* 时间:2021/1/4 15:09
*/
class KylVideoActivity : BaseActivity(), View.OnClickListener, KylVideoView {
companion object {
const val VIDEO_URL = "video_url"
const val VIDEO_ID = "video_id"
}
private val WEB_VEDIO_URL = "https://vring.kuyin123.com/friend/94aa83142f7f5c98?videoId="
private lateinit var videoUrl: String
private lateinit var videoId: String
private val kylVideoPresenter by lazy { KylVideoPresenter() }
private lateinit var videoAdingManager: VideoAdingManager
private var loadVideoFailCount = 0
private var downloadId: Int = -1//vedio下载id
private var downloadVedioSucFlag = false// 下载视频成功
private var vedioPathName = ""
override fun getContentViewLayoutID() = R.layout.activity_kyl_video
override fun isApplyKitKatTranslucency() = false
override fun getBundleExtras(extras: Bundle?) {
super.getBundleExtras(extras)
extras?.let {
videoUrl = it.getString(VIDEO_URL, "")
videoId = it.getString(VIDEO_ID, "")
}
}
override fun initViewsAndEvents() {
if (TextUtils.isEmpty(videoUrl)) {
showToast("加载失败,请稍后重试.")
finish()
return
}
videoAdingManager = VideoAdingManager.getInstance(this)
initListener()
loadVedio(videoUrl)
}
private fun loadVedio(vedioUrl: String) {
cvvVedio.setOnPreparedListener { mp: MediaPlayer ->
mp.start()
mp.isLooping = true
}
cvvVedio?.setVideoPath(vedioUrl)
cvvVedio?.start()
}
override fun onResume() {
super.onResume()
cvvVedio.resume()
}
override fun onPause() {
super.onPause()
cvvVedio.pause()
}
override fun onDestroy() {
super.onDestroy()
if (downloadId != -1) {
PRDownloader.cancel(downloadId)
}
videoAdingManager.setVideoAdingListener(null)
videoAdingManager.onDestroy()
kylVideoPresenter.detachView()
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.ivBack -> finish()
R.id.ivVedio -> {
val bundle = Bundle()
bundle.putString(WebActivity.WEB_TITLE, "视频彩铃")
bundle.putString(WebActivity.WEB_URL, WEB_VEDIO_URL + videoId)
readyGo(WebActivity::class.java, bundle)
}
R.id.ivSetting -> {
if (downloadVedioSucFlag) {
readyGo()
return
}
RxPermissions(this)
.request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.subscribe { granted: Boolean ->
if (granted) {
downloadVedioToCacheFile()
awardVideo()
} else {
showMissingPermissionDialog("存储")
}
}
}
}
}
private fun downloadVedioToCacheFile() {
downloadVedioSucFlag = false
var vedioPath = ""
try {
vedioPath = getExternalFilesDir(null)!!.absolutePath + "/video/"
} catch (e: java.lang.Exception) {
vedioPath = filesDir.absolutePath + "/video/"
}
val vedioName = MD5.GetMD5Code(System.currentTimeMillis().toString() + UserManager.getInstance().userID + videoUrl) + ".mp4"
vedioPathName = vedioPath + vedioName
downloadId = PRDownloader.download(videoUrl, vedioPath, vedioName)
.build()
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
downloadVedioSucFlag = true
}
override fun onError(error: Error) {
}
})
}
private fun initListener() {
ivBack.setOnClickListener(this)
ivSetting.setOnClickListener(this)
ivVedio.setOnClickListener(this)
}
/**
* 获取激励视频
*/
private fun awardVideo() {
if (AppConfig.isVideoSleep) {
showToast("加载失败,请稍后重试。")
return
} else if (videoAdingManager.videoFinishFlag) {
showToast("今日视频已看完,请明天再来吧")
return
}
loadVideoFailCount = 0
showLoading("加载中...")
val bean = VideoAdingBean()
bean.carrierType = Constant.CARRIER_KUYINYUE_VEDIO
loadVideo(videoAdingManager, bean, true)
}
/**
* 加载激励视频
*/
private fun loadVideo(videoAdingManager: VideoAdingManager, bean: VideoAdingBean, isFirstLoad: Boolean) {
videoAdingManager.setVideoAdingListener(object : VideoAdingManager.VideoAdingListener {
override fun videoAdingListenerError(adType: String) {
showToast("加载超时,请休息一下")
hideLoading()
}
override fun videoAdingListenerFail(adType: String) {
loadVideoFailCount++
if (loadVideoFailCount >= 3) {
hideLoading()
showToast("加载失败,请稍后重试!")
} else {
loadVideo(videoAdingManager, bean, false)
}
}
override fun videoAdingListenerSuccess(adType: String) {
hideLoading()
vedioAdingSuccess(adType)
}
})
if (isFirstLoad) {
// 首页按权重加载
videoAdingManager.loadAding(this, bean)
} else {
// 失败按优先级加载
videoAdingManager.loadFailAding(this, bean)
}
}
private fun vedioAdingSuccess(adType: String) {
if (!downloadVedioSucFlag || TextUtils.isEmpty(vedioPathName)) {
showToast("视频处理中,请稍候")
return
}
readyGo()
}
private fun readyGo() {
if (PermissionManager.getInstance().checkEssential(this)) {
VideoDBHelper.getInstance().setSelectVideo(this, VideoDBHelper.UNKNOWN_NUMBER, vedioPathName)
DetailApplyActivity.startSelf(this, vedioPathName, true)
} else {
PermissionActivity.startSelf(this)
}
}
}
package com.wenshu.aiyuebao.ui.fragment
import android.os.Bundle
import androidx.recyclerview.widget.GridLayoutManager
import com.bytedance.sdk.openadsdk.*
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener
import com.scwang.smartrefresh.layout.listener.OnRefreshListener
import com.wenshu.aiyuebao.R
import com.wenshu.aiyuebao.manager.TtCsjAdManager
import com.wenshu.aiyuebao.mvp.model.KylBean
import com.wenshu.aiyuebao.mvp.presenters.KuYinYuePagePresenter
import com.wenshu.aiyuebao.mvp.views.KuYinYuePageView
import com.wenshu.aiyuebao.ui.activitys.KylVideoActivity
import com.wenshu.aiyuebao.ui.adapter.KylPageAdapter
import com.wenshu.aiyuebao.ui.fragment.base.LazyLoadBaseFragment
import com.wenshu.aiyuebao.utils.LogUtil
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener
import com.scwang.smartrefresh.layout.listener.OnRefreshListener
import kotlinx.android.synthetic.main.fragment_main_kyl_page.*
/**
......@@ -63,10 +61,10 @@ class KuYinYuePageFragment(private val targetid: String) : LazyLoadBaseFragment(
override fun onItemClick(position: Int) {
if (kylData != null && kylData.size > 0) {
val bundle = Bundle()
bundle.putString(KylVideoActivity.VIDEO_URL, kylData[position].url)
bundle.putString(KylVideoActivity.VIDEO_ID, kylData[position].vedioId)
readyGo(KylVideoActivity::class.java, bundle)
// val bundle = Bundle()
// bundle.putString(KylVideoActivity.VIDEO_URL, kylData[position].url)
// bundle.putString(KylVideoActivity.VIDEO_ID, kylData[position].vedioId)
// readyGo(KylVideoActivity::class.java, bundle)
}
}
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black">
<com.wenshu.aiyuebao.call.widget.CustomVideoView
android:id="@+id/cvvVedio"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/ivBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginTop="14dp"
android:padding="20dp"
android:src="@mipmap/ic_left_arrow"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/ivVedio"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="@drawable/shape_tv_gold"
android:gravity="center"
android:text="设置视频彩铃"
android:layout_marginBottom="100dp"
app:layout_constraintBottom_toBottomOf="parent"
android:textColor="@color/white" />
<TextView
android:id="@+id/ivSetting"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="@drawable/shape_tv_gold"
android:gravity="center"
android:text="看广告设置来电秀"
android:layout_marginBottom="40dp"
app:layout_constraintBottom_toBottomOf="parent"
android:textColor="@color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment