Commit a79b8e88 authored by wanglei's avatar wanglei

...

parent acd48584
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
<uses-feature <uses-feature
android:name="android.hardware.camera" android:name="android.hardware.camera"
android:required="false" /> <!-- 获取wifi列表 --> android:required="false" />
<!-- 获取wifi列表 -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
...@@ -14,6 +17,12 @@ ...@@ -14,6 +17,12 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<!-- 前台服务 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application <application
android:name=".MyApplication" android:name=".MyApplication"
android:allowBackup="true" android:allowBackup="true"
...@@ -106,6 +115,12 @@ ...@@ -106,6 +115,12 @@
android:resource="@xml/file_paths" /> android:resource="@xml/file_paths" />
</provider> </provider>
<service
android:name=".service.StayJobService"
android:exported="false"
android:foregroundServiceType="dataSync"
android:permission="android.permission.BIND_JOB_SERVICE" />
<meta-data <meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID" android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" /> android:value="ca-app-pub-3940256099942544~3347511713" />
......
...@@ -21,6 +21,7 @@ import com.base.scanqr.fcm.receiver.ScreenStatusReceiver ...@@ -21,6 +21,7 @@ import com.base.scanqr.fcm.receiver.ScreenStatusReceiver
import com.base.scanqr.helper.EventUtils import com.base.scanqr.helper.EventUtils
import com.base.scanqr.helper.InstallHelps import com.base.scanqr.helper.InstallHelps
import com.base.scanqr.helper.NewComUtils import com.base.scanqr.helper.NewComUtils
import com.base.scanqr.service.StayJobService.Companion.startJob
import com.base.scanqr.ui.start.StartActivity import com.base.scanqr.ui.start.StartActivity
import com.base.scanqr.utils.ActivityManagerUtils import com.base.scanqr.utils.ActivityManagerUtils
import com.base.scanqr.utils.AppPreferences import com.base.scanqr.utils.AppPreferences
...@@ -136,7 +137,9 @@ class MyApplication : Application() { ...@@ -136,7 +137,9 @@ class MyApplication : Application() {
PackageStatusReceiver.registerPackageStatusReceiver(this) PackageStatusReceiver.registerPackageStatusReceiver(this)
BatteryStatusReceiver.registerBatteryStatusReceiver(this) BatteryStatusReceiver.registerBatteryStatusReceiver(this)
// startJob() kotlin.runCatching {
// startJob()
}
// startAlarm(appContext, 24) // startAlarm(appContext, 24)
// startAlarm(appContext, 48) // startAlarm(appContext, 48)
// startAlarm(appContext, 72) // startAlarm(appContext, 72)
......
...@@ -33,6 +33,8 @@ class AdInsertMgr { ...@@ -33,6 +33,8 @@ class AdInsertMgr {
} }
if (adState.showingAd) { if (adState.showingAd) {
showCallBack?.failed(1) showCallBack?.failed(1)
adEvent.adShowError("showingAd")
adState.showingAd = false
return return
} }
......
...@@ -31,6 +31,7 @@ class AdOpenMgr { ...@@ -31,6 +31,7 @@ class AdOpenMgr {
if (adState.showingAd) { if (adState.showingAd) {
showCallBack?.failed() showCallBack?.failed()
adEvent.adShowError("showingAd") adEvent.adShowError("showingAd")
adState.showingAd = false
return return
} }
if (showCallBack != null) { if (showCallBack != null) {
...@@ -78,7 +79,7 @@ class AdOpenMgr { ...@@ -78,7 +79,7 @@ class AdOpenMgr {
showCallBack?.googleFailed() showCallBack?.googleFailed()
showCallBack = null showCallBack = null
adState.onAdDisplayed() adState.onAdDisplayFailed()
(adEvent as AdmobEvent).adShowError(adError) (adEvent as AdmobEvent).adShowError(adError)
......
...@@ -21,5 +21,8 @@ class NotificationSendBean( ...@@ -21,5 +21,8 @@ class NotificationSendBean(
const val POPUP_WHERE_PACKAGE = "package" const val POPUP_WHERE_PACKAGE = "package"
const val POPUP_WHERE_WORK_MANAGER = "workManager" const val POPUP_WHERE_WORK_MANAGER = "workManager"
const val POPUP_WHERE_FILE_JOB = "FileJob" const val POPUP_WHERE_FILE_JOB = "FileJob"
const val ACTION_ID_SCAN = "action_id_scan"
} }
} }
\ No newline at end of file
package com.base.scanqr.service
import android.app.NotificationManager
import android.app.job.JobInfo
import android.app.job.JobParameters
import android.app.job.JobScheduler
import android.app.job.JobService
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.os.Build
import android.os.CountDownTimer
import androidx.work.Configuration
import com.base.scanqr.BuildConfig
import com.base.scanqr.service.StayNotification.createPermanentNotification
import com.base.scanqr.utils.LogEx
/**
* 常驻通知栏
*/
class StayJobService : JobService() {
init {
val builder = Configuration.Builder()
builder.setJobSchedulerJobIdRange(0, 1000)
}
companion object {
private val TAG = "StayJobService"
val NOTIFICATION_STAY_ID = 286
private var isRunning = false
private const val JOB_INFO_ID: Int = 101
fun Context.startJob() {
if (isRunning) return
LogEx.logDebug(TAG, "startJob")
val jobScheduler = getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler
val componentName = ComponentName(this, StayJobService::class.java)
val jobInfo = JobInfo.Builder(JOB_INFO_ID, componentName)
.setMinimumLatency(30000)
.build()
jobScheduler.schedule(jobInfo)
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
LogEx.logDebug(TAG, "onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
private fun startForeground() {
val notification = createPermanentNotification(applicationContext)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(
NOTIFICATION_STAY_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
)
} else {
startForeground(NOTIFICATION_STAY_ID, notification)
}
isRunning = true
}
private fun notifyForeground() {
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(NOTIFICATION_STAY_ID, createPermanentNotification(applicationContext))
}
override fun onDestroy() {
isRunning = false
super.onDestroy()
}
override fun onCreate() {
LogEx.logDebug(TAG, "onCreate isRunning=$isRunning")
if (!isRunning) {
isRunning = true
startForeground()
Timer().start()
}
super.onCreate()
}
override fun onStartJob(params: JobParameters?): Boolean {
return true
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
val millisInFuture = if (BuildConfig.DEBUG) 5000L else 30000L
private inner class Timer() : CountDownTimer(millisInFuture, 1000) {
override fun onTick(millisUntilFinished: Long) {
}
override fun onFinish() {
LogEx.logDebug(TAG, "Timer onFinish")
notifyForeground()
Timer().start()
}
}
}
package com.base.scanqr.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.graphics.BitmapFactory
import android.graphics.drawable.Icon
import android.os.Build
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat
import com.base.scanqr.R
import com.base.scanqr.bean.NotificationSendBean.Companion.ACTION_ID_SCAN
import com.base.scanqr.service.StayJobService.Companion.NOTIFICATION_STAY_ID
import com.base.scanqr.ui.main.MainActivity
import com.base.scanqr.ui.start.StartActivity
import kotlin.random.Random
object StayNotification {
private fun customRemoteViews(context: Context, contentView: RemoteViews, expendView: RemoteViews) {
val requestCode1 = Random.nextInt(1800)
val intent1 = Intent(context, StartActivity::class.java).apply {
putExtra("actionId", ACTION_ID_SCAN)
}
val pendingIntent1 =
PendingIntent.getActivity(
context,
requestCode1,
intent1,
PendingIntent.FLAG_IMMUTABLE
)
contentView.setOnClickPendingIntent(R.id.ivQR, pendingIntent1)
contentView.setOnClickPendingIntent(R.id.ivTime, pendingIntent1)
contentView.setOnClickPendingIntent(R.id.llScan, pendingIntent1)
expendView.setOnClickPendingIntent(R.id.ivQR, pendingIntent1)
expendView.setOnClickPendingIntent(R.id.ivTime, pendingIntent1)
expendView.setOnClickPendingIntent(R.id.llScan, pendingIntent1)
}
fun notifyStayNotification(context: Context, desc: String) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(NOTIFICATION_STAY_ID, createPermanentNotification(context))
}
fun createPermanentNotification(context: Context): Notification {
val channelName = "Stay Foreground Service Channel"
val channelId = "Stay_channel"
val contentView = RemoteViews(context.packageName, R.layout.stay_notification_small_qr)
val expendView = RemoteViews(context.packageName, R.layout.stay_notification_big_qr)
customRemoteViews(context, contentView, expendView)
val builder = NotificationCompat.Builder(context, channelId)
val smallIcon = IconCompat.createFromIcon(
context, Icon.createWithResource(
context, R.mipmap.ic_launcher
)
)
smallIcon?.let {
builder.setSmallIcon(smallIcon) //设置状态栏内的小图标
}
val nfIntent = Intent(context, MainActivity::class.java)
val pendingIntent =
PendingIntent.getActivity(context, 0, nfIntent, PendingIntent.FLAG_IMMUTABLE)
builder.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.mipmap.ic_launcher
)
)
builder.setContentTitle(context.resources.getString(R.string.app_name))
builder.setContentIntent(pendingIntent) //设置PendingIntent
builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE) //设置通知公开可见
builder.setAutoCancel(false)
builder.setOngoing(true)
builder.setPriority(NotificationCompat.PRIORITY_MAX) //优先级为:重要通知
builder.setWhen(System.currentTimeMillis())
builder.setCustomContentView(contentView)
builder.setCustomBigContentView(expendView)
builder.setCustomHeadsUpContentView(expendView)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW)
channel.lockscreenVisibility = 1
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
builder.setChannelId(channelId)
}
return builder.build()
}
}
\ No newline at end of file
package com.base.scanqr.ui.main package com.base.scanqr.ui.main
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.TextView import android.widget.TextView
...@@ -11,6 +12,7 @@ import com.base.scanqr.ads.AdsMgr ...@@ -11,6 +12,7 @@ import com.base.scanqr.ads.AdsMgr
import com.base.scanqr.base.BaseActivity import com.base.scanqr.base.BaseActivity
import com.base.scanqr.bean.ConstObject.mainStartTimes import com.base.scanqr.bean.ConstObject.mainStartTimes
import com.base.scanqr.bean.HomeTabUIBean import com.base.scanqr.bean.HomeTabUIBean
import com.base.scanqr.bean.NotificationSendBean.Companion.ACTION_ID_SCAN
import com.base.scanqr.databinding.ActivityMainBinding import com.base.scanqr.databinding.ActivityMainBinding
import com.base.scanqr.databinding.ItemHomeTabBinding import com.base.scanqr.databinding.ItemHomeTabBinding
import com.base.scanqr.qr.CameraUtils import com.base.scanqr.qr.CameraUtils
...@@ -82,6 +84,24 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl ...@@ -82,6 +84,24 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
onBackPressedDispatcher.addCallback { onBackPressedDispatcher.addCallback {
showAppExitDialog() showAppExitDialog()
} }
handleActionIdJump()
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
handleActionIdJump()
}
private fun handleActionIdJump() {
val actionId = intent.extras?.getString("actionId")
LogEx.logDebug(TAG, "actionId=$actionId")
when (actionId) {
ACTION_ID_SCAN -> {
val defaultTab = binding.tabLayout.getTabAt(1)
defaultTab?.select()
defaultTab?.setSelected()
}
}
} }
private fun initTab() { private fun initTab() {
......
...@@ -8,9 +8,12 @@ import com.base.scanqr.ads.AdsShowCallBack ...@@ -8,9 +8,12 @@ import com.base.scanqr.ads.AdsShowCallBack
import com.base.scanqr.base.BaseActivity import com.base.scanqr.base.BaseActivity
import com.base.scanqr.bean.ConstObject import com.base.scanqr.bean.ConstObject
import com.base.scanqr.bean.ConstObject.isFirstLauncher import com.base.scanqr.bean.ConstObject.isFirstLauncher
import com.base.scanqr.bean.NotificationSendBean.Companion.ACTION_ID_SCAN
import com.base.scanqr.databinding.ActivityStartBinding import com.base.scanqr.databinding.ActivityStartBinding
import com.base.scanqr.service.StayJobService.Companion.startJob
import com.base.scanqr.ui.language.LanguageActivity import com.base.scanqr.ui.language.LanguageActivity
import com.base.scanqr.ui.main.MainActivity import com.base.scanqr.ui.main.MainActivity
import com.base.scanqr.utils.LogEx
import com.gyf.immersionbar.ktx.immersionBar import com.gyf.immersionbar.ktx.immersionBar
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
...@@ -31,6 +34,8 @@ class StartActivity : BaseActivity<ActivityStartBinding>(ActivityStartBinding::i ...@@ -31,6 +34,8 @@ class StartActivity : BaseActivity<ActivityStartBinding>(ActivityStartBinding::i
if (ConstObject.ifAgreePrivacy) { if (ConstObject.ifAgreePrivacy) {
agreePrivacy() agreePrivacy()
} }
startJob()
} }
...@@ -102,7 +107,16 @@ class StartActivity : BaseActivity<ActivityStartBinding>(ActivityStartBinding::i ...@@ -102,7 +107,16 @@ class StartActivity : BaseActivity<ActivityStartBinding>(ActivityStartBinding::i
} }
private fun handleActionIdJump() { private fun handleActionIdJump() {
val actionId = intent.extras?.getString("actionId")
LogEx.logDebug(TAG, "actionId=$actionId")
when (actionId) {
ACTION_ID_SCAN -> {
}
}
startActivity(Intent(this, MainActivity::class.java).apply { startActivity(Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
putExtra("actionId", actionId)
}) })
finish() finish()
} }
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#F5F5F5" />
<corners android:radius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
tools:ignore="DisableBaselineAlignment">
<ImageView
android:id="@+id/ivQR"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginVertical="24dp"
android:src="@mipmap/qr"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/ivTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="20dp"
android:src="@mipmap/time"
tools:ignore="ContentDescription" />
<LinearLayout
android:id="@+id/llScan"
android:background="@drawable/bg_f5f5f5_10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:paddingHorizontal="15dp"
android:paddingVertical="14dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/search"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="20dp"
android:includeFontPadding="true"
android:text="@string/search_for_products"
android:textColor="@color/black"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
tools:ignore="DisableBaselineAlignment">
<ImageView
android:id="@+id/ivQR"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginVertical="8dp"
android:src="@mipmap/qr"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/ivTime"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="20dp"
android:src="@mipmap/time"
tools:ignore="ContentDescription" />
<LinearLayout
android:id="@+id/llScan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:background="@drawable/bg_f5f5f5_10"
android:paddingHorizontal="15dp"
android:paddingVertical="6dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/search"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="20dp"
android:includeFontPadding="true"
android:text="@string/search_for_products"
android:textColor="@color/black"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
...@@ -70,5 +70,6 @@ ...@@ -70,5 +70,6 @@
<string name="do_you_want_to_leave_app">Do you want to leave app?</string> <string name="do_you_want_to_leave_app">Do you want to leave app?</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>
<string name="no">No</string> <string name="no">No</string>
<string name="search_for_products">Search for products</string>
</resources> </resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment