Count Hardware Usage of Camera from other apps in Android - android

I would be glad if anyone could help me with an Android app that i am trying to make .
Actually , there is a module in the app which counts how many time i used different service like gps ,wifi , camera etc.
So i am stuck with camera feature , how to record the usage of camera by 3rd party applications like whatsapp , instagram etc . I tried broadcast receiver on gallery , content observer on mediastore , and file manager also .
So how to do it ?

You can use the Accessibility Service to detect every time that the camera is in use.
Remember to add the permission:
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
import android.app.Activity
import android.content.Context
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CameraManager.AvailabilityCallback
import android.os.Handler
class YourClassActivity : Activity() {
private lateinit var callback: AvailabilityCallback
private lateinit var manager: CameraManager
public override fun onResume() {
super.onResume()
manager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
callback = object : AvailabilityCallback() {
override fun onCameraAvailable(cameraId: String) {
super.onCameraAvailable(cameraId)
//Do something
}
override fun onCameraUnavailable(cameraId: String) {
super.onCameraUnavailable(cameraId)
//The camera is not available
}
}
manager.registerAvailabilityCallback(callback, Handler())
}
public override fun onPause() {
//Unsubscribe listener
manager.unregisterAvailabilityCallback(callback)
super.onPause()
}
}

Related

FlutterActivity not working when using cached engine

I am trying to open FlutterActivity in my existing android application. Before I was creating new flutter engine every time I was opening activity like this:
FlutterActivity
.withNewEngine()
.build(context)
And everything was working fine besides a little lag while opening the activity. To get rid of the lag I wanted to switch to using cached engine. I followed this official tutorial: LINK
And ended up with smething like this:
In my Application class:
class App : Application() {
lateinit var flutterEngine: FlutterEngine
override fun onCreate() {
...
flutterEngine = FlutterEngine(this)
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
FlutterEngineCache
.getInstance()
.put("myEngineId", flutterEngine)
}
}
And later in my application on the button click, in the same place that I was successfully opening FlutterActivity:
FlutterActivity
.withCachedEngine("myEngineId")
.build(context)
So I basically followed the all the instructions but the effect that I get now is after the button click there is even longer lag than before and then there is only black screen being displayed. My flutter screen is not displayed and application is kind of frozen I can't go back or do anything. There is also no error or any useful info in the logs. I have no idea what is going on. What am I doing wrong?
To Use cached FlutterEngine
In FlutterActivity you must declare provideFlutterEngine method.
class DemoActivity : FlutterActivity() {
override fun provideFlutterEngine(context: Context): FlutterEngine? =
FlutterEngineCache.getInstance().get(FlutterConstants.ENGINE_ID)
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "demo-channel")
.setMethodCallHandler { call, result ->
if (call.method == "demo-method") {
demoMethod()
result.success(null)
} else {
result.notImplemented()
}
}
}
private fun demoMethod() {
// Do native code
}
}

Android 11 - CallRedirectionService not getting triggered

We need to invoke a service when an outgoing call is placed so that we can use the target number to show certain additional information. As per Android documentation, CallRedirectionService should be used. However, after declaring a custom service as depicted in documentation, we find that the custom service is not getting triggered. Please let us know what we are doing wrong. Appreciate your help.
I referred to this link as well but not clear on the answer. There is a mention to role acquisition but I did not find that in Android documentation. Please direct me to the relevant page if available.
CallRedirectionService Implementation not working
Manifest.xml
<service android:name="<mypackage>.CustomCallService"
android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallRedirectionService"/>
</intent-filter>
</service>
Custom service code
#Override
public void onPlaceCall(#NonNull Uri handle, #NonNull PhoneAccountHandle initialPhoneAccount, boolean allowInteractiveResponse) {
System.out.println("Outgoing:" + initialPhoneAccount + ":" + handle); //Call does not reach here
placeCallUnmodified();
}
In Kotlin:
Your implementation of the CallRedirectionService seems correct. I understand that the only step missing is the role request and acquisition.
You can prompt the user to give you the CallRedirectionService role by using the RoleManager class.
In this example below, we are requesting this role as soon as the MainActivity is created:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!isRedirection())
roleAcquire(RoleManager.ROLE_CALL_REDIRECTION)
}
}
The following functions shall be used:
private fun isRedirection(): Boolean {
return isRoleHeldByApp(RoleManager.ROLE_CALL_REDIRECTION)
}
private fun isRoleHeldByApp(roleName: String): Boolean {
val roleManager: RoleManager? = getSystemService(RoleManager::class.java)
return roleManager!!.isRoleHeld(roleName)
}
private fun roleAcquire(roleName: String) {
val roleManager: RoleManager?
if (roleAvailable(roleName)) {
roleManager = getSystemService(RoleManager::class.java)
val intent = roleManager.createRequestRoleIntent(roleName)
startActivityForResult(intent, 1)
} else {
Toast.makeText(
this,
"Redirection call with role in not available",
Toast.LENGTH_SHORT
).show()
}
}
private fun roleAvailable(roleName: String): Boolean {
val roleManager: RoleManager? = getSystemService(RoleManager::class.java)
return roleManager!!.isRoleAvailable(roleName)
}

Android - invalidate Fingerprint authentication when user minimises app but not when when moving across activities

I have an app in which fingerprint lock is used to protect the app from being used without first authenticating with the fingerprint.
The issue is that the verification only happens at first launch of the app; so after first launch, no more verification until when the app is being launched again,
But I want the current verification to be valid when moving across different activities in the app, but it should be invalidated if the user minimises the app or when the phone screen goes off, so that the user would be asked to verify fingerprint again after minimizing and resuming back into the app.
I have tried using a base activity and overriding the onPause and onResume, but the methods get called even when moving across activities, which is not what I want.
You can likely use the system broadcast intents ACTION_SCREEN_ON, ACTION_SCREEN_OFF, and/or ACTION_USER_PRESENT to achieve your goals. Check https://developer.android.com/reference/android/content/Intent for more on these.
To do so, register as a broadcast receiver to receive these notifications in your main activity onCreate, un-register in onDestroy. You can use these notifications to set flags indicating whether authentication is needed.
Example code:
#Override
protected void onCreate(Bundle savedInstanceState)
{
.
.
.
// register to receive appropriate events
IntentFilter intentUserPresent = new IntentFilter(Intent.ACTION_USER_PRESENT);
intentUserPresent.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(userActionReceiver, intentUserPresent);
.
.
.
}
// create a BroadcastReceiver to receive the notifications
private BroadcastReceiver userActionReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("MyLog", String.format("MainActivity received broadcaast %s", intent.toString()));
if (intent.getAction() == Intent.ACTION_USER_PRESENT)
{
// set flag indicating re-authentication is needed
}
}
};
#Override
protected void onDestroy()
{
// make sure to un-register the receiver!
unregisterReceiver(userActionReceiver);
super.onDestroy();
}
This won't detect a user "minimizing the app", but its unclear why you would consider that re-authentication would be needed in this scenario. Lifecycle events onStart/onStop can detect background/foreground of an activity.
Solved this few weeks ago while working on a completely different project from the one I was working on when I asked the question.
I am glad to share my workaround.
The app is locked after three seconds of minimizing the app or the screen going off; as long as the fingerprint switch is enabled in the app's preferences setting.
First, I created a BaseActivity class from which all other project activities inherit from except the Fingerprint activity class which inherits directly from AppCompatActivity()
package com.domainName.appName.ui.activities
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
open class BaseActivity : AppCompatActivity() {
private var securitySet=false
private var backPressed=false
private var goingToFingerprint=false
companion object{
private var handler:Handler?=null
}
override fun
onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
prefSaver.save(prefFileName, "launched_new_activity",sValue = true,saveImmediately=true)
if(handler==null){
handler= Handler(mainLooper)
}
handler?.removeCallbacksAndMessages(null)
}
override fun onDestroy() {
super.onDestroy()
handler?.removeCallbacksAndMessages(null)
}
override fun onStart() {
handler?.removeCallbacksAndMessages(null)
goingToFingerprint=false
securitySet=prefChecker.check(prefFileName,"fingerprint_security_switch",false)
super.onStart()
}
override fun onPause() {
super.onPause()
prefSaver.save(prefFileName,"launched_new_activity",sValue = false,saveImmediately=true)
if(securitySet && !backPressed){
if(!goingToFingerprint){postLock()}
}
}
override fun onResume() {
super.onResume()
backPressed=false
if(prefChecker.check(prefFileName,"app_locked",false)&&securitySet){
prefSaver.save(prefFileName,"launched_new_activity",sValue = true,saveImmediately=true)
goingToFingerprint=true
startActivity(Intent(this,FingerprintActivity::class.java))
}
}
override fun onBackPressed() {
backPressed=true
super.onBackPressed()
}
private fun postLock(){
handler?.removeCallbacksAndMessages(null)
handler?.postDelayed({
if(!prefChecker.check(prefFileName,"launched_new_activity",false)) {
prefSaver.save(prefFileName,"app_locked",sValue = true,saveImmediately=true)
}
},3000)
}
}
I created an InitialActivity which has noHistory mode set in the Android manifest and acts as the app launcher activity.
The InitialActivity inherits from BaseActivity as well and simply calls startActivity() in its onCreate method for the MainActivity activity.
The InitialActivity overrides onPause this way :
override fun onPause() {
if(prefChecker.check(prefFileName,"fingerprint_security_switch",false)) {
prefSaver.save(prefFileName,"app_locked",sValue = true,true)
/*setting this so app is locked on First Launch if the fingerprint switch is on.
The fingerprint switch is turned on and off from the SettingsActivity */
}
super.onPause()
}
Then FingerprintActivity is implemented this way:
package com.domainName.appName.ui.activities
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.Gravity
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.biometric.BiometricPrompt.PromptInfo
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class FingerprintActivity : AppCompatActivity() {
private lateinit var executor: Executor
var biometricPrompt: BiometricPrompt? = null
var promptInfo: PromptInfo? = null
var notifIntentLabel: String? = null
var finishImmediately=false
override fun
onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);setContentView(R.layout.fingerprint_main)
executor = ContextCompat.getMainExecutor(this)
finishImmediately = intent.getBooleanExtra("finishImmediately",false)
if(finishImmediately)finish()
biometricPrompt = BiometricPrompt(this,
executor, object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
biometricPrompt?.cancelAuthentication()
val intent=Intent(this#FingerprintActivity,FingerprintActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("finishImmediately",true)
startActivity(intent)
}
override fun onAuthenticationSucceeded(
result: BiometricPrompt.AuthenticationResult
) {
super.onAuthenticationSucceeded(result)
prefSaver.save(prefFileName,"app_locked",sValue = false,true)
finish()
}
})
promptInfo = PromptInfo.Builder()
.setTitle("AppName Biometric Login")
.setSubtitle("\t\tLog in using your fingerprint")
.setNegativeButtonText("Cancel")
.build()
val biometricManager = BiometricManager.from(this)
when (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK)) {
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> showToast("No fingerprint hardware detected on this device.")
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> showToast("Fingerprint hardware features are currently unavailable on this device.")
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> showToast("There is no any fingerprint credential associated with your account.\nPlease go to your phone settings to enrol fingerprints.")
BiometricManager.BIOMETRIC_SUCCESS -> authenticateUser()
BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> showToast("Fingerprint feature on device requires updating and is therefore currently unavailable.")
BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> showToast("Fingerprint features not supported on device")
BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> showToast("Fingerprint features status unknown")
}
}
private fun showToast(txt_to_show: String) {
val t = Toast.makeText(this, txt_to_show, Toast.LENGTH_SHORT)
t.setGravity(Gravity.CENTER or Gravity.CENTER_HORIZONTAL, 0, 0)
t.show()
}
private fun authenticateUser() {
if(!finishImmediately){
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.USE_FINGERPRINT
) == PackageManager.PERMISSION_GRANTED
) {
promptInfo?.let{ biometricPrompt?.authenticate(it)}
} else if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.USE_BIOMETRIC
) == PackageManager.PERMISSION_GRANTED
) {
promptInfo?.let{ biometricPrompt?.authenticate(it)}
} else {
showToast("Please grant the AppName app the necessary permissions to use fingerprint hardware.")
}
}
}
}
prefSaver and prefChecker are basically the class. The names were used for descriptive purpose. The class was implemented this way :
package com.domainName.appName.utils
import android.annotation.SuppressLint
import android.content.Context;
import android.content.SharedPreferences;
class PrefCheckerOrSaver(private val context:Context?){
fun <T>check(sFile: String,keyS: String,defaultS: T):T{
if(context==null)return defaultS
val sPref:SharedPreferences= context.getSharedPreferences(sFile,Context.MODE_PRIVATE)
return when(defaultS){
is String->sPref.getString(keyS,defaultS) as T
is Int-> sPref.getInt(keyS,defaultS) as T
is Long-> sPref.getLong(keyS,defaultS) as T
is Boolean-> sPref.getBoolean(keyS,defaultS) as T
else-> defaultS
}
}
#SuppressLint("ApplySharedPref")
fun save(sFile:String, sKey:String, sValue:Any, saveImmediately:Boolean=false){
if(context==null)return
val sharedPreferences:SharedPreferences = context.getSharedPreferences(sFile, Context.MODE_PRIVATE);
val editor:SharedPreferences.Editor = sharedPreferences.edit();
when(sValue) {
is String-> editor.putString(sKey, sValue)
is Int->editor.putInt(sKey, sValue)
is Long-> editor.putLong(sKey, sValue)
is Boolean->editor.putBoolean(sKey, sValue)
}
if(saveImmediately){editor.commit()}
else{ editor.apply()}
}
}
Permission in app manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="com.domainName.appName">
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<application
android:name=".MainApplication"
android:allowBackup="false"
android:icon="${appIcon}"
android:label="#string/app_name"
android:roundIcon="${appIconRound}"
android:resizeableActivity="true"
android:supportsRtl="false"
android:theme="#style/ThemeAppMain"
tools:targetApi="n"
>
<activity
android:name=".ui.activities.InitialActivity"
android:label="#string/app_name"
android:exported="true"
android:noHistory="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.activities.BaseActivity" />
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleTask"/>
<activity android:name=".ui.activities.SettingsActivity" />
<activity android:name=".ui.activities.FingerprintActivity"
android:launchMode="singleTask"
android:noHistory="true"
/>
</application>
</manifest>

