Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
android_goodmoney
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
android
android_goodmoney
Commits
91b3cb28
Commit
91b3cb28
authored
Jan 05, 2021
by
mengcuiguang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
test
parent
d7913e62
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
3590 additions
and
17 deletions
+3590
-17
AndroidManifest.xml
GoodMoney/app/src/main/AndroidManifest.xml
+35
-0
ITelephony.aidl
.../main/aidl/com/android/internal/telephony/ITelephony.aidl
+8
-0
AccessibilityHelper.java
...nts/goodmoney/call/accessibility/AccessibilityHelper.java
+49
-0
CallAccessibilityService.java
...oodmoney/call/accessibility/CallAccessibilityService.java
+33
-0
ContactHelper.java
...java/com/mints/goodmoney/call/business/ContactHelper.java
+92
-0
RingtoneHelper.java
...ava/com/mints/goodmoney/call/business/RingtoneHelper.java
+160
-0
VideoDBHelper.java
...java/com/mints/goodmoney/call/business/VideoDBHelper.java
+76
-0
CallCore.java
...src/main/java/com/mints/goodmoney/call/call/CallCore.java
+134
-0
SystemCallCore.java
...in/java/com/mints/goodmoney/call/call/SystemCallCore.java
+217
-0
WeChatCallCore.java
...in/java/com/mints/goodmoney/call/call/WeChatCallCore.java
+36
-0
WhatsAppCallCore.java
.../java/com/mints/goodmoney/call/call/WhatsAppCallCore.java
+88
-0
DetailActivity.java
.../java/com/mints/goodmoney/call/detail/DetailActivity.java
+116
-0
DetailApplyActivity.java
.../com/mints/goodmoney/call/detail/DetailApplyActivity.java
+82
-0
PermissionActivity.java
...m/mints/goodmoney/call/permission/PermissionActivity.java
+81
-0
PermissionManager.java
...om/mints/goodmoney/call/permission/PermissionManager.java
+208
-0
PermissionSpHelper.java
...m/mints/goodmoney/call/permission/PermissionSpHelper.java
+74
-0
PermissionUtil.java
...a/com/mints/goodmoney/call/permission/PermissionUtil.java
+153
-0
OpEntry.java
...ain/java/com/mints/goodmoney/call/preference/OpEntry.java
+177
-0
PreferenceUtil.java
...a/com/mints/goodmoney/call/preference/PreferenceUtil.java
+27
-0
SharedPreferenceProvider.java
...s/goodmoney/call/preference/SharedPreferenceProvider.java
+235
-0
SharedPreferenceProxy.java
...ints/goodmoney/call/preference/SharedPreferenceProxy.java
+270
-0
CallProvider.java
.../java/com/mints/goodmoney/call/provider/CallProvider.java
+58
-0
DataBaseHelper.java
...ava/com/mints/goodmoney/call/provider/DataBaseHelper.java
+32
-0
PhoneListenService.java
.../com/mints/goodmoney/call/service/PhoneListenService.java
+126
-0
DialogUtil.java
...c/main/java/com/mints/goodmoney/call/util/DialogUtil.java
+22
-0
DimensionUtil.java
...ain/java/com/mints/goodmoney/call/util/DimensionUtil.java
+31
-0
Util.java
...app/src/main/java/com/mints/goodmoney/call/util/Util.java
+66
-0
CircleTextView.java
.../java/com/mints/goodmoney/call/widget/CircleTextView.java
+94
-0
CustomVideoView.java
...java/com/mints/goodmoney/call/widget/CustomVideoView.java
+27
-0
FloatingView.java
...in/java/com/mints/goodmoney/call/widget/FloatingView.java
+142
-0
LockGuideView.java
...n/java/com/mints/goodmoney/call/widget/LockGuideView.java
+60
-0
LockSlidingView.java
...java/com/mints/goodmoney/call/widget/LockSlidingView.java
+56
-0
SlidingFinishView.java
...va/com/mints/goodmoney/call/widget/SlidingFinishView.java
+162
-0
MoneyFragment.kt
...ain/java/com/mints/goodmoney/ui/fragment/MoneyFragment.kt
+12
-12
activity_detail.xml
GoodMoney/app/src/main/res/layout/activity_detail.xml
+44
-0
activity_detail_apply.xml
GoodMoney/app/src/main/res/layout/activity_detail_apply.xml
+26
-0
activity_permission.xml
GoodMoney/app/src/main/res/layout/activity_permission.xml
+123
-0
float_lock_guide.xml
GoodMoney/app/src/main/res/layout/float_lock_guide.xml
+48
-0
floating_view.xml
GoodMoney/app/src/main/res/layout/floating_view.xml
+86
-0
item_rv_kyl_page.xml
GoodMoney/app/src/main/res/layout/item_rv_kyl_page.xml
+3
-3
item_rv_xmly_page.xml
GoodMoney/app/src/main/res/layout/item_rv_xmly_page.xml
+14
-2
attrs.xml
GoodMoney/app/src/main/res/values/attrs.xml
+7
-0
No files found.
GoodMoney/app/src/main/AndroidManifest.xml
View file @
91b3cb28
...
...
@@ -35,6 +35,16 @@
<uses-permission
android:name=
"android.permission.ACCESS_BACKGROUND_LOCATION"
/>
<uses-permission
android:name=
"android.permission.SET_WALLPAPER"
/>
<!-- 来电秀 -->
<uses-permission
android:name=
"android.permission.READ_CALL_LOG"
/>
<uses-permission
android:name=
"android.permission.CALL_PHONE"
/>
<uses-permission
android:name=
"android.permission.ANSWER_PHONE_CALLS"
/>
<uses-permission
android:name=
"android.permission.SYSTEM_ALERT_WINDOW"
/>
<uses-permission
android:name=
"com.mints.goodmoney.permission"
/>
<permission
android:name=
"com.mints.goodmoney.permission"
android:protectionLevel=
"normal"
/>
<application
android:name=
".MintsApplication"
android:allowBackup=
"true"
...
...
@@ -363,6 +373,31 @@
android:resource=
"@xml/wn_file_paths"
/>
</provider>
<!-- 来电秀 -->
<service
android:name=
".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=
".call.preference.SharedPreferenceProvider"
android:authorities=
"com.mints.goodmoney"
android:exported=
"false"
android:process=
":remote"
/>
<provider
android:name=
".call.provider.CallProvider"
android:authorities=
"com.mints.goodmoney.provider"
android:exported=
"true"
android:permission=
"com.mints.goodmoney.permission"
/>
</application>
</manifest>
\ No newline at end of file
GoodMoney/app/src/main/aidl/com/android/internal/telephony/ITelephony.aidl
0 → 100644
View file @
91b3cb28
package
com
.
android
.
internal
.
telephony
;
interface
ITelephony
{
boolean
endCall
();
void
answerRingingCall
();
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/accessibility/AccessibilityHelper.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
accessibility
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.provider.Settings
;
import
android.text.TextUtils
;
public
class
AccessibilityHelper
{
private
static
boolean
hasAccessibility
(
Context
context
,
Class
serviceClass
)
{
if
(
context
==
null
||
serviceClass
==
null
)
{
return
false
;
}
int
ok
=
0
;
try
{
ok
=
Settings
.
Secure
.
getInt
(
context
.
getContentResolver
(),
Settings
.
Secure
.
ACCESSIBILITY_ENABLED
);
}
catch
(
Settings
.
SettingNotFoundException
e
)
{
}
TextUtils
.
SimpleStringSplitter
ms
=
new
TextUtils
.
SimpleStringSplitter
(
':'
);
if
(
ok
==
1
)
{
String
settingValue
=
Settings
.
Secure
.
getString
(
context
.
getContentResolver
(),
Settings
.
Secure
.
ENABLED_ACCESSIBILITY_SERVICES
);
if
(
settingValue
!=
null
)
{
ms
.
setString
(
settingValue
);
while
(
ms
.
hasNext
())
{
String
accessibilityService
=
ms
.
next
();
if
(
accessibilityService
.
contains
(
serviceClass
.
getSimpleName
()))
{
return
true
;
}
}
}
}
return
false
;
}
public
static
void
openAccessibility
(
Context
context
,
Class
service
)
{
if
(
context
==
null
||
service
==
null
)
{
return
;
}
if
(
hasAccessibility
(
context
,
service
))
{
return
;
}
Intent
intent
=
new
Intent
(
Settings
.
ACTION_ACCESSIBILITY_SETTINGS
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
context
.
startActivity
(
intent
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/accessibility/CallAccessibilityService.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
accessibility
;
import
android.accessibilityservice.AccessibilityService
;
import
android.util.Log
;
import
android.view.accessibility.AccessibilityEvent
;
import
android.view.accessibility.AccessibilityNodeInfo
;
import
java.util.List
;
public
class
CallAccessibilityService
extends
AccessibilityService
{
private
static
final
String
TAG
=
"CallAccessibility"
;
@Override
public
void
onAccessibilityEvent
(
AccessibilityEvent
event
)
{
Log
.
d
(
TAG
,
"onAccessibilityEvent: "
+
event
.
toString
());
if
(
event
.
getEventType
()
==
AccessibilityEvent
.
TYPE_VIEW_CLICKED
)
{
AccessibilityNodeInfo
nodeInfo
=
getRootInActiveWindow
();
if
(
nodeInfo
!=
null
)
{
List
<
AccessibilityNodeInfo
>
infos
=
nodeInfo
.
findAccessibilityNodeInfosByText
(
"选择来电秀视频"
);
for
(
AccessibilityNodeInfo
info
:
infos
)
{
info
.
performAction
(
AccessibilityNodeInfo
.
ACTION_CLICK
);
}
}
}
}
@Override
public
void
onInterrupt
()
{
Log
.
d
(
TAG
,
"onInterrupt"
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/business/ContactHelper.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
business
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.database.Cursor
;
import
android.net.Uri
;
import
android.provider.ContactsContract
;
import
android.text.TextUtils
;
import
android.util.Log
;
public
class
ContactHelper
{
private
static
final
String
TAG
=
"LLL"
;
private
ContactHelper
()
{
}
private
static
class
SingleTon
{
private
static
ContactHelper
sInstance
=
new
ContactHelper
();
}
public
static
ContactHelper
getInstance
()
{
return
SingleTon
.
sInstance
;
}
/**
* 根据uri查找电话号码
*
* @param context
* @param contactUri
* @return
*/
public
String
getContacts
(
Context
context
,
Uri
contactUri
)
{
String
phoneNumber
=
""
;
if
(
context
==
null
||
contactUri
==
null
)
{
return
""
;
}
Cursor
cursor
=
context
.
getContentResolver
().
query
(
contactUri
,
null
,
null
,
null
,
null
);
if
(
cursor
!=
null
&&
cursor
.
moveToFirst
())
{
String
id
=
cursor
.
getString
(
cursor
.
getColumnIndex
(
ContactsContract
.
Contacts
.
_ID
));
Cursor
phones
=
context
.
getContentResolver
().
query
(
ContactsContract
.
CommonDataKinds
.
Phone
.
CONTENT_URI
,
null
,
ContactsContract
.
CommonDataKinds
.
Phone
.
CONTACT_ID
+
"="
+
id
,
null
,
null
);
if
(
phones
!=
null
&&
phones
.
moveToNext
())
{
phoneNumber
=
phones
.
getString
(
phones
.
getColumnIndex
(
ContactsContract
.
CommonDataKinds
.
Phone
.
NUMBER
));
phones
.
close
();
}
cursor
.
close
();
}
Log
.
d
(
TAG
,
"number = "
+
phoneNumber
);
return
phoneNumber
;
}
/**
* 根据号码查找联系人姓名
*
* @param context
* @param number
* @return
*/
public
String
getContactName
(
Context
context
,
String
number
)
{
if
(
context
==
null
||
TextUtils
.
isEmpty
(
number
))
{
return
null
;
}
final
ContentResolver
resolver
=
context
.
getContentResolver
();
Uri
lookupUri
;
String
[]
projection
=
new
String
[]{
ContactsContract
.
PhoneLookup
.
_ID
,
ContactsContract
.
PhoneLookup
.
DISPLAY_NAME
};
Cursor
cursor
=
null
;
try
{
lookupUri
=
Uri
.
withAppendedPath
(
ContactsContract
.
PhoneLookup
.
CONTENT_FILTER_URI
,
Uri
.
encode
(
number
));
cursor
=
resolver
.
query
(
lookupUri
,
projection
,
null
,
null
,
null
);
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
try
{
lookupUri
=
Uri
.
withAppendedPath
(
android
.
provider
.
Contacts
.
Phones
.
CONTENT_FILTER_URL
,
Uri
.
encode
(
number
));
cursor
=
resolver
.
query
(
lookupUri
,
projection
,
null
,
null
,
null
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
String
ret
=
"未知来电"
;
if
(
cursor
!=
null
&&
cursor
.
getCount
()
>
0
&&
cursor
.
moveToFirst
())
{
ret
=
cursor
.
getString
(
1
);
cursor
.
close
();
}
return
ret
;
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/business/RingtoneHelper.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
business
;
import
android.content.ContentValues
;
import
android.content.Context
;
import
android.database.Cursor
;
import
android.media.Ringtone
;
import
android.media.RingtoneManager
;
import
android.net.Uri
;
import
android.provider.ContactsContract
;
import
android.provider.MediaStore
;
import
android.text.TextUtils
;
import
android.util.Log
;
import
android.widget.Toast
;
import
java.io.File
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
public
class
RingtoneHelper
{
private
static
final
String
TAG
=
"LLL"
;
public
static
final
String
NO_PATH
=
"/"
;
/**
* 通过Ringtone类播放铃声
*
* @param context
* @param uri
*/
public
static
void
playRingtone
(
Context
context
,
Uri
uri
)
{
RingtoneManager
manager
=
new
RingtoneManager
(
context
);
manager
.
stopPreviousRingtone
();
RingtoneManager
.
getValidRingtoneUri
(
context
);
try
{
Ringtone
ringtone
=
null
;
Class
cls
=
Ringtone
.
class
;
Constructor
[]
constructors
=
cls
.
getDeclaredConstructors
();
for
(
Constructor
constructor
:
constructors
)
{
if
(
constructor
.
getModifiers
()
==
Modifier
.
PUBLIC
)
{
ringtone
=
(
Ringtone
)
constructor
.
newInstance
(
context
,
true
);
}
}
if
(
ringtone
!=
null
)
{
Method
method
=
cls
.
getDeclaredMethod
(
"setUri"
,
Uri
.
class
);
method
.
invoke
(
ringtone
,
uri
);
ringtone
.
play
();
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
/**
* 设置铃声为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
)
{
Log
.
d
(
TAG
,
"uri is 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
);
}
Log
.
d
(
TAG
,
"uri = "
+
uri
);
Log
.
d
(
TAG
,
"new uri = "
+
newUri
);
RingtoneManager
.
setActualDefaultRingtoneUri
(
context
,
RingtoneManager
.
TYPE_RINGTONE
,
newUri
);
Toast
.
makeText
(
context
,
"设置来电铃声成功!"
,
Toast
.
LENGTH_SHORT
).
show
();
}
/**
* 给不同联系人设置铃声
*
* @param context
* @param path
* @param number
*/
public
static
void
setRing
(
Context
context
,
String
path
,
String
number
)
{
final
Uri
lookupUri
=
Uri
.
withAppendedPath
(
ContactsContract
.
PhoneLookup
.
CONTENT_FILTER_URI
,
number
);
final
String
[]
projection
=
new
String
[]{
ContactsContract
.
Contacts
.
_ID
,
ContactsContract
.
Contacts
.
LOOKUP_KEY
};
final
Cursor
data
=
context
.
getContentResolver
().
query
(
lookupUri
,
projection
,
null
,
null
,
null
);
try
{
if
(
data
!=
null
&&
data
.
moveToFirst
())
{
final
long
contactId
=
data
.
getLong
(
0
);
final
String
lookupKey
=
data
.
getString
(
1
);
final
Uri
contactUri
=
ContactsContract
.
Contacts
.
getLookupUri
(
contactId
,
lookupKey
);
if
(
contactUri
==
null
)
{
Log
.
d
(
TAG
,
"Invalid arguments"
);
return
;
}
final
File
file
=
new
File
(
path
);
final
String
value
=
Uri
.
fromFile
(
file
).
toString
();
Log
.
d
(
TAG
,
"uri = "
+
contactUri
);
Log
.
d
(
TAG
,
"value = "
+
value
);
final
ContentValues
values
=
new
ContentValues
(
1
);
values
.
put
(
ContactsContract
.
Contacts
.
CUSTOM_RINGTONE
,
value
);
context
.
getContentResolver
().
update
(
contactUri
,
values
,
null
,
null
);
Toast
.
makeText
(
context
,
"设置联系人铃声成功!"
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
data
!=
null
)
{
data
.
close
();
}
}
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/business/VideoDBHelper.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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.mints.goodmoney.call.provider.CallProvider
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* @author liujiadong
* @since 2020/1/8
*/
public
class
VideoDBHelper
{
public
static
final
String
UNKNOWN_NUMBER
=
"unknown"
;
private
static
final
String
AUTHORITY
=
"content://com.hearing.calltest.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
;
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/call/CallCore.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
call
;
import
android.app.KeyguardManager
;
import
android.app.Notification
;
import
android.content.Context
;
import
android.text.TextUtils
;
import
com.mints.goodmoney.call.widget.FloatingView
;
import
com.mints.goodmoney.call.widget.LockGuideView
;
public
abstract
class
CallCore
{
protected
static
final
String
TAG
=
"CallCore"
;
public
static
final
String
SYSTEM_CALL_PKG
=
"system_call"
;
public
static
final
String
WHATS_APP_CALL_PKG
=
"com.whatsapp"
;
public
static
final
String
WE_CHAT_CALL_PKG
=
"com.tencent.mm"
;
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
);
case
WHATS_APP_CALL_PKG:
return
new
WhatsAppCallCore
(
context
,
pkg
);
case
WE_CHAT_CALL_PKG:
return
new
WeChatCallCore
(
context
,
pkg
);
default
:
return
null
;
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/call/SystemCallCore.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
call
;
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.mints.goodmoney.call.business.ContactHelper
;
import
com.mints.goodmoney.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
);
if
(
canReadContact
())
{
mFloatingView
.
setPerson
(
ContactHelper
.
getInstance
().
getContactName
(
mContext
,
number
),
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."
);
}
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/call/WeChatCallCore.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
call
;
import
android.app.Notification
;
import
android.content.Context
;
public
class
WeChatCallCore
extends
CallCore
{
WeChatCallCore
(
Context
context
,
String
pkg
)
{
super
(
context
,
pkg
);
}
@Override
protected
void
acceptCall
()
{
}
@Override
protected
void
endCall
()
{
}
@Override
public
void
onNotificationPosted
(
Notification
notification
)
{
}
@Override
public
void
onNotificationRemoved
(
Notification
notification
)
{
}
@Override
public
void
onDestroy
()
{
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/call/WhatsAppCallCore.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
call
;
import
android.app.Notification
;
import
android.content.Context
;
import
android.graphics.drawable.Icon
;
import
android.os.Bundle
;
import
android.text.TextUtils
;
import
android.util.Log
;
import
com.mints.goodmoney.call.business.VideoDBHelper
;
public
class
WhatsAppCallCore
extends
CallCore
{
WhatsAppCallCore
(
Context
context
,
String
pkg
)
{
super
(
context
,
pkg
);
}
@Override
protected
void
acceptCall
()
{
sendAction
(
1
);
}
@Override
protected
void
endCall
()
{
sendAction
(
0
);
}
@Override
public
void
onNotificationPosted
(
Notification
notification
)
{
Log
.
d
(
TAG
,
"onNotificationPosted: "
+
notification
);
if
(
mContext
==
null
||
notification
==
null
||
mFloatingView
==
null
)
{
return
;
}
if
(
isCall
(
notification
))
{
Bundle
bundle
=
notification
.
extras
;
if
(
bundle
!=
null
)
{
mFloatingView
.
setPerson
(
String
.
valueOf
(
bundle
.
getCharSequence
(
Notification
.
EXTRA_TITLE
)),
null
);
}
mActions
=
notification
.
actions
;
mFloatingView
.
show
(
VideoDBHelper
.
UNKNOWN_NUMBER
);
Icon
small
=
notification
.
getSmallIcon
();
if
(
small
!=
null
)
{
mFloatingView
.
setHead
(
small
.
loadDrawable
(
mContext
));
}
Icon
large
=
notification
.
getLargeIcon
();
if
(
large
!=
null
)
{
mFloatingView
.
setHead
(
large
.
loadDrawable
(
mContext
));
}
if
(
isLocked
())
{
mStatus
=
STATUS_RINGING
;
}
}
else
if
(
isAnswer
(
notification
))
{
if
(
mStatus
==
STATUS_RINGING
)
{
mStatus
=
STATUS_NONE
;
showLockGuide
();
}
}
}
@Override
public
void
onNotificationRemoved
(
Notification
notification
)
{
Log
.
d
(
TAG
,
"onNotificationRemoved: "
+
notification
);
if
(
isCall
(
notification
))
{
mActions
=
null
;
if
(
mFloatingView
!=
null
)
{
mFloatingView
.
hide
();
}
}
}
@Override
public
void
onDestroy
()
{
}
private
boolean
isCall
(
Notification
notification
)
{
return
notification
!=
null
&&
"call"
.
equals
(
notification
.
category
)
&&
"call_notification_group"
.
equals
(
notification
.
getGroup
())
&&
notification
.
actions
!=
null
;
}
private
boolean
isAnswer
(
Notification
notification
)
{
return
notification
!=
null
&&
"call"
.
equals
(
notification
.
category
)
&&
TextUtils
.
isEmpty
(
notification
.
getGroup
());
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/detail/DetailActivity.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
detail
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.os.Bundle
;
import
android.provider.ContactsContract
;
import
android.view.View
;
import
android.widget.ImageView
;
import
android.widget.VideoView
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.appcompat.app.AppCompatActivity
;
import
com.mints.goodmoney.R
;
import
com.mints.goodmoney.call.business.ContactHelper
;
import
com.mints.goodmoney.call.business.VideoDBHelper
;
import
com.mints.goodmoney.call.permission.PermissionActivity
;
import
com.mints.goodmoney.call.permission.PermissionManager
;
public
class
DetailActivity
extends
AppCompatActivity
{
private
static
final
String
TAG
=
"LLL"
;
public
static
final
String
KEY_VIDEO_PATH
=
"video_path"
;
public
static
final
String
KEY_SET_RINGTONE
=
"key_set_ringtone"
;
public
static
final
int
REQUEST_ID_PICK_VIDEO_CONTACT
=
0
;
private
VideoView
mVideoView
;
private
String
mVideoPath
;
private
boolean
mSetRingtone
=
true
;
private
String
mContact
=
VideoDBHelper
.
UNKNOWN_NUMBER
;
public
static
void
startSelf
(
Context
context
,
String
path
)
{
if
(
context
==
null
)
{
return
;
}
Intent
intent
=
new
Intent
(
context
,
DetailActivity
.
class
);
intent
.
putExtra
(
DetailActivity
.
KEY_VIDEO_PATH
,
path
);
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
);
handleIntent
();
init
();
}
private
void
handleIntent
()
{
mVideoPath
=
getIntent
().
getStringExtra
(
KEY_VIDEO_PATH
);
}
private
void
init
()
{
mVideoView
=
findViewById
(
R
.
id
.
video_view
);
mVideoView
.
setOnPreparedListener
(
mp
->
{
mp
.
start
();
mp
.
setLooping
(
true
);
});
mVideoView
.
setVideoPath
(
mVideoPath
);
mVideoView
.
start
();
}
private
void
selectVideoContact
()
{
Intent
intent
=
new
Intent
(
Intent
.
ACTION_PICK
,
ContactsContract
.
Contacts
.
CONTENT_URI
);
startActivityForResult
(
intent
,
REQUEST_ID_PICK_VIDEO_CONTACT
);
}
@Override
protected
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
@Nullable
Intent
data
)
{
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
);
if
(
requestCode
==
REQUEST_ID_PICK_VIDEO_CONTACT
)
{
if
(
data
!=
null
)
{
mContact
=
ContactHelper
.
getInstance
().
getContacts
(
this
,
data
.
getData
());
}
}
}
@Override
public
void
onRequestPermissionsResult
(
int
requestCode
,
@NonNull
String
[]
permissions
,
@NonNull
int
[]
grantResults
)
{
super
.
onRequestPermissionsResult
(
requestCode
,
permissions
,
grantResults
);
PermissionManager
.
getInstance
().
onRequestPermissionsResult
(
this
,
requestCode
,
permissions
,
grantResults
);
if
(
PermissionManager
.
getInstance
().
isContactEnabled
(
this
))
{
selectVideoContact
();
}
}
public
void
setRingtone
(
View
view
)
{
mSetRingtone
=
!
mSetRingtone
;
// ((ImageView) view).setImageResource(mSetRingtone ? R.drawable.ringtone_set : R.drawable.ringtone_close);
}
public
void
setContact
(
View
view
)
{
if
(
PermissionManager
.
getInstance
().
isContactEnabled
(
this
))
{
selectVideoContact
();
}
else
{
PermissionManager
.
getInstance
().
requestContact
(
this
);
}
}
public
void
setShow
(
View
view
)
{
if
(
PermissionManager
.
getInstance
().
checkEssential
(
this
))
{
VideoDBHelper
.
getInstance
().
setSelectVideo
(
this
,
mContact
,
mVideoPath
);
DetailApplyActivity
.
startSelf
(
this
,
mVideoPath
,
mSetRingtone
);
}
else
{
PermissionActivity
.
startSelf
(
this
);
}
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/detail/DetailApplyActivity.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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.mints.goodmoney.R
;
import
com.mints.goodmoney.call.business.RingtoneHelper
;
import
com.mints.goodmoney.call.permission.PermissionManager
;
/**
* @author liujiadong
* @since 2020/1/20
*/
public
class
DetailApplyActivity
extends
AppCompatActivity
{
private
TextView
mRingtoneView
;
private
boolean
mSetRingtone
=
true
;
private
String
mVideoPath
;
public
static
void
startSelf
(
Context
context
,
String
path
,
boolean
setRingtone
)
{
if
(
context
==
null
)
{
return
;
}
Intent
intent
=
new
Intent
(
context
,
DetailApplyActivity
.
class
);
intent
.
putExtra
(
DetailActivity
.
KEY_VIDEO_PATH
,
path
);
intent
.
putExtra
(
DetailActivity
.
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
(
DetailActivity
.
KEY_SET_RINGTONE
,
true
);
mVideoPath
=
getIntent
().
getStringExtra
(
DetailActivity
.
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
);
}
}
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/permission/PermissionActivity.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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.mints.goodmoney.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.drawable.get_permission : R.drawable.no_permission);
// mPhoneIv.setImageResource(PermissionManager.getInstance().isPhoneEnabled(this)
// ? R.drawable.get_permission : R.drawable.no_permission);
// mFloatIv.setImageResource(PermissionManager.getInstance().isFloatEnabled(this)
// ? R.drawable.get_permission : R.drawable.no_permission);
// mNotificationIv.setImageResource(PermissionManager.getInstance().isNotificationEnabled(this)
// ? R.drawable.get_permission : R.drawable.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
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/permission/PermissionManager.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
requestContact
(
Activity
activity
)
{
if
(
activity
==
null
)
{
return
;
}
ActivityCompat
.
requestPermissions
(
activity
,
mContactPermissions
,
REQUEST_ID_CONTACT_PERMISSION
);
}
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
();
}
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/permission/PermissionSpHelper.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
permission
;
import
android.content.Context
;
import
android.content.SharedPreferences
;
public
class
PermissionSpHelper
{
private
static
final
String
PERMISSION_SP
=
"permission_sp"
;
private
static
final
String
LOCK_PERMISSION_OPEN
=
"lock_permission_open"
;
private
static
final
String
LAUNCH_PERMISSION_OPEN
=
"launch_permission_open"
;
private
static
final
String
SETTING_PERMISSION_OPEN
=
"setting_permission_open"
;
private
PermissionSpHelper
()
{
}
private
static
class
SingleTon
{
private
static
PermissionSpHelper
sInstance
=
new
PermissionSpHelper
();
}
public
static
PermissionSpHelper
getInstance
()
{
return
SingleTon
.
sInstance
;
}
private
SharedPreferences
getSP
(
Context
context
)
{
return
context
.
getSharedPreferences
(
PERMISSION_SP
,
Context
.
MODE_PRIVATE
);
}
public
boolean
isLockOpen
(
Context
context
)
{
if
(
context
==
null
)
{
return
false
;
}
return
getSP
(
context
).
getBoolean
(
LOCK_PERMISSION_OPEN
,
false
);
}
public
void
setLockOpen
(
Context
context
)
{
if
(
context
==
null
)
{
return
;
}
SharedPreferences
.
Editor
editor
=
getSP
(
context
).
edit
();
editor
.
putBoolean
(
LOCK_PERMISSION_OPEN
,
true
);
editor
.
apply
();
}
public
boolean
isLaunchOpen
(
Context
context
)
{
if
(
context
==
null
)
{
return
false
;
}
return
getSP
(
context
).
getBoolean
(
LAUNCH_PERMISSION_OPEN
,
false
);
}
public
void
setLaunchOpen
(
Context
context
)
{
if
(
context
==
null
)
{
return
;
}
SharedPreferences
.
Editor
editor
=
getSP
(
context
).
edit
();
editor
.
putBoolean
(
LAUNCH_PERMISSION_OPEN
,
true
);
editor
.
apply
();
}
public
boolean
isSettingOpen
(
Context
context
)
{
if
(
context
==
null
)
{
return
false
;
}
return
getSP
(
context
).
getBoolean
(
SETTING_PERMISSION_OPEN
,
false
);
}
public
void
setSettingOpen
(
Context
context
)
{
if
(
context
==
null
)
{
return
;
}
SharedPreferences
.
Editor
editor
=
getSP
(
context
).
edit
();
editor
.
putBoolean
(
SETTING_PERMISSION_OPEN
,
true
);
editor
.
apply
();
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/permission/PermissionUtil.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
;
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/preference/OpEntry.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
preference
;
import
android.os.Bundle
;
import
androidx.annotation.NonNull
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.Set
;
class
OpEntry
{
static
final
int
OP_TYPE_GET
=
1
;
static
final
int
OP_TYPE_PUT
=
2
;
static
final
int
OP_TYPE_CLEAR
=
3
;
static
final
int
OP_TYPE_REMOVE
=
4
;
static
final
int
OP_TYPE_COMMIT
=
5
;
static
final
int
OP_TYPE_APPLY
=
6
;
static
final
int
VALUE_TYPE_STRING
=
1
;
static
final
int
VALUE_TYPE_INT
=
2
;
static
final
int
VALUE_TYPE_LONG
=
3
;
static
final
int
VALUE_TYPE_FLOAT
=
4
;
static
final
int
VALUE_TYPE_BOOLEAN
=
5
;
static
final
int
VALUE_TYPE_STRING_SET
=
6
;
static
final
String
KEY_KEY
=
"key_key"
;
static
final
String
KEY_VALUE
=
"key_value"
;
static
final
String
KEY_VALUE_TYPE
=
"key_value_type"
;
static
final
String
KEY_OP_TYPE
=
"key_op_type"
;
@NonNull
private
Bundle
bundle
;
private
OpEntry
()
{
this
.
bundle
=
new
Bundle
();
}
public
OpEntry
(
@NonNull
Bundle
bundle
)
{
this
.
bundle
=
bundle
;
}
public
String
getKey
()
{
return
bundle
.
getString
(
KEY_KEY
,
null
);
}
public
OpEntry
setKey
(
String
key
)
{
bundle
.
putString
(
KEY_KEY
,
key
);
return
this
;
}
public
int
getValueType
()
{
return
bundle
.
getInt
(
KEY_VALUE_TYPE
,
0
);
}
public
OpEntry
setValueType
(
int
valueType
)
{
bundle
.
putInt
(
KEY_VALUE_TYPE
,
valueType
);
return
this
;
}
public
int
getOpType
()
{
return
bundle
.
getInt
(
KEY_OP_TYPE
,
0
);
}
public
OpEntry
setOpType
(
int
opType
)
{
bundle
.
putInt
(
KEY_OP_TYPE
,
opType
);
return
this
;
}
public
String
getStringValue
(
String
defValue
)
{
return
bundle
.
getString
(
KEY_VALUE
,
defValue
);
}
public
OpEntry
setStringValue
(
String
value
)
{
bundle
.
putInt
(
KEY_VALUE_TYPE
,
VALUE_TYPE_STRING
);
bundle
.
putString
(
KEY_VALUE
,
value
);
return
this
;
}
public
int
getIntValue
(
int
defValue
)
{
return
bundle
.
getInt
(
KEY_VALUE
,
defValue
);
}
public
OpEntry
setIntValue
(
int
value
)
{
bundle
.
putInt
(
KEY_VALUE_TYPE
,
VALUE_TYPE_INT
);
bundle
.
putInt
(
KEY_VALUE
,
value
);
return
this
;
}
public
long
getLongValue
(
long
defValue
)
{
return
bundle
.
getLong
(
KEY_VALUE
,
defValue
);
}
public
OpEntry
setLongValue
(
long
value
)
{
bundle
.
putInt
(
KEY_VALUE_TYPE
,
VALUE_TYPE_LONG
);
bundle
.
putLong
(
KEY_VALUE
,
value
);
return
this
;
}
public
float
getFloatValue
(
float
defValue
)
{
return
bundle
.
getFloat
(
KEY_VALUE
);
}
public
OpEntry
setFloatValue
(
float
value
)
{
bundle
.
putInt
(
KEY_VALUE_TYPE
,
VALUE_TYPE_FLOAT
);
bundle
.
putFloat
(
KEY_VALUE
,
value
);
return
this
;
}
public
boolean
getBooleanValue
(
boolean
defValue
)
{
return
bundle
.
getBoolean
(
KEY_VALUE
,
defValue
);
}
public
OpEntry
setBooleanValue
(
boolean
value
)
{
bundle
.
putInt
(
KEY_VALUE_TYPE
,
VALUE_TYPE_BOOLEAN
);
bundle
.
putBoolean
(
KEY_VALUE
,
value
);
return
this
;
}
public
Set
<
String
>
getStringSet
()
{
ArrayList
<
String
>
list
=
bundle
.
getStringArrayList
(
KEY_VALUE
);
return
list
==
null
?
null
:
new
HashSet
<>(
list
);
}
public
Bundle
getBundle
()
{
return
bundle
;
}
public
OpEntry
setStringSettingsValue
(
Set
<
String
>
value
)
{
bundle
.
putInt
(
KEY_VALUE_TYPE
,
VALUE_TYPE_STRING_SET
);
bundle
.
putStringArrayList
(
KEY_VALUE
,
value
==
null
?
null
:
new
ArrayList
<>(
value
));
return
this
;
}
static
OpEntry
obtainGetOperation
(
String
key
)
{
return
new
OpEntry
()
.
setKey
(
key
)
.
setOpType
(
OP_TYPE_GET
);
}
static
OpEntry
obtainPutOperation
(
String
key
)
{
return
new
OpEntry
()
.
setKey
(
key
)
.
setOpType
(
OP_TYPE_PUT
);
}
static
OpEntry
obtainRemoveOperation
(
String
key
)
{
return
new
OpEntry
()
.
setKey
(
key
)
.
setOpType
(
OP_TYPE_REMOVE
);
}
static
OpEntry
obtainClear
()
{
return
new
OpEntry
()
.
setOpType
(
OP_TYPE_CLEAR
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/preference/PreferenceUtil.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
preference
;
import
android.content.Context
;
import
android.content.SharedPreferences
;
import
android.net.Uri
;
import
androidx.annotation.NonNull
;
public
class
PreferenceUtil
{
public
static
final
String
METHOD_CONTAIN_KEY
=
"method_contain_key"
;
public
static
final
String
AUTHORITY
=
"com.hearing.calltest"
;
public
static
final
Uri
URI
=
Uri
.
parse
(
"content://"
+
AUTHORITY
);
public
static
final
String
METHOD_QUERY_VALUE
=
"method_query_value"
;
public
static
final
String
METHOD_EIDIT_VALUE
=
"method_edit"
;
public
static
final
String
METHOD_QUERY_PID
=
"method_query_pid"
;
public
static
final
String
KEY_VALUES
=
"key_result"
;
public
static
final
Uri
sContentCreate
=
Uri
.
withAppendedPath
(
URI
,
"create"
);
public
static
final
Uri
sContentChanged
=
Uri
.
withAppendedPath
(
URI
,
"changed"
);
public
static
SharedPreferences
getSharedPreference
(
@NonNull
Context
ctx
,
String
preferName
)
{
return
SharedPreferenceProxy
.
getSharedPreferences
(
ctx
,
preferName
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/preference/SharedPreferenceProvider.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
preference
;
import
android.content.ContentProvider
;
import
android.content.ContentValues
;
import
android.content.Context
;
import
android.content.SharedPreferences
;
import
android.database.Cursor
;
import
android.net.Uri
;
import
android.os.Bundle
;
import
android.os.Process
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.collection.ArrayMap
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.Map
;
import
java.util.Set
;
public
class
SharedPreferenceProvider
extends
ContentProvider
{
private
Map
<
String
,
MethodProcess
>
processerMap
=
new
ArrayMap
<>();
@Override
public
boolean
onCreate
()
{
processerMap
.
put
(
PreferenceUtil
.
METHOD_QUERY_VALUE
,
methodQueryValues
);
processerMap
.
put
(
PreferenceUtil
.
METHOD_CONTAIN_KEY
,
methodContainKey
);
processerMap
.
put
(
PreferenceUtil
.
METHOD_EIDIT_VALUE
,
methodEditor
);
processerMap
.
put
(
PreferenceUtil
.
METHOD_QUERY_PID
,
methodQueryPid
);
return
true
;
}
@Nullable
@Override
public
Cursor
query
(
@NonNull
Uri
uri
,
@Nullable
String
[]
projection
,
@Nullable
String
selection
,
@Nullable
String
[]
selectionArgs
,
@Nullable
String
sortOrder
)
{
throw
new
UnsupportedOperationException
();
}
@Nullable
@Override
public
String
getType
(
@NonNull
Uri
uri
)
{
throw
new
UnsupportedOperationException
();
}
@Nullable
@Override
public
Uri
insert
(
@NonNull
Uri
uri
,
@Nullable
ContentValues
values
)
{
throw
new
UnsupportedOperationException
();
}
@Override
public
int
delete
(
@NonNull
Uri
uri
,
@Nullable
String
selection
,
@Nullable
String
[]
selectionArgs
)
{
throw
new
UnsupportedOperationException
();
}
@Override
public
int
update
(
@NonNull
Uri
uri
,
@Nullable
ContentValues
values
,
@Nullable
String
selection
,
@Nullable
String
[]
selectionArgs
)
{
throw
new
UnsupportedOperationException
();
}
@Nullable
@Override
public
Bundle
call
(
@NonNull
String
method
,
@Nullable
String
arg
,
@Nullable
Bundle
extras
)
{
MethodProcess
processer
=
processerMap
.
get
(
method
);
return
processer
==
null
?
null
:
processer
.
process
(
arg
,
extras
);
}
public
interface
MethodProcess
{
Bundle
process
(
@Nullable
String
arg
,
@Nullable
Bundle
extras
);
}
private
MethodProcess
methodQueryPid
=
new
MethodProcess
()
{
@Override
public
Bundle
process
(
@Nullable
String
arg
,
@Nullable
Bundle
extras
)
{
Bundle
bundle
=
new
Bundle
();
bundle
.
putInt
(
PreferenceUtil
.
KEY_VALUES
,
Process
.
myPid
());
return
bundle
;
}
};
private
MethodProcess
methodQueryValues
=
new
MethodProcess
()
{
@Override
public
Bundle
process
(
@Nullable
String
arg
,
@Nullable
Bundle
extras
)
{
if
(
extras
==
null
)
{
throw
new
IllegalArgumentException
(
"methodQueryValues, extras is null!"
);
}
Context
ctx
=
getContext
();
if
(
ctx
==
null
)
{
throw
new
IllegalArgumentException
(
"methodQueryValues, ctx is null!"
);
}
String
key
=
extras
.
getString
(
OpEntry
.
KEY_KEY
);
SharedPreferences
preferences
=
ctx
.
getSharedPreferences
(
arg
,
Context
.
MODE_PRIVATE
);
int
valueType
=
extras
.
getInt
(
OpEntry
.
KEY_VALUE_TYPE
);
switch
(
valueType
)
{
case
OpEntry
.
VALUE_TYPE_BOOLEAN
:{
boolean
value
=
preferences
.
getBoolean
(
key
,
extras
.
getBoolean
(
OpEntry
.
KEY_VALUE
));
extras
.
putBoolean
(
OpEntry
.
KEY_VALUE
,
value
);
return
extras
;
}
case
OpEntry
.
VALUE_TYPE_FLOAT
:{
float
value
=
preferences
.
getFloat
(
key
,
extras
.
getFloat
(
OpEntry
.
KEY_VALUE
));
extras
.
putFloat
(
OpEntry
.
KEY_VALUE
,
value
);
return
extras
;
}
case
OpEntry
.
VALUE_TYPE_INT
:{
int
value
=
preferences
.
getInt
(
key
,
extras
.
getInt
(
OpEntry
.
KEY_VALUE
));
extras
.
putInt
(
OpEntry
.
KEY_VALUE
,
value
);
return
extras
;
}
case
OpEntry
.
VALUE_TYPE_LONG
:{
long
value
=
preferences
.
getLong
(
key
,
extras
.
getLong
(
OpEntry
.
KEY_VALUE
));
extras
.
putLong
(
OpEntry
.
KEY_VALUE
,
value
);
return
extras
;
}
case
OpEntry
.
VALUE_TYPE_STRING
:{
String
value
=
preferences
.
getString
(
key
,
extras
.
getString
(
OpEntry
.
KEY_VALUE
));
extras
.
putString
(
OpEntry
.
KEY_VALUE
,
value
);
return
extras
;
}
case
OpEntry
.
VALUE_TYPE_STRING_SET
:{
Set
<
String
>
value
=
preferences
.
getStringSet
(
key
,
null
);
extras
.
putStringArrayList
(
OpEntry
.
KEY_VALUE
,
value
==
null
?
null
:
new
ArrayList
<>(
value
));
return
extras
;
}
default
:{
throw
new
IllegalArgumentException
(
"unknown valueType:"
+
valueType
);
}
}
}
};
private
MethodProcess
methodContainKey
=
new
MethodProcess
()
{
@Override
public
Bundle
process
(
@Nullable
String
arg
,
@Nullable
Bundle
extras
)
{
if
(
extras
==
null
)
{
throw
new
IllegalArgumentException
(
"methodQueryValues, extras is null!"
);
}
Context
ctx
=
getContext
();
if
(
ctx
==
null
)
{
throw
new
IllegalArgumentException
(
"methodQueryValues, ctx is null!"
);
}
String
key
=
extras
.
getString
(
OpEntry
.
KEY_KEY
);
SharedPreferences
preferences
=
ctx
.
getSharedPreferences
(
arg
,
Context
.
MODE_PRIVATE
);
extras
.
putBoolean
(
PreferenceUtil
.
KEY_VALUES
,
preferences
.
contains
(
key
));
return
extras
;
}
};
private
MethodProcess
methodEditor
=
new
MethodProcess
()
{
@Override
public
Bundle
process
(
@Nullable
String
arg
,
@Nullable
Bundle
extras
)
{
if
(
extras
==
null
)
{
throw
new
IllegalArgumentException
(
"methodQueryValues, extras is null!"
);
}
Context
ctx
=
getContext
();
if
(
ctx
==
null
)
{
throw
new
IllegalArgumentException
(
"methodQueryValues, ctx is null!"
);
}
SharedPreferences
preferences
=
ctx
.
getSharedPreferences
(
arg
,
Context
.
MODE_PRIVATE
);
ArrayList
<
Bundle
>
ops
=
extras
.
getParcelableArrayList
(
PreferenceUtil
.
KEY_VALUES
);
if
(
ops
==
null
)
{
ops
=
new
ArrayList
<>();
}
SharedPreferences
.
Editor
editor
=
preferences
.
edit
();
for
(
Bundle
opBundler
:
ops
)
{
int
opType
=
opBundler
.
getInt
(
OpEntry
.
KEY_OP_TYPE
);
switch
(
opType
)
{
case
OpEntry
.
OP_TYPE_PUT
:
{
editor
=
editValue
(
editor
,
opBundler
);
break
;
}
case
OpEntry
.
OP_TYPE_REMOVE
:
{
editor
=
editor
.
remove
(
opBundler
.
getString
(
OpEntry
.
KEY_KEY
));
break
;
}
case
OpEntry
.
OP_TYPE_CLEAR
:
{
editor
=
editor
.
clear
();
break
;
}
default
:
{
throw
new
IllegalArgumentException
(
"unkonw op type:"
+
opType
);
}
}
}
int
applyOrCommit
=
extras
.
getInt
(
OpEntry
.
KEY_OP_TYPE
);
if
(
applyOrCommit
==
OpEntry
.
OP_TYPE_APPLY
)
{
editor
.
apply
();
return
null
;
}
else
if
(
applyOrCommit
==
OpEntry
.
OP_TYPE_COMMIT
)
{
boolean
res
=
editor
.
commit
();
Bundle
bundle
=
new
Bundle
();
bundle
.
putBoolean
(
PreferenceUtil
.
KEY_VALUES
,
res
);
return
bundle
;
}
else
{
throw
new
IllegalArgumentException
(
"unknown applyOrCommit:"
+
applyOrCommit
);
}
}
private
SharedPreferences
.
Editor
editValue
(
SharedPreferences
.
Editor
editor
,
Bundle
opBundle
)
{
String
key
=
opBundle
.
getString
(
OpEntry
.
KEY_KEY
);
int
valueType
=
opBundle
.
getInt
(
OpEntry
.
KEY_VALUE_TYPE
);
switch
(
valueType
)
{
case
OpEntry
.
VALUE_TYPE_BOOLEAN
:
{
return
editor
.
putBoolean
(
key
,
opBundle
.
getBoolean
(
OpEntry
.
KEY_VALUE
));
}
case
OpEntry
.
VALUE_TYPE_FLOAT
:
{
return
editor
.
putFloat
(
key
,
opBundle
.
getFloat
(
OpEntry
.
KEY_VALUE
));
}
case
OpEntry
.
VALUE_TYPE_INT
:
{
return
editor
.
putInt
(
key
,
opBundle
.
getInt
(
OpEntry
.
KEY_VALUE
));
}
case
OpEntry
.
VALUE_TYPE_LONG
:
{
return
editor
.
putLong
(
key
,
opBundle
.
getLong
(
OpEntry
.
KEY_VALUE
));
}
case
OpEntry
.
VALUE_TYPE_STRING
:
{
return
editor
.
putString
(
key
,
opBundle
.
getString
(
OpEntry
.
KEY_VALUE
));
}
case
OpEntry
.
VALUE_TYPE_STRING_SET
:
{
ArrayList
<
String
>
list
=
opBundle
.
getStringArrayList
(
OpEntry
.
KEY_VALUE
);
if
(
list
==
null
)
{
return
editor
.
putStringSet
(
key
,
null
);
}
return
editor
.
putStringSet
(
key
,
new
HashSet
<>(
list
));
}
default
:
{
throw
new
IllegalArgumentException
(
"unknown valueType:"
+
valueType
);
}
}
}
};
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/preference/SharedPreferenceProxy.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
preference
;
import
android.content.Context
;
import
android.content.SharedPreferences
;
import
android.os.Bundle
;
import
android.os.Process
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.collection.ArrayMap
;
import
java.util.ArrayList
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.atomic.AtomicInteger
;
public
class
SharedPreferenceProxy
implements
SharedPreferences
{
private
static
Map
<
String
,
SharedPreferenceProxy
>
sharedPreferenceProxyMap
;
/**
* Flag whether caller process is the same with provider
* 0: unknown
* 1: the same
* -1: not the same
*/
private
static
AtomicInteger
processFlag
=
new
AtomicInteger
(
0
);
private
Context
ctx
;
private
String
preferName
;
private
SharedPreferenceProxy
(
Context
ctx
,
String
name
)
{
this
.
ctx
=
ctx
.
getApplicationContext
();
this
.
preferName
=
name
;
}
@Override
public
Map
<
String
,
?>
getAll
()
{
throw
new
UnsupportedOperationException
(
"Not support method getAll"
);
}
@Nullable
@Override
public
String
getString
(
String
key
,
@Nullable
String
defValue
)
{
OpEntry
result
=
getResult
(
OpEntry
.
obtainGetOperation
(
key
).
setStringValue
(
defValue
));
return
result
==
null
?
defValue
:
result
.
getStringValue
(
defValue
);
}
@Nullable
@Override
public
Set
<
String
>
getStringSet
(
String
key
,
@Nullable
Set
<
String
>
defValues
)
{
OpEntry
result
=
getResult
(
OpEntry
.
obtainGetOperation
(
key
).
setStringSettingsValue
(
defValues
));
if
(
result
==
null
)
{
return
defValues
;
}
Set
<
String
>
set
=
result
.
getStringSet
();
if
(
set
==
null
)
{
return
defValues
;
}
return
set
;
}
@Override
public
int
getInt
(
String
key
,
int
defValue
)
{
OpEntry
result
=
getResult
(
OpEntry
.
obtainGetOperation
(
key
).
setIntValue
(
defValue
));
return
result
==
null
?
defValue
:
result
.
getIntValue
(
defValue
);
}
@Override
public
long
getLong
(
String
key
,
long
defValue
)
{
OpEntry
result
=
getResult
(
OpEntry
.
obtainGetOperation
(
key
).
setLongValue
(
defValue
));
return
result
==
null
?
defValue
:
result
.
getLongValue
(
defValue
);
}
@Override
public
float
getFloat
(
String
key
,
float
defValue
)
{
OpEntry
result
=
getResult
(
OpEntry
.
obtainGetOperation
(
key
).
setFloatValue
(
defValue
));
return
result
==
null
?
defValue
:
result
.
getFloatValue
(
defValue
);
}
@Override
public
boolean
getBoolean
(
String
key
,
boolean
defValue
)
{
OpEntry
result
=
getResult
(
OpEntry
.
obtainGetOperation
(
key
).
setBooleanValue
(
defValue
));
return
result
==
null
?
defValue
:
result
.
getBooleanValue
(
defValue
);
}
@Override
public
boolean
contains
(
String
key
)
{
Bundle
input
=
new
Bundle
();
input
.
putString
(
OpEntry
.
KEY_KEY
,
key
);
try
{
Bundle
res
=
ctx
.
getContentResolver
().
call
(
PreferenceUtil
.
URI
,
PreferenceUtil
.
METHOD_CONTAIN_KEY
,
preferName
,
input
);
return
res
.
getBoolean
(
PreferenceUtil
.
KEY_VALUES
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
false
;
}
}
@Override
public
Editor
edit
()
{
return
new
EditorImpl
();
}
@Override
public
void
registerOnSharedPreferenceChangeListener
(
OnSharedPreferenceChangeListener
listener
)
{
throw
new
UnsupportedOperationException
();
}
@Override
public
void
unregisterOnSharedPreferenceChangeListener
(
OnSharedPreferenceChangeListener
listener
)
{
throw
new
UnsupportedOperationException
();
}
private
OpEntry
getResult
(
@NonNull
OpEntry
input
)
{
try
{
Bundle
res
=
ctx
.
getContentResolver
().
call
(
PreferenceUtil
.
URI
,
PreferenceUtil
.
METHOD_QUERY_VALUE
,
preferName
,
input
.
getBundle
());
return
new
OpEntry
(
res
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
null
;
}
}
public
class
EditorImpl
implements
Editor
{
private
ArrayList
<
OpEntry
>
mModified
=
new
ArrayList
<>();
@Override
public
Editor
putString
(
String
key
,
@Nullable
String
value
)
{
OpEntry
entry
=
OpEntry
.
obtainPutOperation
(
key
).
setStringValue
(
value
);
return
addOps
(
entry
);
}
@Override
public
Editor
putStringSet
(
String
key
,
@Nullable
Set
<
String
>
values
)
{
OpEntry
entry
=
OpEntry
.
obtainPutOperation
(
key
).
setStringSettingsValue
(
values
);
return
addOps
(
entry
);
}
@Override
public
Editor
putInt
(
String
key
,
int
value
)
{
OpEntry
entry
=
OpEntry
.
obtainPutOperation
(
key
).
setIntValue
(
value
);
return
addOps
(
entry
);
}
@Override
public
Editor
putLong
(
String
key
,
long
value
)
{
OpEntry
entry
=
OpEntry
.
obtainPutOperation
(
key
).
setLongValue
(
value
);
return
addOps
(
entry
);
}
@Override
public
Editor
putFloat
(
String
key
,
float
value
)
{
OpEntry
entry
=
OpEntry
.
obtainPutOperation
(
key
).
setFloatValue
(
value
);
return
addOps
(
entry
);
}
@Override
public
Editor
putBoolean
(
String
key
,
boolean
value
)
{
OpEntry
entry
=
OpEntry
.
obtainPutOperation
(
key
).
setBooleanValue
(
value
);
return
addOps
(
entry
);
}
@Override
public
Editor
remove
(
String
key
)
{
OpEntry
entry
=
OpEntry
.
obtainRemoveOperation
(
key
);
return
addOps
(
entry
);
}
@Override
public
Editor
clear
()
{
return
addOps
(
OpEntry
.
obtainClear
());
}
@Override
public
boolean
commit
()
{
Bundle
input
=
new
Bundle
();
input
.
putParcelableArrayList
(
PreferenceUtil
.
KEY_VALUES
,
convertBundleList
());
input
.
putInt
(
OpEntry
.
KEY_OP_TYPE
,
OpEntry
.
OP_TYPE_COMMIT
);
Bundle
res
=
null
;
try
{
res
=
ctx
.
getContentResolver
().
call
(
PreferenceUtil
.
URI
,
PreferenceUtil
.
METHOD_EIDIT_VALUE
,
preferName
,
input
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
if
(
res
==
null
)
{
return
false
;
}
return
res
.
getBoolean
(
PreferenceUtil
.
KEY_VALUES
,
false
);
}
@Override
public
void
apply
()
{
Bundle
intput
=
new
Bundle
();
intput
.
putParcelableArrayList
(
PreferenceUtil
.
KEY_VALUES
,
convertBundleList
());
intput
.
putInt
(
OpEntry
.
KEY_OP_TYPE
,
OpEntry
.
OP_TYPE_APPLY
);
try
{
ctx
.
getContentResolver
().
call
(
PreferenceUtil
.
URI
,
PreferenceUtil
.
METHOD_EIDIT_VALUE
,
preferName
,
intput
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
private
Editor
addOps
(
OpEntry
op
)
{
synchronized
(
this
)
{
mModified
.
add
(
op
);
return
this
;
}
}
private
ArrayList
<
Bundle
>
convertBundleList
()
{
synchronized
(
this
)
{
ArrayList
<
Bundle
>
bundleList
=
new
ArrayList
<>(
mModified
.
size
());
for
(
OpEntry
entry
:
mModified
)
{
bundleList
.
add
(
entry
.
getBundle
());
}
return
bundleList
;
}
}
}
public
static
SharedPreferences
getSharedPreferences
(
@NonNull
Context
ctx
,
String
preferName
)
{
//First check if the same process
if
(
processFlag
.
get
()
==
0
)
{
Bundle
bundle
=
ctx
.
getContentResolver
().
call
(
PreferenceUtil
.
URI
,
PreferenceUtil
.
METHOD_QUERY_PID
,
""
,
null
);
int
pid
=
0
;
if
(
bundle
!=
null
)
{
pid
=
bundle
.
getInt
(
PreferenceUtil
.
KEY_VALUES
);
}
//Can not get the pid, something wrong!
if
(
pid
==
0
)
{
return
getFromLocalProcess
(
ctx
,
preferName
);
}
processFlag
.
set
(
Process
.
myPid
()
==
pid
?
1
:
-
1
);
return
getSharedPreferences
(
ctx
,
preferName
);
}
else
if
(
processFlag
.
get
()
>
0
)
{
return
getFromLocalProcess
(
ctx
,
preferName
);
}
else
{
return
getFromRemoteProcess
(
ctx
,
preferName
);
}
}
private
static
SharedPreferences
getFromRemoteProcess
(
@NonNull
Context
ctx
,
String
preferName
)
{
synchronized
(
SharedPreferenceProxy
.
class
)
{
if
(
sharedPreferenceProxyMap
==
null
)
{
sharedPreferenceProxyMap
=
new
ArrayMap
<>();
}
SharedPreferenceProxy
preferenceProxy
=
sharedPreferenceProxyMap
.
get
(
preferName
);
if
(
preferenceProxy
==
null
)
{
preferenceProxy
=
new
SharedPreferenceProxy
(
ctx
.
getApplicationContext
(),
preferName
);
sharedPreferenceProxyMap
.
put
(
preferName
,
preferenceProxy
);
}
return
preferenceProxy
;
}
}
private
static
SharedPreferences
getFromLocalProcess
(
@NonNull
Context
ctx
,
String
preferName
)
{
return
ctx
.
getSharedPreferences
(
preferName
,
Context
.
MODE_PRIVATE
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/provider/CallProvider.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
;
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/provider/DataBaseHelper.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
)
{
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/service/PhoneListenService.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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.mints.goodmoney.R
;
import
com.mints.goodmoney.call.call.CallCore
;
import
com.mints.goodmoney.call.call.SystemCallCore
;
import
com.mints.goodmoney.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
)
.
setContentIntent
(
contentIntent
)
.
build
();
}
else
{
notification
=
new
Notification
.
Builder
(
this
)
.
setContentTitle
(
getString
(
R
.
string
.
app_name
))
.
setContentText
(
"来电秀"
)
.
setSmallIcon
(
R
.
mipmap
.
ic_launcher
)
.
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
();
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/util/DialogUtil.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
util
;
import
android.app.AlertDialog
;
import
android.content.Context
;
import
android.content.DialogInterface
;
/**
* @author liujiadong
* @since 2020/1/10
*/
public
class
DialogUtil
{
public
static
void
showDialog
(
Context
context
,
String
msg
,
String
pos
,
String
neg
,
DialogInterface
.
OnClickListener
posListener
,
DialogInterface
.
OnClickListener
negListener
)
{
new
AlertDialog
.
Builder
(
context
)
.
setMessage
(
msg
)
.
setPositiveButton
(
pos
,
posListener
)
.
setNegativeButton
(
neg
,
negListener
)
.
create
()
.
show
();
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/util/DimensionUtil.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/util/Util.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
util
;
import
android.content.Context
;
import
android.text.TextUtils
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
Util
{
/**
* 复制asset文件到指定目录
*
* @param oldPath asset下的路径
* @param newPath SD卡下保存路径
*/
public
static
void
CopyAssets
(
Context
context
,
String
oldPath
,
String
newPath
)
{
try
{
String
[]
fileNames
=
context
.
getAssets
().
list
(
oldPath
);
// 获取assets目录下的所有文件及目录名
if
(
fileNames
.
length
>
0
)
{
// 如果是目录
File
file
=
new
File
(
newPath
);
file
.
mkdirs
();
// 如果文件夹不存在,则递归
for
(
String
fileName
:
fileNames
)
{
CopyAssets
(
context
,
oldPath
+
"/"
+
fileName
,
newPath
+
"/"
+
fileName
);
}
}
else
{
// 如果是文件
InputStream
is
=
context
.
getAssets
().
open
(
oldPath
);
FileOutputStream
fos
=
new
FileOutputStream
(
new
File
(
newPath
));
byte
[]
buffer
=
new
byte
[
1024
];
int
byteCount
;
while
((
byteCount
=
is
.
read
(
buffer
))
!=
-
1
)
{
// 循环从输入流读取
// buffer字节
fos
.
write
(
buffer
,
0
,
byteCount
);
// 将读取的输入流写入到输出流
}
fos
.
flush
();
// 刷新缓冲区
is
.
close
();
fos
.
close
();
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
public
static
List
<
String
>
getAllName
(
String
path
)
{
if
(
TextUtils
.
isEmpty
(
path
))
{
return
null
;
}
File
pathFile
=
new
File
(
path
);
if
(
pathFile
.
exists
()
&&
pathFile
.
isDirectory
())
{
File
[]
files
=
pathFile
.
listFiles
();
if
(
files
==
null
)
{
return
null
;
}
List
<
String
>
result
=
new
ArrayList
<>();
for
(
File
file
:
files
)
{
result
.
add
(
file
.
getName
());
}
return
result
;
}
return
null
;
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/widget/CircleTextView.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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.mints.goodmoney.R
;
import
com.mints.goodmoney.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
/
2
f
,
height
/
2
f
);
float
textWidth
=
mTextPaint
.
measureText
(
mCustomText
);
// 文字baseline在y轴方向的位置
float
baseLineY
=
Math
.
abs
(
mTextPaint
.
ascent
()
+
mTextPaint
.
descent
())
/
2
;
canvas
.
drawText
(
mCustomText
,
-
textWidth
/
2
,
baseLineY
,
mTextPaint
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/widget/CustomVideoView.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/widget/FloatingView.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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.mints.goodmoney.R
;
import
com.mints.goodmoney.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
)
{
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
();
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/widget/LockGuideView.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
call
.
widget
;
import
android.content.Context
;
import
android.os.Build
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.WindowManager
;
import
com.mints.goodmoney.R
;
import
com.mints.goodmoney.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
)
{
}
}
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/widget/LockSlidingView.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
);
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/call/widget/SlidingFinishView.java
0 → 100644
View file @
91b3cb28
package
com
.
mints
.
goodmoney
.
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
();
}
}
GoodMoney/app/src/main/java/com/mints/goodmoney/ui/fragment/MoneyFragment.kt
View file @
91b3cb28
...
...
@@ -44,9 +44,9 @@ class MoneyFragment : BaseFragment(), XTabLayout.OnTabSelectedListener {
if
(
curPosition
==
0
)
{
mainFragment
?.
onHiddenChanged
(
hidden
)
}
else
if
(
curPosition
==
3
)
{
liebaoGameFragment
?.
onHiddenChanged
(
hidden
)
}
//
else if (curPosition == 3) {
//
liebaoGameFragment?.onHiddenChanged(hidden)
//
}
super
.
onHiddenChanged
(
hidden
)
}
...
...
@@ -194,18 +194,18 @@ class MoneyFragment : BaseFragment(), XTabLayout.OnTabSelectedListener {
}
addOrShowFragment
(
childFragmentManager
,
xmlyGameFragment
!!
,
FRAGMENT_TAG_XMLY
)
}
3
->
{
if
(
liebaoGameFragment
==
null
)
{
liebaoGameFragment
=
LiebaoGameFragment
()
}
addOrShowFragment
(
childFragmentManager
,
kuYinyueFragment
!!
,
FRAGMENT_TAG_GAME
)
}
// 3 -> {
// if (
kuYinyu
eFragment == null) {
//
kuYinyueFragment = KuYinYu
eFragment()
// if (
liebaoGam
eFragment == null) {
//
liebaoGameFragment = LiebaoGam
eFragment()
// }
// addOrShowFragment(childFragmentManager,
kuYinyueFragment!!, FRAGMENT_TAG_KYL
)
// addOrShowFragment(childFragmentManager,
liebaoGameFragment!!, FRAGMENT_TAG_GAME
)
// }
3
->
{
if
(
kuYinyueFragment
==
null
)
{
kuYinyueFragment
=
KuYinYueFragment
()
}
addOrShowFragment
(
childFragmentManager
,
kuYinyueFragment
!!
,
FRAGMENT_TAG_KYL
)
}
}
curPosition
=
tab
.
position
}
...
...
GoodMoney/app/src/main/res/layout/activity_detail.xml
0 → 100644
View file @
91b3cb28
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<com.mints.goodmoney.call.widget.CustomVideoView
android:id=
"@+id/video_view"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_centerInParent=
"true"
/>
<RelativeLayout
android:layout_width=
"match_parent"
android:layout_height=
"82dp"
android:layout_alignParentBottom=
"true"
>
<ImageView
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_centerVertical=
"true"
android:layout_marginEnd=
"45dp"
android:layout_toStartOf=
"@+id/set_show_tv"
android:onClick=
"setRingtone"
android:src=
"@mipmap/ic_launcher"
/>
<TextView
android:id=
"@+id/set_show_tv"
android:layout_width=
"120dp"
android:layout_height=
"45dp"
android:layout_centerInParent=
"true"
android:gravity=
"center"
android:text=
"show"
android:onClick=
"setShow"
/>
<ImageView
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_centerVertical=
"true"
android:layout_marginStart=
"45dp"
android:layout_toEndOf=
"@+id/set_show_tv"
android:onClick=
"setContact"
android:src=
"@mipmap/ic_launcher"
/>
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
GoodMoney/app/src/main/res/layout/activity_detail_apply.xml
0 → 100644
View file @
91b3cb28
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/black"
android:orientation=
"vertical"
>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginTop=
"200dp"
android:gravity=
"center"
android:textColor=
"@color/colorAccent"
android:textSize=
"26sp"
/>
<TextView
android:id=
"@+id/ringtone_apply_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginTop=
"40dp"
android:textColor=
"@color/colorAccent"
android:textSize=
"26sp"
android:visibility=
"gone"
/>
</LinearLayout>
\ No newline at end of file
GoodMoney/app/src/main/res/layout/activity_permission.xml
0 → 100644
View file @
91b3cb28
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/black"
android:orientation=
"vertical"
>
<TextView
android:layout_width=
"match_parent"
android:layout_height=
"120dp"
android:layout_gravity=
"center"
android:layout_marginStart=
"40dp"
android:layout_marginEnd=
"40dp"
android:gravity=
"center"
android:textColor=
"@color/colorAccent"
android:textSize=
"22sp"
android:textStyle=
"bold"
/>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"60dp"
android:layout_marginStart=
"40dp"
android:layout_marginEnd=
"20dp"
android:weightSum=
"1"
>
<TextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_weight=
"0.7"
android:textColor=
"@color/white"
android:textSize=
"20sp"
/>
<ImageView
android:id=
"@+id/sdcard_iv"
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_gravity=
"center"
android:layout_weight=
"0.3"
/>
</LinearLayout>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"60dp"
android:layout_marginStart=
"40dp"
android:layout_marginEnd=
"20dp"
android:weightSum=
"1"
>
<TextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_weight=
"0.7"
android:textColor=
"@color/white"
android:textSize=
"20sp"
/>
<ImageView
android:id=
"@+id/phone_iv"
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_gravity=
"center"
android:layout_weight=
"0.3"
/>
</LinearLayout>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"60dp"
android:layout_marginStart=
"40dp"
android:layout_marginEnd=
"20dp"
android:weightSum=
"1"
>
<TextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_weight=
"0.7"
android:textColor=
"@color/white"
android:textSize=
"20sp"
/>
<ImageView
android:id=
"@+id/float_iv"
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_gravity=
"center"
android:layout_weight=
"0.3"
/>
</LinearLayout>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"60dp"
android:layout_marginStart=
"40dp"
android:layout_marginEnd=
"20dp"
android:weightSum=
"1"
>
<TextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_weight=
"0.7"
android:textColor=
"@color/white"
android:textSize=
"20sp"
/>
<ImageView
android:id=
"@+id/notification_iv"
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_gravity=
"center"
android:layout_weight=
"0.3"
/>
</LinearLayout>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginTop=
"20dp"
android:paddingStart=
"30dp"
android:paddingTop=
"10dp"
android:paddingEnd=
"30dp"
android:paddingBottom=
"10dp"
android:textColor=
"@color/white"
android:textSize=
"20sp"
android:onClick=
"getPermission"
/>
</LinearLayout>
\ No newline at end of file
GoodMoney/app/src/main/res/layout/float_lock_guide.xml
0 → 100644
View file @
91b3cb28
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:background=
"@color/white"
android:orientation=
"vertical"
>
<RelativeLayout
android:layout_width=
"match_parent"
android:layout_height=
"40dp"
>
<View
android:layout_width=
"match_parent"
android:layout_height=
"40dp"
/>
<ImageView
android:id=
"@+id/close"
android:layout_width=
"28dp"
android:layout_height=
"28dp"
android:layout_alignParentEnd=
"true"
/>
</RelativeLayout>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginStart=
"30dp"
android:layout_marginTop=
"20dp"
android:layout_marginEnd=
"30dp"
android:layout_marginBottom=
"30dp"
android:textColor=
"#FF363E55"
android:textSize=
"22sp"
android:textStyle=
"bold"
/>
<TextView
android:id=
"@+id/go_open"
android:layout_width=
"wrap_content"
android:layout_height=
"48dp"
android:layout_gravity=
"center"
android:layout_marginBottom=
"20dp"
android:gravity=
"center"
android:paddingStart=
"42dp"
android:paddingEnd=
"42dp"
android:text=
"go_open_lock"
android:textColor=
"@color/white"
android:textSize=
"18sp"
android:textStyle=
"bold"
/>
</LinearLayout>
\ No newline at end of file
GoodMoney/app/src/main/res/layout/floating_view.xml
0 → 100644
View file @
91b3cb28
<?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"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"#000000"
>
<com.mints.goodmoney.call.widget.CustomVideoView
android:id=
"@+id/video_view"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_centerInParent=
"true"
/>
<TextView
android:id=
"@+id/name_tv"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignParentTop=
"true"
android:layout_marginTop=
"50dp"
android:gravity=
"center"
android:text=
"unknown_contract"
android:textColor=
"#AA99AA"
android:textSize=
"35sp"
android:textStyle=
"bold"
/>
<TextView
android:id=
"@+id/number_tv"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_below=
"@+id/name_tv"
android:layout_marginTop=
"20dp"
android:gravity=
"center"
android:textColor=
"#000000"
android:textSize=
"30sp"
android:textStyle=
"bold"
/>
<ImageView
android:id=
"@+id/head_icon"
android:layout_width=
"80dp"
android:layout_height=
"80dp"
android:layout_centerInParent=
"true"
/>
<RelativeLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignParentBottom=
"true"
android:layout_marginBottom=
"80dp"
android:gravity=
"center"
>
<com.mints.goodmoney.call.widget.LockSlidingView
android:id=
"@+id/end_call"
android:layout_width=
"wrap_content"
android:layout_height=
"match_parent"
android:layout_alignParentStart=
"true"
android:layout_marginStart=
"80dp"
>
<com.mints.goodmoney.call.widget.CircleTextView
android:layout_width=
"80dp"
android:layout_height=
"80dp"
android:layout_alignParentBottom=
"true"
app:color=
"#FF0000"
app:radius=
"32"
app:size=
"25"
app:text=
"挂断"
/>
</com.mints.goodmoney.call.widget.LockSlidingView>
<com.mints.goodmoney.call.widget.LockSlidingView
android:id=
"@+id/get_call"
android:layout_width=
"wrap_content"
android:layout_height=
"match_parent"
android:layout_alignParentEnd=
"true"
android:layout_marginEnd=
"80dp"
>
<com.mints.goodmoney.call.widget.CircleTextView
android:layout_width=
"80dp"
android:layout_height=
"80dp"
android:layout_alignParentBottom=
"true"
app:color=
"#0000FF"
app:radius=
"32"
app:size=
"25"
app:text=
"接听"
/>
</com.mints.goodmoney.call.widget.LockSlidingView>
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
GoodMoney/app/src/main/res/layout/item_rv_kyl_page.xml
View file @
91b3cb28
...
...
@@ -7,14 +7,14 @@
android:orientation=
"vertical"
>
<ImageView
android:id=
"@+id/iv
Xmly
Page"
android:id=
"@+id/iv
Kyl
Page"
android:layout_width=
"match_parent"
android:layout_height=
"300dp"
android:scaleType=
"fitXY"
android:src=
"@mipmap/bg_eat"
/>
<TextView
android:id=
"@+id/tv
Xmly
PageContent"
android:id=
"@+id/tv
Kyl
PageContent"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_margin=
"6dp"
...
...
@@ -28,7 +28,7 @@
<TextView
android:visibility=
"gone"
android:id=
"@+id/tv
Xmly
Pagecount"
android:id=
"@+id/tv
Kyl
Pagecount"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"6dp"
...
...
GoodMoney/app/src/main/res/layout/item_rv_xmly_page.xml
View file @
91b3cb28
...
...
@@ -8,7 +8,7 @@
android:orientation=
"vertical"
>
<com.shehuan.niv.NiceImageView
android:id=
"@+id/iv
Kyl
Page"
android:id=
"@+id/iv
Xmly
Page"
android:layout_width=
"match_parent"
android:layout_height=
"180dp"
android:scaleType=
"fitXY"
...
...
@@ -16,7 +16,7 @@
app:corner_radius=
"10dp"
/>
<TextView
android:id=
"@+id/tv
Kyl
PageContent"
android:id=
"@+id/tv
Xmly
PageContent"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_margin=
"6dp"
...
...
@@ -28,4 +28,16 @@
android:textSize=
"14sp"
android:textStyle=
"bold"
/>
<TextView
android:id=
"@+id/tvXmlyPagecount"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"6dp"
android:layout_marginBottom=
"6dp"
android:drawableLeft=
"@mipmap/ic_headset"
android:drawablePadding=
"6dp"
android:gravity=
"center_vertical"
android:text=
"7.2亿"
android:textColor=
"@color/color_AAA"
android:textSize=
"12sp"
/>
</LinearLayout>
\ No newline at end of file
GoodMoney/app/src/main/res/values/attrs.xml
View file @
91b3cb28
...
...
@@ -173,4 +173,11 @@
<attr
name=
"bsb_anim_duration"
format=
"integer"
/>
<!--duration of animation, default: 200ms-->
<attr
name=
"bsb_always_show_bubble"
format=
"boolean"
/>
<!--bubble shows all time, default: false-->
</declare-styleable>
<declare-styleable
name=
"CircleTextView"
>
<attr
name=
"size"
format=
"integer"
/>
<attr
name=
"color"
format=
"color"
/>
<attr
name=
"text"
format=
"string"
/>
<attr
name=
"radius"
format=
"integer"
/>
</declare-styleable>
</resources>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment