I have video stream in mjpeg format, so I have read and implmented a lot of ways to work with it, but anything of these ways don't meet my requirments (also I was using webView packages, but now we should implement changing screen oreintation feature and webView dosen't have such thing, so I am using Hero animation to make it works, but in that case my urls with video stream open twice. It dosen't work because it has limitation: only one user can watch stream, in other cases stream will be closed).
So I have found the way to play mjepeg video using Kotlin, and read bout MethodChannel in Flutter, I implemented almost everything as it was said in docs, but it still dosen't work.
Native code:
class MainActivity: FlutterActivity() {
private val channel = "com.example.my_app"
private var view: MjpegView? = null
override fun configureFlutterEngine(#NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler {
call, result ->
if(call.method == "Video") {
view = findViewById(R.id.mjpegid)
view!!.isAdjustHeight = true
view!!.mode1 = MjpegView.MODE_FIT_WIDTH
view!!.setUrl("http://videos/videos/LiveViewCamera")
view!!.isRecycleBitmap1 = true
result.success("it successed!")
}
else {
result.notImplemented()
}
}
}
}
in Flutter:
final channel = MethodChannel('com.example.my_app');
String videos = '';
Future getVideoFromNative() async {
videos = await channel.invokeMethod('Video');
print(videos);
print('are you hehe?');
setState(() {});
}
Got this error:
E/MethodChannel#com.example.rosysk_nano_cleaned(17621): Failed to handle method call
E/MethodChannel#com.example.rosysk_nano_cleaned(17621): java.lang.NullPointerException
When I open it in pure Kotlin app, my video and code works perfectly fine
in editor work fine. i am trying to add my project fierbase and in work. but when i start test at android login window dont react. i am trying to do this
Unity3D firebase AUTH not working on ANDROID
public class FirebaseINIT : MonoBehaviour
{
public static bool firebaseReady;
void Start()
{
CheckIfReady();
}
void Update()
{
if(firebaseReady == true)
{
SceneManager.LoadScene("LoginScene");
}
}
public static void CheckIfReady()
{
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
Firebase.DependencyStatus dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available)
{
Firebase.FirebaseApp app = Firebase.FirebaseApp.DefaultInstance;
firebaseReady = true;
Debug.Log("Firebase is ready for use.");
}
else
{
firebaseReady = false;
UnityEngine.Debug.LogError(System.String.Format(
"Could not resolve all Firebase dependencies: {0}", dependencyStatus));
}
});
}
}
but not loaded next scene. and i am confused why this happen, i cant do next because dont understand problem. May this will be from android resolve? Because in order to build the project, I must remove the Resolved libraries.
otherwise if I don't remove assets=> Android=> resolve libraries then I will get the following errors
Configure project :launcher
WARNING: The option setting 'android.enableR8=false' is deprecated.
Execution failed for task ':launcher:processReleaseResources'.
A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
Android resource linking failed
the project has an additional plugin for advertising appodeal + admob at least the direction of movement of the study of the issue
and i am integrate this first time i am not sure i am at the right way
I have implemented the notificationServiceExtension as mentioned by onesignal in it's documentation but now I am not being able to run background notification handler in one signal.
I have implemented the following code in main activity:::
package com.example.just_normal
import com.onesignal.OneSignal
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
private val methodchannel = "background/notification";
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
OneSignal.OSRemoteNotificationReceivedHandler { context, osNotificationReceivedEvent ->
val CHANNEL : MethodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger , methodchannel)
CHANNEL.invokeMethod("onBackgroundNotification" , osNotificationReceivedEvent);
// osNotificationReceivedEvent.complete(null);
}
}
}
In the above code I am trying to call the flutter method immediately after the notification has been received in the background. How can I run flutter method immediately after notification is received in backgound. Please help....
use this in the init function where you are registering onesignal in the app:
OneSignal.shared.setNotificationWillShowInForegroundHandler((OSNotificationReceivedEvent event) {
event.complete(event.notification);
});
Now you will be able to get notifications even when the app got killed.
TL;DR how can I have an Android sensor permanently running/active/registered for my app, even if I close it?
Objective:
I'm making a Flutter application that counts your steps using the pedometer package,
which uses the built-in sensor TYPE_STEP_COUNTER of Android,
which returns the # of steps taken since last boot (iOS). On Android, any steps taken before installing the app are not counted.
How I implemented it:
When the app is actively running in the foreground, each step causes
a myStepCount to increment by 1.
In all other cases (phone locked, went to home-screen, closed the app...), the android TYPE_STEP_COUNTER sensor should
still be running in the background, and once I open my app again, the
difference between new stepCount and last saved stepCount (saved
using shared_prefs) will be calculated and added to myStepCount.
Important:
The TYPE_STEP_COUNTER sensor must be permanently running/stay registered in the background, even after I lock my phone, go to the home-screen, or close the app...
Observations:
On my Samsung Galaxy A02s, my app works perfectly fine, as it it supposed to
(as described above). That is because on that phone I also have the
Google Fit app installed, which tracks your steps 24/7 (so the
TYPE_STEP_COUNTER sensor is permanently registered).
On my Samsung Galaxy S7, my app does not work as it's supposed to.
myStepCount gets incremented when I take steps while the app is
running in the foreground. But steps taken while the app is closed
will NOT be added to myStepCount once I open the app again.
Note: I don't have any other step-counting-apps like Google Fit on this phone.
Conclusion:
I need to find a way to register the TYPE_STEP_COUNTER sensor from my Flutter app, and keep it registered even after I close the app.
2 Attempted (but unsuccessful) Solutions:
1st Attempt:
Calling Native Android Code from my Flutter Code to register the sensor
This is my main.dart file (with the unimportant parts left out for simplicity):
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(App());
}
class App extends StatefulWidget {
#override
_AppState createState() => _AppState();
}
class _AppState extends State<App> with WidgetsBindingObserver {
#override
void initState() {
super.initState();
if (Platform.isAndroid) {
_activateStepCounterSensor();
} else if (Platform.isIOS) {
//TODO check if anything is needed to to here
}
}
void _activateStepCounterSensor() async {
MethodChannel _stepCounterChannel = MethodChannel('com.cedricds.wanderapp/stepCounter'); //convention
dynamic result = await _stepCounterChannel.invokeMethod('activateStepCounterSensor');
switch (result) {
case "success":
//The following line gets printed when I run the flutter app on my Samsung Galaxy S7:
print('_activateStepCounterSensor(): successfully registered step counter sensor for android');
break;
case "error":
print('_activateStepCounterSensor(): failed to register step counter sensor (not available) for android');
//TODO display errorpage (because app is completely useless in this case)
break;
default:
print('_activateStepCounterSensor(): unknown result: $result');
break;
}
}
//build() and other lifecycle-methods and helper methods: not important for this question
}
This is my MainActivity.kt file:
package com.cedricds.wanderapp
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.util.Log
import android.widget.Toast
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity2: FlutterActivity(), SensorEventListener {
private val STEP_COUNTER_CHANNEL = "com.cedricds.wanderapp/stepCounter";
private lateinit var channel: MethodChannel
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, STEP_COUNTER_CHANNEL)
channel.setMethodCallHandler { call, result ->
when(call.method){ //this is like switch-case statement in Java
"activateStepCounterSensor" -> {
activateStepCounterSensor(result)
}
}
}
}
private var sensorManager : SensorManager?=null
private var sensor: Sensor ?= null
private fun activateStepCounterSensor(result: MethodChannel.Result) {
//This line gets printed when I run the flutter app, so the method gets called successfully:
Log.d("Android", "Native Android: activateStepCounterSensor()")
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
if (sensor == null) {
Toast.makeText(this, "missing hardware.", Toast.LENGTH_LONG).show()
result.error("error", "error", "error")
} else {
sensorManager?.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL)
//This line gets printed:
Log.d("Android", "Native Android: registered TYPE_STEP_COUNTER")
//and never unregister that listener
result.success("success")
}
}
override fun onSensorChanged(p0: SensorEvent?) {}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {}
}
Despite the few print(...) and Log.d(...) being printed in the console as expected, the app doesn't work how I expected it to work. When I exit the app, walk for example 50 steps, then open the app again, those 50 steps are missing. It seems the sensor is being unregistered somewhere.
2nd Attempt:
Modifying the pedometer package's code by removing unregisterListener(...):
The only changes I did to the file were 2 Log.d(...) statements and more importantly, commenting out a specific line of code.
modified SensorStreamHandler.kt from the pedometer package:
package com.example.pedometer
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Looper
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.EventChannel
import android.os.Handler
import android.util.Log
class SensorStreamHandler() : EventChannel.StreamHandler {
private var sensorEventListener: SensorEventListener? = null
private var sensorManager: SensorManager? = null
private var sensor: Sensor? = null
private lateinit var context: Context
private lateinit var sensorName: String
private lateinit var flutterPluginBinding: FlutterPlugin.FlutterPluginBinding
constructor(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding, sensorType: Int) : this() {
this.context = flutterPluginBinding.applicationContext
this.sensorName = if (sensorType == Sensor.TYPE_STEP_COUNTER) "StepCount" else "StepDetection"
sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager!!.getDefaultSensor(sensorType)
this.flutterPluginBinding = flutterPluginBinding
}
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
Log.d("Pedometer", "Native Android: onListen()")
if (sensor == null) {
events!!.error("1", "$sensorName not available",
"$sensorName is not available on this device");
} else {
sensorEventListener = sensorEventListener(events!!);
sensorManager!!.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
override fun onCancel(arguments: Any?) {
Log.d("Pedometer", "Native Android: onCancel()")
//The only change I did: commenting out the following line:
// sensorManager!!.unregisterListener(sensorEventListener);
}
}
This also did not solve my problem. So if someone knows how I can permanently register the TYPE_STEP_COUNTER sensor in my flutter app, please let me know.
Update:
I've contacted one of the developers of the pedometer package, and he suggested me to use flutter_foreground_service (which is developed by the same team/company as pedometer). It works.
But I would still find it interesting, if there is another way (maybe similar to my 2 failed attempts).
I know these libraries flutter_isolate and isolate_handler exist that support doing these but I couldn't find any method to call platform specific codes from inside of them. Can someone show any example of how it's done ?
My answer might not answer to your question directly but I was facing the same situation.
I was working on this to run a computing intensive task avoiding UI lagging. After a long research, no, you cannot run Platform from other isolates rather than the main one.
Instead of making and running the native code on another isolate, let's make the native code run in background instead with TaskQueue.
Channels and platform threading
The example code in the above link is using onAttachedToEngine, you can check it out. However, I was using is configureFlutterEngine so I have to figure out a little bit until I found a solution that I need binaryMessenger to make it working. Luckily it can called from flutterEngine too!
This is the example code of when using configureFlutterEngine
class MainActivity: FlutterFragmentActivity() {
val MOBILE_SDK_CHANNEL = "com.example.app/flutter"
override fun configureFlutterEngine(#NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
super.configureFlutterEngine(flutterEngine)
val taskQueue = flutterEngine.dartExecutor.binaryMessenger.makeBackgroundTaskQueue()
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, MOBILE_SDK_CHANNEL,
StandardMethodCodec.INSTANCE, taskQueue).setMethodCallHandler { call, result ->
// TODO : Do implementation here
when (call.method) {
"example_method" -> {
// success
// result.success(data)
}
else -> result.notImplemented()
}
}
}
}
With taskQueue the native code will be ready to run in background.
Future<void> getData() async {
if (Platform.isAndroid) {
const platform = MethodChannel("com.example.app/flutter");
var data = await platform.invokeMethod("example_method");
// data is ready to use and non-blocked the UI thread
return data
}
}
The native code now runs in non-blocking manner, no more UI lag. :)