How to show in Android with kotlin, the "someone calling" screen when app is closed or fone in idle like when someone call? For a video call

I working in a internal chat application with video calls, when someone call, the phone must show the "ringing" screen. I need to wake up the phone screen and show the full screen notification with the calling screen when the app receives a push notification that someone is calling.
How can I do that?
Thank you.
You need to use the TelephonyManager to give you access to a subset of API's available natively.
Once you create an instance of this, you must register to listen() passing in a class that implements the PhoneStateListener. From here you can listen to a numerous states when listening for the LISTEN_CALL_STATE
Something like this:
private var yourListenerClass: ListenerClass? = null
override fun onCreate(savedInstanceState: Bundle?) {
var telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
telephonyManager?.listen(yourListenerClass, PhoneStateListener.LISTEN_CALL_STATE)
}
private inner class ListenerClass : PhoneStateListener() {
override fun onCallStateChanged(state: Int, number: String?) {
super.onCallStateChanged(state, number)
when (state) {
TelephonyManager.CALL_STATE_RINGING-> {
//incoming call detected, do something
}
TelephonyManager.CALL_STATE_IDLE-> {
}
}
}
}
Here is the resource to the documentation that can give you more API's available for this listener: onCallStateChanged()

Is CastRemoteDisplayLocalService usable in a Custom Receiver?

I'm trying to create an app that can broadcast Android views on the Chromecast, and I thought I found something promising in CastRemoteDisplayLocalService. I created a simple test app but found the callback onCreatePresentation was never called when I casted my device. After some searching I discovered it was because my application was not published as a Remote Display Application but a Custom Application Receiver from the Google Cast Developer Console.
Unfortunately when I try to create a new application from the console, Remote Display Application is not an option. After some searching, I came across this Stack Overflow question that said Remote Display API is now deprecated. There is an interface called CastRemoteDisplayApi which is marked as deprecated, but the classes I have been trying to use are not marked as such.
This leads me to wondering if CastRemoteDisplayLocalService and all other Remote Display classes not marked as deprecated are in fact deprecated and unusable, or if perhaps the functionality was shifted to work in a Custom Receiver by configuring it to accept remote displays.
This is what the relevant code looks like right now:
MainActivity.kt
private fun startCastService() {
val intent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
val notificationSettings = CastRemoteDisplayLocalService.NotificationSettings.Builder().setNotificationPendingIntent(pendingIntent).build()
CastRemoteDisplayLocalService.startService(this, CastRemoteDisplayLocalServiceImpl::class.java, "2839EC8D", castDevice, notificationSettings, object : CastRemoteDisplayLocalService.Callbacks {
override fun onRemoteDisplaySessionEnded(p0: CastRemoteDisplayLocalService?) {
Log.d(TAG, "onRemoteDisplaySessionEnded")
}
override fun onRemoteDisplaySessionError(p0: Status?) {
Log.d(TAG, "onRemoteDisplaySessionError")
}
override fun onRemoteDisplaySessionStarted(p0: CastRemoteDisplayLocalService?) {
Log.d(TAG, "onRemoteDisplaySessionStarted")
}
override fun onServiceCreated(p0: CastRemoteDisplayLocalService?) {
Log.d(TAG, "onServiceCreated")
}
})
}
CastRemoteDisplayLocalServiceImpl.kt
class CastRemoteDisplayLocalServiceImpl : CastRemoteDisplayLocalService() {
val TAG = "CastRemoteDisplayLoc..."
// This function gets called
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate")
}
// This function does not get called
override fun onCreatePresentation(p0: Display?) {
Log.d(TAG, "onCreatePresentation")
}
override fun onDismissPresentation() {
Log.d(TAG, "onDismissPresentation")
}
}
If there's a way with the Custom Application Receiver to get the onCreatePresentation callback that would solve this, I'm having difficulty finding it. If CastRemoteDisplayLocalService is in fact deprecated, is there another way to easily cast Android views to a Chromecast? Thanks!

Categories

Resources