Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
ethan
/
appframe
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit 5e48d4f1
authored
2026-04-02 09:37:53 +0800
by
tanghuan
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
在启动Flutter之前,增加一个原生的隐私政策界面
1 parent
8d06fd18
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
291 additions
and
7 deletions
android/app/src/main/AndroidManifest.xml
android/app/src/main/java/cn/banxe/bxe/PrivacyActivity.java
android/app/src/main/AndroidManifest.xml
View file @
5e48d4f
...
...
@@ -21,30 +21,38 @@
<application
android:label=
"班小二"
android:name=
"
cn.banxe.bxe.MyApplication
"
android:name=
"
${applicationName}
"
android:icon=
"@mipmap/launcher_icon"
android:networkSecurityConfig=
"@xml/network_security_config"
>
<!-- 隐私政策Activity - 启动入口 -->
<activity
android:name=
".PrivacyActivity"
android:exported=
"true"
android:theme=
"@style/LaunchTheme"
android:configChanges=
"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<activity
android:name=
".MainActivity"
android:exported=
"true"
android:launchMode=
"singleTop"
android:taskAffinity=
""
android:theme=
"@style/LaunchTheme"
android:configChanges=
"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated=
"true"
android:windowSoftInputMode=
"adjustResize"
>
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the
Flutter
UI initializes. After that, this theme continues
while the
Android
UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name=
"io.flutter.embedding.android.NormalTheme"
android:resource=
"@style/NormalTheme"
/>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
...
...
android/app/src/main/java/cn/banxe/bxe/PrivacyActivity.java
0 → 100644
View file @
5e48d4f
package
cn
.
banxe
.
bxe
;
import
android.app.Activity
;
import
android.app.AlertDialog
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.SharedPreferences
;
import
android.graphics.Typeface
;
import
android.net.Uri
;
import
android.os.Bundle
;
import
android.text.SpannableString
;
import
android.text.Spanned
;
import
android.text.TextPaint
;
import
android.text.method.LinkMovementMethod
;
import
android.text.style.ClickableSpan
;
import
android.view.Gravity
;
import
android.view.View
;
import
android.widget.Button
;
import
android.widget.LinearLayout
;
import
android.widget.TextView
;
public
class
PrivacyActivity
extends
Activity
{
private
static
final
String
PREFS_NAME
=
"privacy_prefs"
;
private
static
final
String
KEY_AGREED
=
"privacy_agreed"
;
private
static
final
String
USER_AGREEMENT_URL
=
"https://bxr.banxiaoer.net/apps/useragreement.html"
;
private
static
final
String
PRIVACY_POLICY_URL
=
"https://bxr.banxiaoer.net/apps/privacysettings.html"
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
// 检查是否已同意隐私政策
if
(
isPrivacyAgreed
())
{
startMainActivity
();
return
;
}
setContentView
(
createContentView
());
}
@Override
protected
void
onNewIntent
(
Intent
intent
)
{
super
.
onNewIntent
(
intent
);
setIntent
(
intent
);
// 如果已同意隐私政策,将新Intent转发给MainActivity
if
(
isPrivacyAgreed
())
{
forwardToMainActivity
(
intent
);
}
}
private
boolean
isPrivacyAgreed
()
{
SharedPreferences
prefs
=
getSharedPreferences
(
PREFS_NAME
,
Context
.
MODE_PRIVATE
);
return
prefs
.
getBoolean
(
KEY_AGREED
,
false
);
}
private
void
savePrivacyAgreed
()
{
SharedPreferences
prefs
=
getSharedPreferences
(
PREFS_NAME
,
Context
.
MODE_PRIVATE
);
prefs
.
edit
().
putBoolean
(
KEY_AGREED
,
true
).
apply
();
}
private
View
createContentView
()
{
// 根布局
LinearLayout
rootLayout
=
new
LinearLayout
(
this
);
rootLayout
.
setOrientation
(
LinearLayout
.
VERTICAL
);
rootLayout
.
setGravity
(
Gravity
.
CENTER_VERTICAL
);
rootLayout
.
setPadding
(
dpToPx
(
32
),
dpToPx
(
48
),
dpToPx
(
32
),
dpToPx
(
48
));
rootLayout
.
setBackgroundColor
(
0xFFFFFFFF
);
// 内容容器
LinearLayout
contentLayout
=
new
LinearLayout
(
this
);
contentLayout
.
setOrientation
(
LinearLayout
.
VERTICAL
);
LinearLayout
.
LayoutParams
contentLayoutParams
=
new
LinearLayout
.
LayoutParams
(
LinearLayout
.
LayoutParams
.
MATCH_PARENT
,
LinearLayout
.
LayoutParams
.
WRAP_CONTENT
);
rootLayout
.
addView
(
contentLayout
,
contentLayoutParams
);
// 标题
TextView
titleView
=
new
TextView
(
this
);
titleView
.
setText
(
"用户协议与隐私政策"
);
titleView
.
setTextSize
(
22
);
titleView
.
setTextColor
(
0xFF333333
);
titleView
.
setTypeface
(
null
,
Typeface
.
BOLD
);
titleView
.
setGravity
(
Gravity
.
CENTER
);
titleView
.
setPadding
(
0
,
0
,
0
,
dpToPx
(
32
));
contentLayout
.
addView
(
titleView
);
// 内容(带可点击链接)
TextView
contentView
=
new
TextView
(
this
);
contentView
.
setText
(
createClickableContent
());
contentView
.
setMovementMethod
(
LinkMovementMethod
.
getInstance
());
contentView
.
setHighlightColor
(
0x00000000
);
contentView
.
setTextSize
(
17
);
contentView
.
setTextColor
(
0xFF666666
);
contentView
.
setLineSpacing
(
dpToPx
(
6
),
1.0f
);
contentView
.
setGravity
(
Gravity
.
START
);
contentLayout
.
addView
(
contentView
);
// 按钮容器
LinearLayout
buttonLayout
=
new
LinearLayout
(
this
);
buttonLayout
.
setOrientation
(
LinearLayout
.
HORIZONTAL
);
buttonLayout
.
setGravity
(
Gravity
.
CENTER
);
LinearLayout
.
LayoutParams
buttonLayoutParams
=
new
LinearLayout
.
LayoutParams
(
LinearLayout
.
LayoutParams
.
MATCH_PARENT
,
LinearLayout
.
LayoutParams
.
WRAP_CONTENT
);
buttonLayoutParams
.
topMargin
=
dpToPx
(
48
);
contentLayout
.
addView
(
buttonLayout
,
buttonLayoutParams
);
// 同意按钮
Button
agreeButton
=
new
Button
(
this
);
agreeButton
.
setText
(
"同意"
);
agreeButton
.
setTextColor
(
0xFFFFFFFF
);
agreeButton
.
setBackgroundColor
(
0xFF4CAF50
);
agreeButton
.
setTextSize
(
16
);
agreeButton
.
setGravity
(
Gravity
.
CENTER
);
agreeButton
.
setSingleLine
(
true
);
agreeButton
.
setMinWidth
(
dpToPx
(
120
));
agreeButton
.
setMinHeight
(
dpToPx
(
48
));
int
btnPaddingH
=
dpToPx
(
24
);
int
btnPaddingV
=
dpToPx
(
12
);
agreeButton
.
setPadding
(
btnPaddingH
,
btnPaddingV
,
btnPaddingH
,
btnPaddingV
);
agreeButton
.
setOnClickListener
(
v
->
onAgreeClicked
());
LinearLayout
.
LayoutParams
agreeParams
=
new
LinearLayout
.
LayoutParams
(
LinearLayout
.
LayoutParams
.
WRAP_CONTENT
,
LinearLayout
.
LayoutParams
.
WRAP_CONTENT
);
agreeParams
.
setMargins
(
dpToPx
(
16
),
0
,
dpToPx
(
16
),
0
);
buttonLayout
.
addView
(
agreeButton
,
agreeParams
);
// 不同意按钮
Button
disagreeButton
=
new
Button
(
this
);
disagreeButton
.
setText
(
"不同意"
);
disagreeButton
.
setTextColor
(
0xFF666666
);
disagreeButton
.
setBackgroundColor
(
0xFFEEEEEE
);
disagreeButton
.
setTextSize
(
16
);
disagreeButton
.
setGravity
(
Gravity
.
CENTER
);
disagreeButton
.
setSingleLine
(
true
);
disagreeButton
.
setMinWidth
(
dpToPx
(
120
));
disagreeButton
.
setMinHeight
(
dpToPx
(
48
));
disagreeButton
.
setPadding
(
btnPaddingH
,
btnPaddingV
,
btnPaddingH
,
btnPaddingV
);
disagreeButton
.
setOnClickListener
(
v
->
onDisagreeClicked
());
LinearLayout
.
LayoutParams
disagreeParams
=
new
LinearLayout
.
LayoutParams
(
LinearLayout
.
LayoutParams
.
WRAP_CONTENT
,
LinearLayout
.
LayoutParams
.
WRAP_CONTENT
);
disagreeParams
.
setMargins
(
dpToPx
(
16
),
0
,
dpToPx
(
16
),
0
);
buttonLayout
.
addView
(
disagreeButton
,
disagreeParams
);
return
rootLayout
;
}
private
int
dpToPx
(
int
dp
)
{
float
density
=
getResources
().
getDisplayMetrics
().
density
;
return
(
int
)
(
dp
*
density
+
0.5f
);
}
private
SpannableString
createClickableContent
()
{
String
text
=
"请您仔细阅读《用户协议》和《隐私政策》,\n充分理解协议内容。\n\n"
+
"我们将严格遵守相关法律法规,保护您的个人信息安全。\n\n"
+
"点击\"同意\"即表示您已阅读并同意相关协议。"
;
SpannableString
spannableString
=
new
SpannableString
(
text
);
// 用户协议点击
int
userAgreementStart
=
text
.
indexOf
(
"《用户协议》"
);
int
userAgreementEnd
=
userAgreementStart
+
"《用户协议》"
.
length
();
spannableString
.
setSpan
(
new
ClickableSpan
()
{
@Override
public
void
onClick
(
View
widget
)
{
openBrowser
(
USER_AGREEMENT_URL
);
}
@Override
public
void
updateDrawState
(
TextPaint
ds
)
{
super
.
updateDrawState
(
ds
);
ds
.
setColor
(
0xFF4CAF50
);
ds
.
setUnderlineText
(
true
);
}
},
userAgreementStart
,
userAgreementEnd
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
// 隐私政策点击
int
privacyPolicyStart
=
text
.
indexOf
(
"《隐私政策》"
);
int
privacyPolicyEnd
=
privacyPolicyStart
+
"《隐私政策》"
.
length
();
spannableString
.
setSpan
(
new
ClickableSpan
()
{
@Override
public
void
onClick
(
View
widget
)
{
openBrowser
(
PRIVACY_POLICY_URL
);
}
@Override
public
void
updateDrawState
(
TextPaint
ds
)
{
super
.
updateDrawState
(
ds
);
ds
.
setColor
(
0xFF4CAF50
);
ds
.
setUnderlineText
(
true
);
}
},
privacyPolicyStart
,
privacyPolicyEnd
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
return
spannableString
;
}
private
void
openBrowser
(
String
url
)
{
Intent
intent
=
new
Intent
(
Intent
.
ACTION_VIEW
,
Uri
.
parse
(
url
));
startActivity
(
intent
);
}
private
void
onAgreeClicked
()
{
savePrivacyAgreed
();
startMainActivity
();
}
private
void
onDisagreeClicked
()
{
new
AlertDialog
.
Builder
(
this
)
.
setTitle
(
"提示"
)
.
setMessage
(
"您需要同意隐私政策才能使用本应用,是否重新考虑?"
)
.
setPositiveButton
(
"重新考虑"
,
(
dialog
,
which
)
->
{
// 不做任何操作,保持当前界面
})
.
setNegativeButton
(
"仍不同意"
,
(
dialog
,
which
)
->
{
// 退出应用
finishAffinity
();
})
.
setCancelable
(
false
)
.
show
();
}
private
void
startMainActivity
()
{
Intent
intent
=
new
Intent
(
this
,
MainActivity
.
class
);
copyIntentData
(
getIntent
(),
intent
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
|
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
startActivity
(
intent
);
finish
();
}
private
void
forwardToMainActivity
(
Intent
sourceIntent
)
{
Intent
intent
=
new
Intent
(
this
,
MainActivity
.
class
);
copyIntentData
(
sourceIntent
,
intent
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
|
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
startActivity
(
intent
);
finish
();
}
private
void
copyIntentData
(
Intent
source
,
Intent
dest
)
{
if
(
source
==
null
)
return
;
// 复制Extras
if
(
source
.
getExtras
()
!=
null
)
{
dest
.
putExtras
(
source
.
getExtras
());
}
// 复制Data URI(微信回调可能使用)
if
(
source
.
getData
()
!=
null
)
{
dest
.
setData
(
source
.
getData
());
}
// 复制Action
if
(
source
.
getAction
()
!=
null
)
{
dest
.
setAction
(
source
.
getAction
());
}
// 复制所有分类
if
(
source
.
getCategories
()
!=
null
)
{
for
(
String
category
:
source
.
getCategories
())
{
dest
.
addCategory
(
category
);
}
}
// 复制Flags(排除某些会导致问题的flags)
int
flags
=
source
.
getFlags
();
flags
&=
~
Intent
.
FLAG_ACTIVITY_NEW_TASK
;
flags
&=
~
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
;
dest
.
setFlags
(
flags
);
}
@Override
public
void
onBackPressed
()
{
// 禁止返回键
}
}
Write
Preview
Styling with
Markdown
is supported
Attach a file
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 post a comment