Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
com.ccwangluo.accelerator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sheteng
com.ccwangluo.accelerator
Commits
08b2b87c
Commit
08b2b87c
authored
Jan 11, 2020
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial changes to subscriptions
parent
5b018c97
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
64 additions
and
54 deletions
+64
-54
core/src/main/java/com/github/shadowsocks/database/Profile.kt
.../src/main/java/com/github/shadowsocks/database/Profile.kt
+7
-2
core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt
...in/java/com/github/shadowsocks/database/ProfileManager.kt
+44
-29
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
+6
-2
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
.../src/main/java/com/github/shadowsocks/ProfilesFragment.kt
+2
-2
mobile/src/main/java/com/github/shadowsocks/UdpFallbackProfileActivity.kt
...java/com/github/shadowsocks/UdpFallbackProfileActivity.kt
+1
-1
mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt
...m/github/shadowsocks/subscription/SubscriptionFragment.kt
+1
-15
mobile/src/main/java/com/github/shadowsocks/tasker/ConfigActivity.kt
...main/java/com/github/shadowsocks/tasker/ConfigActivity.kt
+1
-1
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
.../java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
+1
-1
tv/src/main/java/com/github/shadowsocks/tv/ProfilesDialogFragment.kt
.../java/com/github/shadowsocks/tv/ProfilesDialogFragment.kt
+1
-1
No files found.
core/src/main/java/com/github/shadowsocks/database/Profile.kt
View file @
08b2b87c
...
@@ -53,10 +53,12 @@ data class Profile(
...
@@ -53,10 +53,12 @@ data class Profile(
// user configurable fields
// user configurable fields
var
name
:
String
?
=
""
,
var
name
:
String
?
=
""
,
var
host
:
String
=
sponsored
,
var
host
:
String
=
sponsored
,
var
remotePort
:
Int
=
8388
,
var
remotePort
:
Int
=
8388
,
var
password
:
String
=
"u1rRWTssNv0p"
,
var
password
:
String
=
"u1rRWTssNv0p"
,
var
method
:
String
=
"aes-256-cfb"
,
var
method
:
String
=
"aes-256-cfb"
,
var
route
:
String
=
"all"
,
var
route
:
String
=
"all"
,
var
remoteDns
:
String
=
"dns.google"
,
var
remoteDns
:
String
=
"dns.google"
,
var
proxyApps
:
Boolean
=
false
,
var
proxyApps
:
Boolean
=
false
,
...
@@ -252,8 +254,11 @@ data class Profile(
...
@@ -252,8 +254,11 @@ data class Profile(
@Query
(
"SELECT * FROM `Profile` WHERE `id` = :id"
)
@Query
(
"SELECT * FROM `Profile` WHERE `id` = :id"
)
operator
fun
get
(
id
:
Long
):
Profile
?
operator
fun
get
(
id
:
Long
):
Profile
?
@Query
(
"SELECT * FROM `Profile` ORDER BY `userOrder`"
)
@Query
(
"SELECT * FROM `Profile` WHERE `Subscription` != 2 ORDER BY `userOrder`"
)
fun
list
():
List
<
Profile
>
fun
listActive
():
List
<
Profile
>
@Query
(
"SELECT * FROM `Profile`"
)
fun
listAll
():
List
<
Profile
>
@Query
(
"SELECT MAX(`userOrder`) + 1 FROM `Profile`"
)
@Query
(
"SELECT MAX(`userOrder`) + 1 FROM `Profile`"
)
fun
nextOrder
():
Long
?
fun
nextOrder
():
Long
?
...
...
core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt
View file @
08b2b87c
...
@@ -24,9 +24,7 @@ import android.database.sqlite.SQLiteCantOpenDatabaseException
...
@@ -24,9 +24,7 @@ import android.database.sqlite.SQLiteCantOpenDatabaseException
import
android.util.LongSparseArray
import
android.util.LongSparseArray
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.DirectBoot
import
com.github.shadowsocks.utils.*
import
com.github.shadowsocks.utils.forEachTry
import
com.github.shadowsocks.utils.printLog
import
com.google.gson.JsonStreamParser
import
com.google.gson.JsonStreamParser
import
org.json.JSONArray
import
org.json.JSONArray
import
java.io.IOException
import
java.io.IOException
...
@@ -54,38 +52,45 @@ object ProfileManager {
...
@@ -54,38 +52,45 @@ object ProfileManager {
return
profile
return
profile
}
}
fun
createProfilesFromSubscription
(
jsons
:
Sequence
<
InputStream
>,
replace
:
Boolean
,
fun
createProfilesFromSubscription
(
jsons
:
Sequence
<
InputStream
>)
{
oldProfiles
:
List
<
Profile
>?)
{
val
currentId
=
DataStore
.
profileId
val
profiles
=
oldProfiles
?.
associateBy
{
it
.
formattedAddress
}
val
profiles
=
getAllProfiles
()
val
feature
=
profiles
?.
values
?.
singleOrNull
{
it
.
id
==
DataStore
.
profileId
}
val
subscriptions
=
mutableMapOf
<
String
,
Profile
>()
val
lazyClear
=
lazy
{
clear
()
}
val
toUpdate
=
mutableSetOf
<
Long
>()
var
feature
:
Profile
?
=
null
profiles
?.
forEach
{
profile
->
// preprocessing phase
if
(
currentId
==
profile
.
id
)
feature
=
profile
if
(
profile
.
subscription
==
Profile
.
SubscriptionStatus
.
UserConfigured
)
return
@forEach
if
(
subscriptions
.
putIfAbsentCompat
(
profile
.
formattedAddress
,
profile
)
!=
null
)
{
delProfile
(
profile
.
id
)
if
(
currentId
==
profile
.
id
)
DataStore
.
profileId
=
0
}
else
if
(
profile
.
subscription
==
Profile
.
SubscriptionStatus
.
Active
)
{
toUpdate
.
add
(
profile
.
id
)
profile
.
subscription
=
Profile
.
SubscriptionStatus
.
Obsolete
}
}
jsons
.
asIterable
().
forEachTry
{
json
->
jsons
.
asIterable
().
forEachTry
{
json
->
Profile
.
parseJson
(
JsonStreamParser
(
json
.
bufferedReader
()).
asSequence
().
single
(),
feature
)
{
Profile
.
parseJson
(
JsonStreamParser
(
json
.
bufferedReader
()).
asSequence
().
single
(),
feature
)
{
if
(
replace
)
{
val
oldProfile
=
subscriptions
[
it
.
formattedAddress
]
lazyClear
.
value
when
(
oldProfile
?.
subscription
)
{
Profile
.
SubscriptionStatus
.
Active
->
{
}
// skip dup subscription
Profile
.
SubscriptionStatus
.
Obsolete
->
{
oldProfile
.
password
=
it
.
password
oldProfile
.
method
=
it
.
method
oldProfile
.
subscription
=
Profile
.
SubscriptionStatus
.
Active
}
}
// if two profiles has the same address, treat them as the same profile and copy settings over
else
->
createProfile
(
it
.
apply
{
profiles
?.
get
(
it
.
formattedAddress
)
?.
apply
{
subscription
=
Profile
.
SubscriptionStatus
.
Active
it
.
tx
=
tx
subscriptions
[
it
.
formattedAddress
]
=
it
it
.
rx
=
rx
})
it
.
individual
=
individual
it
.
route
=
route
it
.
bypass
=
bypass
it
.
ipv6
=
ipv6
it
.
metered
=
metered
it
.
proxyApps
=
proxyApps
it
.
remoteDns
=
remoteDns
it
.
udpdns
=
udpdns
it
.
udpFallback
=
udpFallback
}
it
.
subscription
=
Profile
.
SubscriptionStatus
.
Active
createProfile
(
it
)
}
}
}
}
}
}
profiles
?.
forEach
{
profile
->
if
(
toUpdate
.
contains
(
profile
.
id
))
updateProfile
(
profile
)
}
}
fun
createProfilesFromJson
(
jsons
:
Sequence
<
InputStream
>,
replace
:
Boolean
=
false
)
{
fun
createProfilesFromJson
(
jsons
:
Sequence
<
InputStream
>,
replace
:
Boolean
=
false
)
{
val
profiles
=
if
(
replace
)
getAllProfiles
()
?.
associateBy
{
it
.
formattedAddress
}
else
null
val
profiles
=
if
(
replace
)
getAllProfiles
()
?.
associateBy
{
it
.
formattedAddress
}
else
null
val
feature
=
if
(
replace
)
{
val
feature
=
if
(
replace
)
{
...
@@ -107,7 +112,7 @@ object ProfileManager {
...
@@ -107,7 +112,7 @@ object ProfileManager {
}
}
}
}
fun
serializeToJson
(
profiles
:
List
<
Profile
>?
=
getA
ll
Profiles
()):
JSONArray
?
{
fun
serializeToJson
(
profiles
:
List
<
Profile
>?
=
getA
ctive
Profiles
()):
JSONArray
?
{
if
(
profiles
==
null
)
return
null
if
(
profiles
==
null
)
return
null
val
lookup
=
LongSparseArray
<
Profile
>(
profiles
.
size
).
apply
{
profiles
.
forEach
{
put
(
it
.
id
,
it
)
}
}
val
lookup
=
LongSparseArray
<
Profile
>(
profiles
.
size
).
apply
{
profiles
.
forEach
{
put
(
it
.
id
,
it
)
}
}
return
JSONArray
(
profiles
.
map
{
it
.
toJson
(
lookup
)
}.
toTypedArray
())
return
JSONArray
(
profiles
.
map
{
it
.
toJson
(
lookup
)
}.
toTypedArray
())
...
@@ -159,9 +164,19 @@ object ProfileManager {
...
@@ -159,9 +164,19 @@ object ProfileManager {
if
(!
nonEmpty
)
DataStore
.
profileId
=
createProfile
().
id
if
(!
nonEmpty
)
DataStore
.
profileId
=
createProfile
().
id
}
}
@Throws
(
IOException
::
class
)
fun
getActiveProfiles
():
List
<
Profile
>?
=
try
{
PrivateDatabase
.
profileDao
.
listActive
()
}
catch
(
ex
:
SQLiteCantOpenDatabaseException
)
{
throw
IOException
(
ex
)
}
catch
(
ex
:
SQLException
)
{
printLog
(
ex
)
null
}
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
getAllProfiles
():
List
<
Profile
>?
=
try
{
fun
getAllProfiles
():
List
<
Profile
>?
=
try
{
PrivateDatabase
.
profileDao
.
list
()
PrivateDatabase
.
profileDao
.
list
All
()
}
catch
(
ex
:
SQLiteCantOpenDatabaseException
)
{
}
catch
(
ex
:
SQLiteCantOpenDatabaseException
)
{
throw
IOException
(
ex
)
throw
IOException
(
ex
)
}
catch
(
ex
:
SQLException
)
{
}
catch
(
ex
:
SQLException
)
{
...
...
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
View file @
08b2b87c
...
@@ -89,8 +89,12 @@ fun String?.parseNumericAddress(): InetAddress? = Os.inet_pton(OsConstants.AF_IN
...
@@ -89,8 +89,12 @@ fun String?.parseNumericAddress(): InetAddress? = Os.inet_pton(OsConstants.AF_IN
if
(
Build
.
VERSION
.
SDK_INT
>=
29
)
it
else
parseNumericAddress
.
invoke
(
null
,
this
)
as
InetAddress
if
(
Build
.
VERSION
.
SDK_INT
>=
29
)
it
else
parseNumericAddress
.
invoke
(
null
,
this
)
as
InetAddress
}
}
fun
<
K
,
V
>
MutableMap
<
K
,
V
>.
computeIfAbsentCompat
(
key
:
K
,
value
:
()
->
V
)
=
if
(
Build
.
VERSION
.
SDK_INT
>=
24
)
fun
<
K
,
V
>
MutableMap
<
K
,
V
>.
computeIfAbsentCompat
(
key
:
K
,
value
:
()
->
V
)
=
if
(
Build
.
VERSION
.
SDK_INT
<
24
)
{
computeIfAbsent
(
key
)
{
value
()
}
else
this
[
key
]
?:
value
().
also
{
put
(
key
,
it
)
}
this
[
key
]
?:
value
().
also
{
put
(
key
,
it
)
}
}
else
computeIfAbsent
(
key
)
{
value
()
}
fun
<
K
,
V
>
MutableMap
<
K
,
V
>.
putIfAbsentCompat
(
key
:
K
,
value
:
V
)
=
if
(
Build
.
VERSION
.
SDK_INT
<
24
)
{
this
[
key
]
?:
put
(
key
,
value
)
}
else
putIfAbsent
(
key
,
value
)
suspend
fun
<
T
>
HttpURLConnection
.
useCancellable
(
block
:
suspend
HttpURLConnection
.()
->
T
):
T
{
suspend
fun
<
T
>
HttpURLConnection
.
useCancellable
(
block
:
suspend
HttpURLConnection
.()
->
T
):
T
{
return
suspendCancellableCoroutine
{
cont
->
return
suspendCancellableCoroutine
{
cont
->
...
...
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
View file @
08b2b87c
...
@@ -344,7 +344,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
...
@@ -344,7 +344,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
}
}
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>(),
ProfileManager
.
Listener
{
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>(),
ProfileManager
.
Listener
{
internal
val
profiles
=
ProfileManager
.
getA
ll
Profiles
()
?.
toMutableList
()
?:
mutableListOf
()
internal
val
profiles
=
ProfileManager
.
getA
ctive
Profiles
()
?.
toMutableList
()
?:
mutableListOf
()
private
val
updated
=
HashSet
<
Profile
>()
private
val
updated
=
HashSet
<
Profile
>()
init
{
init
{
...
@@ -543,7 +543,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
...
@@ -543,7 +543,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
true
true
}
}
R
.
id
.
action_export_clipboard
->
{
R
.
id
.
action_export_clipboard
->
{
val
profiles
=
ProfileManager
.
getA
ll
Profiles
()
val
profiles
=
ProfileManager
.
getA
ctive
Profiles
()
(
activity
as
MainActivity
).
snackbar
().
setText
(
if
(
profiles
!=
null
)
{
(
activity
as
MainActivity
).
snackbar
().
setText
(
if
(
profiles
!=
null
)
{
clipboard
.
setPrimaryClip
(
ClipData
.
newPlainText
(
null
,
profiles
.
joinToString
(
"\n"
)))
clipboard
.
setPrimaryClip
(
ClipData
.
newPlainText
(
null
,
profiles
.
joinToString
(
"\n"
)))
R
.
string
.
action_export_msg
R
.
string
.
action_export_msg
...
...
mobile/src/main/java/com/github/shadowsocks/UdpFallbackProfileActivity.kt
View file @
08b2b87c
...
@@ -64,7 +64,7 @@ class UdpFallbackProfileActivity : AppCompatActivity() {
...
@@ -64,7 +64,7 @@ class UdpFallbackProfileActivity : AppCompatActivity() {
}
}
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>()
{
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>()
{
internal
val
profiles
=
(
ProfileManager
.
getA
ll
Profiles
()
?.
toMutableList
()
?:
mutableListOf
())
internal
val
profiles
=
(
ProfileManager
.
getA
ctive
Profiles
()
?.
toMutableList
()
?:
mutableListOf
())
.
filter
{
it
.
id
!=
editingId
&&
PluginConfiguration
(
it
.
plugin
?:
""
).
selected
.
isEmpty
()
}
.
filter
{
it
.
id
!=
editingId
&&
PluginConfiguration
(
it
.
plugin
?:
""
).
selected
.
isEmpty
()
}
override
fun
onBindViewHolder
(
holder
:
ProfileViewHolder
,
position
:
Int
)
=
override
fun
onBindViewHolder
(
holder
:
ProfileViewHolder
,
position
:
Int
)
=
...
...
mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt
View file @
08b2b87c
...
@@ -41,7 +41,6 @@ import com.github.shadowsocks.MainActivity
...
@@ -41,7 +41,6 @@ import com.github.shadowsocks.MainActivity
import
com.github.shadowsocks.R
import
com.github.shadowsocks.R
import
com.github.shadowsocks.ToolbarFragment
import
com.github.shadowsocks.ToolbarFragment
import
com.github.shadowsocks.bg.BaseService
import
com.github.shadowsocks.bg.BaseService
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.plugin.AlertDialogFragment
import
com.github.shadowsocks.plugin.AlertDialogFragment
import
com.github.shadowsocks.utils.asIterable
import
com.github.shadowsocks.utils.asIterable
...
@@ -231,29 +230,16 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
...
@@ -231,29 +230,16 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
fetchJob
=
GlobalScope
.
launch
{
fetchJob
=
GlobalScope
.
launch
{
val
subscription
=
Subscription
.
instance
val
subscription
=
Subscription
.
instance
val
oldProfiles
=
ProfileManager
.
getAllProfiles
()
var
replace
=
true
for
(
url
in
subscription
.
urls
.
asIterable
())
{
for
(
url
in
subscription
.
urls
.
asIterable
())
{
try
{
try
{
val
connection
=
url
.
openConnection
()
as
HttpURLConnection
val
connection
=
url
.
openConnection
()
as
HttpURLConnection
connection
.
useCancellable
{
connection
.
useCancellable
{
ProfileManager
.
createProfilesFromSubscription
(
sequenceOf
(
connection
.
inputStream
),
ProfileManager
.
createProfilesFromSubscription
(
sequenceOf
(
connection
.
inputStream
))
replace
,
oldProfiles
)
}
}
}
catch
(
e
:
Exception
)
{
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
e
.
printStackTrace
()
activity
.
snackbar
(
e
.
readableMessage
).
show
()
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
finally
{
replace
=
false
}
}
val
userProfiles
=
oldProfiles
?.
filter
{
it
.
subscription
==
Profile
.
SubscriptionStatus
.
UserConfigured
}
if
(
userProfiles
!=
null
)
{
for
(
profile
in
userProfiles
.
asIterable
())
{
ProfileManager
.
createProfile
(
profile
)
}
}
}
}
...
...
mobile/src/main/java/com/github/shadowsocks/tasker/ConfigActivity.kt
View file @
08b2b87c
...
@@ -71,7 +71,7 @@ class ConfigActivity : AppCompatActivity() {
...
@@ -71,7 +71,7 @@ class ConfigActivity : AppCompatActivity() {
}
}
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>()
{
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>()
{
internal
val
profiles
=
ProfileManager
.
getA
ll
Profiles
()
?.
toMutableList
()
?:
mutableListOf
()
internal
val
profiles
=
ProfileManager
.
getA
ctive
Profiles
()
?.
toMutableList
()
?:
mutableListOf
()
override
fun
onBindViewHolder
(
holder
:
ProfileViewHolder
,
position
:
Int
)
=
override
fun
onBindViewHolder
(
holder
:
ProfileViewHolder
,
position
:
Int
)
=
if
(
position
==
0
)
holder
.
bindDefault
()
else
holder
.
bind
(
profiles
[
position
-
1
])
if
(
position
==
0
)
holder
.
bindDefault
()
else
holder
.
bind
(
profiles
[
position
-
1
])
...
...
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
View file @
08b2b87c
...
@@ -209,7 +209,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
...
@@ -209,7 +209,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
private
fun
populateProfiles
()
{
private
fun
populateProfiles
()
{
ProfileManager
.
ensureNotEmpty
()
ProfileManager
.
ensureNotEmpty
()
val
profiles
=
ProfileManager
.
getA
ll
Profiles
()
!!
val
profiles
=
ProfileManager
.
getA
ctive
Profiles
()
!!
fab
.
value
=
null
fab
.
value
=
null
fab
.
entries
=
profiles
.
map
{
it
.
formattedName
}.
toTypedArray
()
fab
.
entries
=
profiles
.
map
{
it
.
formattedName
}.
toTypedArray
()
fab
.
entryValues
=
profiles
.
map
{
it
.
id
.
toString
()
}.
toTypedArray
()
fab
.
entryValues
=
profiles
.
map
{
it
.
id
.
toString
()
}.
toTypedArray
()
...
...
tv/src/main/java/com/github/shadowsocks/tv/ProfilesDialogFragment.kt
View file @
08b2b87c
...
@@ -52,7 +52,7 @@ class ProfilesDialogFragment : LeanbackListPreferenceDialogFragmentCompat() {
...
@@ -52,7 +52,7 @@ class ProfilesDialogFragment : LeanbackListPreferenceDialogFragmentCompat() {
}
}
}
}
private
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>()
{
private
inner
class
ProfilesAdapter
:
RecyclerView
.
Adapter
<
ProfileViewHolder
>()
{
val
profiles
=
ProfileManager
.
getA
ll
Profiles
()
!!
val
profiles
=
ProfileManager
.
getA
ctive
Profiles
()
!!
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
)
=
ProfileViewHolder
(
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
)
=
ProfileViewHolder
(
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
leanback_list_preference_item_single_2
,
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
leanback_list_preference_item_single_2
,
...
...
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