I'm trying and failing to get a camera-feed on the Mavic Enterprise 2 dual, using the Mobile SDK. I am connected to the drone, and my app runs fine and displays the video with both the Mini2 and Air 2S. I am on MSDK 4.16.4.
It seems like the problem video-data listener, defined in activity onCreate, is never called. Here is the snippet of relevant code. On the Mini2 and Air2S (with R1-N1 controller), the video-data-listener is called. On the ME2 Dual (with the controller that came with the drone), the video-data-listener is never called.
textureView.surfaceTextureListener = FakeTextureView(
codecCallback = {
mCodecManager = it
primaryVideoFeed.addVideoDataListener { videoBuffer, size ->
freshFrameAvailable = true
mCodecManager?.sendDataToDecoder(videoBuffer, size)
}
},
applicationContext = applicationContext
)
Is there some extra step required for ME2 Dual that I'm missing?
Related
I've been searching on this for quite some time, and have found lots of solutions that ultimately use the Android GUI to prompt the end-user for connection/confirmation. We would like to present a user with a form and directly connect to the specified network. I understand from a security perspective why this is necessary, but in our case, it is a system app going on a fully managed Android device. It is not intended for general use in the Play store. We are using Xamarin, but I can adapt any Java/Kotlin code.
The closest I've found thus far is the following (using C#):
public void ConnectToWifi(string ssid, string password = "") {
var wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder().SetSsid(ssid);
if (!string.IsNullOrEmpty(password))
wifiNetworkSpecifier.SetWpa2Passphrase(password);
var networkRequest = new NetworkRequest.Builder().AddTransportType(TransportType.Wifi)?
.SetNetworkSpecifier(wifiNetworkSpecifier.Build())?.Build();
if (networkRequest is null)
return;
var theNetworkCallback = new TheNetworkCallback();
var connectivityManager = (ConnectivityManager?)MainActivity.Current.ApplicationContext?
.GetSystemService(Context.ConnectivityService);
connectivityManager?.RequestNetwork(networkRequest, theNetworkCallback);
}
It sorta works, but does prompt the end-user, and my understanding, this approach is deprecated and doesn't work well in newer versions of Android. We're hoping for a solution that works in Android 11.
I'm even fine if there's a solution to write directly to wifi files on the OS. I've seen various solutions to manually populate entries via ADB, but I'm having a tough time adapting that to Xamarin/Java (can't seem to access the /data/misc/wifi directories). Again, this is intended for use exclusively on our own managed devices.
I have a blog post about this topic here: https://blog.ostebaronen.dk/2020/11/android-11-wifi.html
Android Network API is not the greatest thing to work with as there are pitfals depending on the API level the code runs on.
From Android 10 and up a lot of the Network stuff has been restricted for "privacy" reasons, so you cannot work around not asking the user for input, unless the device is rooted or your App is set up as Device Admin.
For Android 11, there is a new API to present a system dialog and allow the user to save and connect to a network. This will look something like:
You can launch this through an Intent called android.settings.WIFI_ADD_NETWORKS:
var intent = new Intent(
"android.settings.WIFI_ADD_NETWORKS");
var bundle = new Bundle();
bundle.PutParcelableArrayList(
"android.provider.extra.WIFI_NETWORK_LIST",
new List<IParcelable>
{
new WifiNetworkSuggestion.Builder()
.SetSsid(ssid)
.SetWpa2Passphrase(password)
.Build()
});
intent.PutExtras(bundle);
StartActivityForResult(intent, AddWifiSettingsRequestCode);
You can then get the result in your Activity overriding OnActivityResult and fetching the result like so:
if (requestCode == AddWifiSettingsRequestCode)
{
if (data != null && data.HasExtra(
"android.provider.extra.WIFI_NETWORK_RESULT_LIST"))
{
var extras =
data.GetIntegerArrayListExtra(
"android.provider.extra.WIFI_NETWORK_RESULT_LIST")
?.Select(i => i.IntValue()).ToArray() ?? new int[0];
if (extras.Length > 0)
{
var ok = extras
.Select(GetResultFromCode)
.All(r => r == Result.Ok);
// if ok is true, BINGO!
return;
}
}
}
I have a repository here with the full sample: https://github.com/Cheesebaron/Android11WiFi
From using this in the wild, I've found that this API does not work nicely with some OEMs such as OnePlus and Huawei. Some of these either restrict or the System Settings App simply crashes due to a misconfiguration on their part. For those I fall back to the API's introduced in Android 10.
scenario:
have an application in flutter with a hard-coded list of 20 cards after a release build of this on my 120 fps devices it still feels like 60 fps how to fix it while the native android counterpart has a smooth render at 120 fps.
have tries the above scenario will the scrolling based widget both builder-based and normal ones.
Is it a flaw in flutter that it doesn't render at 120 fps.
On Android phones with 120hz display by default is chosen the wrong display mode (e.g. 60hz instead 120hz). This can easily be corrected, then performance on phones like Oneplus 8T or Galaxy S20+ is great.
Import flutter_displaymode library:
flutter_displaymode: ^0.3.0-nullsafety.0
Add this to your root widget (stateful):
class _YourAppState extends State<YourApp> {
#override
void initState() {
setOptimalDisplayMode();
super.initState();
}
Future<void> setOptimalDisplayMode() async {
final List<DisplayMode> supported = await FlutterDisplayMode.supported;
final DisplayMode active = await FlutterDisplayMode.active;
final List<DisplayMode> sameResolution = supported.where(
(DisplayMode m) => m.width == active.width
&& m.height == active.height).toList()..sort(
(DisplayMode a, DisplayMode b) =>
b.refreshRate.compareTo(a.refreshRate));
final DisplayMode mostOptimalMode = sameResolution.isNotEmpty
? sameResolution.first
: active;
/// This setting is per session.
/// Please ensure this was placed with `initState` of your root widget.
await FlutterDisplayMode.setPreferredMode(mostOptimalMode);
}
}
Note, that right now there are no 120hz iPhones, so there is no need to execute them.
You must profile your performance metrics. check out this https://flutter.dev/docs/perf/rendering/ui-performance
Please try this, you can use media query for sizing your widget.
MediaQuery.of(context).size
I'm trying to launch a second activity on a secondary display. This works fine on the emulators, but I need the secondary display to handle touch events.
With Android Pie, launching an activity on some second displays would throw a security exception. Google recently pushed out this new API for Android Q - isActivityStartAllowedOnDisplay() (https://developer.android.com/reference/android/app/ActivityManager.html#isActivityStartAllowedOnDisplay(android.content.Context,%2520int,%2520android.content.Intent)) - to be able to tell if the second display has this security exception or not.
This new API is helpful, BUT, is there any way around it? Maybe I've misunderstood the documentation, but it seems like if the device doesn't support it, then there's no way around it. Does anyone know of any displays that will NOT throw this security exception?
In order to get touch events to register on the secondary display (GeChic Touch Monitor), I had a DisplayLink device connected between the Android device and touch display. At this point, it was mirroring the view on the phone/tablet but would handle touch events. So, I wrote an app that would attempt to launch a second activity on the second display using this code on Android Pie OS:
DisplayManager mgr = (DisplayManager) this.getBaseContext().getSystemService(Context.DISPLAY_SERVICE);
if (mgr != null) {
Display[] displays = mgr.getDisplays();
for (int i = 0; i < displays.length; i++) {
Display display = displays[i];
Point point = new Point();
display.getSize(point);
if (point.y == PX_HEIGHT_OF_SECONDARY_DISPLAY || point.x == PX_HEIGHT_OF_SECONDARY_DISPLAY) {
Context displayContext = createDisplayContext(display);
Intent newIntent = new Intent(displayContext, ActivityCID.class);
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(display.getDisplayId());
newIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent, options.toBundle());
return;
}
}
}
Note that I did not use display.getDisplayId() and did a hacky way with the point.y and point.x values with a pixel width or height that did not match the pixel width or height of the Android phone/tablet. The displayId() was not always a consistent value which "should" be stable in Android Q. This is where the app would crash and the second activity would fail with a security permissions error. So, I used Android Q Beta to test the new isActivityStartAllowedOnDisplay() API. I ran this through Android Studio onto the phone (which was on Android Q Beta OS) to run it and to no surprise, the secondary display came back false. See code below:
public void launchOnSecondaryDisplay(Display display) {
Context displayContext = createDisplayContext(display);
Intent newIntent = new Intent(displayContext, ActivityTest.class);
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Activity.ACTIVITY_SERVICE);
if (activityManager != null) {
boolean allowsDisplay = activityManager.isActivityStartAllowedOnDisplay(displayContext, display.getDisplayId(), newIntent);
if (allowsDisplay) {
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(display.getDisplayId());
newIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent, options.toBundle());
} else {
Toast.makeText(this, "Cannot start activity on that display as it is not supported.", Toast.LENGTH_LONG).show();
}
}
}
I decided to try this through the command line. After networking the physical device to match my Mac's connected network, I was able to connect to the phone wirelessly and was able to make changes in adb. Using an adb command, I was able to get a secondary activity on the secondary display! It seemed to be working! But no, it was not... Touch events still continued to act like the device was being mirrored so this was still a problem and was not going to work.
I discussed this with the Googler as well and was explained that adb root can override these permissions. However, there was still no way to get the touch events to map to the second activity on the secondary display.
At the moment of writing this, the only supported way to test multi touch displays is to use a physical device running Android Q Beta and follow these steps:
enable developer options,
in developer options, enable these 4 options: Force All Activities to be Resizeable, Freeform Windows, Force Desktop, and Simulate Secondary Display (doesn't matter which option picked for simulate secondary display),
reboot the device,
connect a mouse to the device. The mouse will show up and be stuck inside the overlaying window that is "simulating the secondary display". This will handle touch events.
In the future, there will be emulators that have multiple displays to better test multi display applications but this is not available at the moment.
How can I differentiate between a TV and a STB/game console on AndroidTV programatically? This method (https://developer.android.com/training/tv/start/hardware) won't work because an STB running AndroidTV is considered a television.
What's Your Goal?
The obvious reason for doing this would be to determine if a device is suitable for a game to be played on. If it's for any other reason, then the purpose needs to be elaborated on in order to receive applicable assistance.
With that said ...
Since it's not possible to query the device type directly -- personally, I'd look for something that only a game console would be likely to have.
In other words: a game controller/gamepad.
public ArrayList<Integer> getGameControllerIds() {
ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>();
int[] deviceIds = InputDevice.getDeviceIds();
for (int deviceId : deviceIds) {
InputDevice dev = InputDevice.getDevice(deviceId);
int sources = dev.getSources();
// Verify that the device has gamepad buttons, control sticks, or both.
if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|| ((sources & InputDevice.SOURCE_JOYSTICK)
== InputDevice.SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
if (!gameControllerDeviceIds.contains(deviceId)) {
gameControllerDeviceIds.add(deviceId);
}
}
}
return gameControllerDeviceIds;
}
Of course, it's not fool-proof. Obviously, nothing would be returned if the gamepad(s) were unplugged at the time (not sure when that would happen). Not to mention, some TVs support gamepads (Samsung comes to mind first) -- but, if you're intention is to verify that there's an adequate input available for the application, this would be ideal.
If a gamepad isn't present, a message could be displayed stating, "Please connect a gamepad." -- while continuously checking in the background, and automatically proceeding once one is detected.
Recently I went thru the code for accessing the camera using flash ActionScript3 and I have tested the code in iMac machine, iPhone and Android.Now based on this, I am developing an application for Android which includes the accessibility of the front camera. Now my Problem is I dont know how to access the front camera? We should use some other code or should we specify which camera should be accessed? First of all, can we access the front camera thru flash?
I made a simple android app. Here is the code for selecting camera window
public class SelectCameraAlertAndroid extends StartAlertAndroid_design{
public function SelectCameraAlertAndroid() {
frontCameraButton.addEventListener(MouseEvent.CLICK, onFrontCamera);
backCameraButton.addEventListener(MouseEvent.CLICK, onBackCamera);
}
private function onFrontCamera(event:MouseEvent):void {
Model.model.camera = Camera.getCamera("1");
Model.model.cameraSelectedSignal.dispatch();
dispatchEvent(new Event("closeMe"));
}
private function onBackCamera(event:MouseEvent):void {
Model.model.camera = Camera.getCamera("0");
Model.model.cameraSelectedSignal.dispatch();
dispatchEvent(new Event("closeMe"));
}
}
Not true. You can access the front camera on Android.
The only problem is that you don't get to use the CameraUI(pretty sure).
var camera = Camera.getCamera("1");
camera.setMode(stage.stageWidth, stage.stageHeight, 30, true);
var video:Video = new Video(stage.stageWidth, stage.stageHeight);
video.attachCamera(camera);
addChild(video);
Note: This answer is outdated. Please refer to the other answers for updated information.
Currently, AIR only supports access to the primary camera on an Android device.
http://forums.adobe.com/thread/849983
Official documentation: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Camera.html#getCamera()
"On Android devices, you can only access the rear-facing camera."