Comments (27)
Agent comment from yating.liao in Zendesk ticket #110093:
1. Do I need to disable MediaManager if I want to take photos again? -- Yes. After exiting the playback mode, you can take photos.
2. Do I need to call pullMediaFileListFromCamera again, if I disabled MediaManager? -- No.The file list will update automatically, even if you disable MediaManager.
3. Does MediaDataCenter.getInstance().mediaManager.mediaFileListData updates by itself or I need to call pullMedia again. -- Yes, it will update automatically. The file list status UP_TO_DATE indicates that the update is complete.
°°°
from mobile-sdk-android-v5.
@antonymarion We can discuss under the issue you created, which will continue to track the problem with @IakovlevAA .
from mobile-sdk-android-v5.
Why are you putting sleeping timer and not using (nesting your code) into success callback instead ?
For instance enable is followed by sleep, why don't you put the code after the sleep into the success callback of enable instead ?
from mobile-sdk-android-v5.
I think I'll try your method, but theoretically I don't need to nest it because for example:
MediaDataCenter.getInstance().mediaManager.enable(object :
CommonCallbacks.CompletionCallback {
override fun onSuccess() {
var currentTime = System.currentTimeMillis()
MediaDataCenter.getInstance().mediaManager.pullMediaFileListFromCamera(
PullMediaFileListParam.Builder().mediaFileIndex(-1).count(-1).filter(MediaFileFilter.PHOTO).build(),
object :
CommonCallbacks.CompletionCallback {
override fun onSuccess() {
ToastUtils.showToast("Spend time:${(System.currentTimeMillis() - currentTime) / 1000}s")
println("fetch success")
mediafiles = MediaDataCenter.getInstance().mediaManager.mediaFileListData.data
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("fetch failed$error")
}
})
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("error is ${error.description()}")
}
})
This code, if I understood you, doesn't look correct to me...
from mobile-sdk-android-v5.
This code is correct, this is kind of callback hell (will lead to nested callback inside nested callback and so on), but it is the correct way to handle asynchronous execution.
Promise Like with await/async is much better to read: https://kotlinlang.org/docs/composing-suspending-functions.html#concurrent-using-async
https://kotlinlang.org/docs/async-programming.html
from mobile-sdk-android-v5.
Thanks for tips! Interesting what others think about it. I'm just 100% confident, that there is another way, but not nesting callbacks
from mobile-sdk-android-v5.
Yes async await as explained in the docs above.
Callback is error prone and not maintanable.
Promise with then is better for maintenance.
Async await is the best option
from mobile-sdk-android-v5.
By the way, I tested right now (removing all the timers) I have no issue of slow down like you have, I believe that your timer does not help..
from mobile-sdk-android-v5.
Do you mean slow down of fetching mediafiles or pulling image? Without timers I couldn't get code to work at all
from mobile-sdk-android-v5.
As Antony mentioned, I tried nesting callbacks. Also I found, that if you call CameraKey.KeyStartShootPhoto.create().action() and after that trying to do something with MediaDataCenter or MediaManager it will process comands a very long time(enabling will always fail btw). So, that was the reason why fetching and downloading was too slow
from mobile-sdk-android-v5.
Call enabling with MediaManager instead.
It will work then
from mobile-sdk-android-v5.
No, still failing with this code
fun takePhoto(callback: CommonCallbacks.CompletionCallback) {
RxUtil.setValue(
KeyTools.createKey<CameraMode>(
CameraKey.KeyCameraMode
), CameraMode.PHOTO_NORMAL)
.andThen(RxUtil.performActionWithOutResult(KeyTools.createKey(CameraKey.KeyStartShootPhoto)))
.subscribe({ CallbackUtils.onSuccess(callback) }
) { throwable: Throwable ->
CallbackUtils.onFailure(
callback,
(throwable as RxError).djiError
)
}
}
fun shootPhoto()
{
takePhoto(object : CommonCallbacks.CompletionCallback {
override fun onSuccess() {
ToastUtils.showToast("take photo success")
var currentTime = System.currentTimeMillis()
MediaManager.getInstance().enable(object :
CommonCallbacks.CompletionCallback {
override fun onSuccess() {
ToastUtils.showToast("enable playback success")
val mediaSource = MediaFileListDataSource.Builder().setLocation(CameraStorageLocation.SDCARD).build()
MediaDataCenter.getInstance().mediaManager.setMediaFileDataSource(mediaSource)
MediaDataCenter.getInstance().mediaManager.pullMediaFileListFromCamera(
PullMediaFileListParam.Builder().mediaFileIndex(-1).count(-1).filter(MediaFileFilter.PHOTO).build(),
object :
CommonCallbacks.CompletionCallback {
override fun onSuccess() {
ToastUtils.showToast("Spend time:${(System.currentTimeMillis() - currentTime) / 1000}s")
println("fetch success")
mediafiles = MediaDataCenter.getInstance().mediaManager.mediaFileListData.data
downloadFile()
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("fetch failed$error")
}
})
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("error is ${error.description()}")
}
})
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("take photo failed")
}
})
}
Noticed that there is an error with this code
java.lang.NoClassDefFoundError: Failed resolution of: Ldji/v5/common/callback/CommonCallbacks$CompletionCallback;
But if I insert this code in begining of function shootPhoto
if(CameraKey.KeyIsShootingPhoto.create().get() == true)
{
CameraKey.KeyStopShootPhoto.create().action()
}
MediaManager won't be enabled
from mobile-sdk-android-v5.
Weird.
Working on my side, I use 300 RTK for testing
If ever you do not find with the official DJI support then go to my profile page and take the $50 sponsor I will give you support.
from mobile-sdk-android-v5.
Tried another approach:
fun pullMedia()
{
var currentTime = System.currentTimeMillis()
MediaManager.getInstance().enable(object :
CommonCallbacks.CompletionCallback {
override fun onSuccess() {
ToastUtils.showToast("enable playback success")
val mediaSource = MediaFileListDataSource.Builder().setLocation(CameraStorageLocation.SDCARD).build()
MediaDataCenter.getInstance().mediaManager.setMediaFileDataSource(mediaSource)
MediaDataCenter.getInstance().mediaManager.pullMediaFileListFromCamera(
PullMediaFileListParam.Builder().mediaFileIndex(-1).count(-1).filter(MediaFileFilter.PHOTO).build(),
object :
CommonCallbacks.CompletionCallback {
override fun onSuccess() {
ToastUtils.showToast("Spend time:${(System.currentTimeMillis() - currentTime) / 1000}s")
println("fetch success")
mediafiles = MediaDataCenter.getInstance().mediaManager.mediaFileListData.data
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("fetch failed$error")
}
})
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("error is ${error.description()}")
}
})
}
fun shootPhoto(): ByteArray {
rotateCamera()
KeyManager.getInstance().performAction(KeyTools.createKey(CameraKey.KeyResetCameraSetting), object: CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>{
override fun onSuccess(t: EmptyMsg?) {
ToastUtils.showToast("reset photo success")
KeyManager.getInstance().performAction(KeyTools.createKey(CameraKey.KeyStartShootPhoto), object: CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>{
override fun onSuccess(t: EmptyMsg?) {
ToastUtils.showToast("take photo success")
pullMedia()
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("take photo failed $error")
}
})
}
override fun onFailure(error: IDJIError) {
ToastUtils.showToast("reset photo failed $error")
}
})
First shoot is ok, but after that CameraKey.KeyStartShootPhoto returns CANNOT_START_TASK_VLOTAGE_ALARM error. I've read that I must set camera mode, but it doesn't help
from mobile-sdk-android-v5.
Agent comment from yating.liao in Zendesk ticket #110093:
I have reviewed your code. After switching the camera mode, you directly take a photo and then use mediaManager to retrieve the information. The sequence is correct, but we need to consider the time required for the camera to switch modes and generate the photo.
I would recommend adjusting your code according to this logic:
- Listen for changes in KeyCameraMode to determine when the camera has completed the mode switch. The success of setValue only indicates that the camera has successfully received the command.
- Add a MediaFileListStateListener to monitor the status of media files. After taking a photo, the camera will generate the corresponding file, and the file list status can indicate whether the camera has completed writing the file. UP_TO_DATE indicates that the file list is up to date, and you can directly retrieve the latest file type using getMediaFileListData. Typically, the latest photo is placed first. It is worth to noting that you need to call pullMediaFileListFromCamera at least once to initialize the listener and file list.
- Before downloading the file, use MediaManager.getInstance().enable to put the camera into playback mode. You can use CameraKey.KeyIsPlayingBack to determine if it is in playback mode.
°°°
from mobile-sdk-android-v5.
Thanks, I'll try this. I have some questions:
- Do I need to disable MediaManager if I want to take photos again?
- Do I need to call pullMediaFileListFromCamera again, if I disabled MediaManager?
- Does MediaDataCenter.getInstance().mediaManager.mediaFileListData updates by itself or I need to call pullMedia again
from mobile-sdk-android-v5.
Agent comment from yating.liao in Zendesk ticket #110093:I have reviewed your code. After switching the camera mode, you directly take a photo and then use mediaManager to retrieve the information. The sequence is correct, but we need to consider the time required for the camera to switch modes and generate the photo.
I would recommend adjusting your code according to this logic:
- Listen for changes in KeyCameraMode to determine when the camera has completed the mode switch. The success of setValue only indicates that the camera has successfully received the command.
- Add a MediaFileListStateListener to monitor the status of media files. After taking a photo, the camera will generate the corresponding file, and the file list status can indicate whether the camera has completed writing the file. UP_TO_DATE indicates that the file list is up to date, and you can directly retrieve the latest file type using getMediaFileListData. Typically, the latest photo is placed first. It is worth to noting that you need to call pullMediaFileListFromCamera at least once to initialize the listener and file list.
- Before downloading the file, use MediaManager.getInstance().enable to put the camera into playback mode. You can use CameraKey.KeyIsPlayingBack to determine if it is in playback mode.
°°°
Just to make sure, you said "Listen for changes in KeyCameraMode", but, is it necessary to listen if we can simply use RxUtil.setValue
to cameraMode PHOTO_NORMAL and chain the promise using andThen
instead ?
Normally, if the Promise is returned after the CameraMode has resolved, it should already be in the right state to take the Photo. So, no need to create a dedicated listener for this, right?
from mobile-sdk-android-v5.
Thanks, it helped a lot! Yet, one another question: Is it necessary to enter playaback mode to download photos? As I can see, I can enable MediaManager, start pulling photos and as it updates without MediaManager, I can just look for photo by its index. So, in short - does pullOriginalMediaFileFromCamera need playback mode enabled?
from mobile-sdk-android-v5.
And please do not forget my question about chained promises using RxUtil setValue.
It is quite critical to know if we can rely on promises in DJI's SDK or if we have to set listeners and trigger some logic on events received instead, as you proposed...
from mobile-sdk-android-v5.
Agent comment from yating.liao in Zendesk ticket #110093:
Do you mean if the callback result of the SDK interface can be used as the result for the next step in RxUtil? I would recommend using the listeners provided by the SDK as the callback result of the SDK interface does not represent the execution result of the drone. This is also the approach that Mobile SDK has always taken.
°°°
from mobile-sdk-android-v5.
Well, it answers to my question, but the fact that "this is also the approach that Mobile SDK has always taken." is not a justification if you place yourself at the users' perspective.
You said "the callback result of the SDK interface does not represent the execution result of the drone".
So it confirms what I noticed and did not expect from an SDK. But I prefered to be sure and to have your confirmation.
Do you believe the DJI's SDK will handle callback/promises as expected in a near future?
Promise or Callback are designed to be chained, and if it is not possible with DJI's SDK then it is a design flaw inside the SDK.
from mobile-sdk-android-v5.
Tried method with listening mediaFileListState. I come to a problem with pullMedia. When drone starts and I take photo mediaFileListState becomes UPDATING permanently, and this changes only if I call pullMedia once again or takePhoto. Also my question was left without answer....
does pullOriginalMediaFileFromCamera or pullPreviewFromCamera need playback mode enabled?
from mobile-sdk-android-v5.
Agent comment from yating.liao in Zendesk ticket #110093:
Is the latest version of MSDK being used by you? This issue was present in earlier versions, but it has been fixed in the new version.
°°°
from mobile-sdk-android-v5.
yes, just tried in Sample app. In Widget tool -> Media Playback -> take photo. State is UPDATING, until I push fetch media. Also found, if I take photo and immediately push enable(Media Manager), state is stucked in Updating, until new photo is taken
from mobile-sdk-android-v5.
My goal is to download photo as soon as it was taken. Right now I'm struggling with strange behaviour
- Take photo with RxUtil (sometimes failing with REQUEST_HANDLER_NOT_FOUND, reason - unknown)
- Start pulling the exact photo I've taken with CameraKey.KeyNewlyGeneratedMediaFile.create().get()?.index
val index = CameraKey.KeyNewlyGeneratedMediaFile.create().get()?.index ?: -1
val count = if(index == -1) -1 else 1
val mediaSource = MediaFileListDataSource.Builder().setLocation(CameraStorageLocation.SDCARD).build()
MediaDataCenter.getInstance().mediaManager.setMediaFileDataSource(mediaSource)
MediaDataCenter.getInstance().mediaManager.pullMediaFileListFromCamera(
PullMediaFileListParam.Builder().mediaFileIndex(index).count(count).filter(MediaFileFilter.PHOTO).build(), object : CommonCallbacks.CompletionCallback {
override fun onSuccess() {
cameraStateActivity.postValue("Pull media success")
}
override fun onFailure(error: IDJIError) {
cameraStateActivity.postValue("fetch failed ${error.description()}")
errorHappened = true
}
})
This called once fileListState is IDLE
3. Once mediaFileList is updated I'm enabling MediaManager
if (mediaFileListState == MediaFileListState.UP_TO_DATE)
{
MediaDataCenter.getInstance().mediaManager.stopPullMediaFileListFromCamera()
val data = MediaDataCenter.getInstance().mediaManager.mediaFileListData;
mediaFileListData.postValue(data)
MediaManager.getInstance().enable(object :
CommonCallbacks.CompletionCallback {
override fun onSuccess()
{
downloadFile()
}
override fun onFailure(error: IDJIError) {
println("$error")
}
})
}
P.S On this stage after taking photo may never ends, and so mediaFileListState is UPDATING permanently
4. Call mediaFile.pullPreviewFromCamera on mediaFile I pulled
Sometimes, pulling just don't work and it pull old photos or never pull at all.
You can reproduce the same in Sample App, by tapping buttons very fast(take photo->fetch media->enable). FileState will stuck in infite update
from mobile-sdk-android-v5.
Agent comment from yating.liao in Zendesk ticket #110093:
The MediaManager.getInstance().enable method puts the camera into playback mode. In playback mode, it is not possible to take photos. The take photo interface will instead callback a photo capture failure, rather than continuously attempting to capture a photo.
It seems illogical to use the take photo interface without confirming the result of enabling MediaManager first.
°°°
from mobile-sdk-android-v5.
I do understand, that it is impossible to take photos while MediaManager is enabled. What I'm trying to show, that too fast switch between take photo and enable MediaManager causes troubles (even if I check that camera stopped shooting photo).
Right now I achieved my goal to download photo with this steps
Take photo -> sleep(5000) -> enable MediaManager -> wait for camera to enter playback mode -> pullMedia with index I got in CameraKey.KeyNewlyGeneratedMediaFile -> disable MediaManager(because in playback mode filestate stuck in infinite UPDATE) -> Wait for filestate to enter UP_TO_DATE -> enable MediaManager -> stopPullMediaFileListFromCamera -> download photo with mediaFile.pullPreviewFromCamera -> disable MediaManager
Only this method works for me. Listening for states or anything else mentioned in this always caused different problems, that I mentioned above. Closing this as I am pleased with results I've got
from mobile-sdk-android-v5.
Related Issues (20)
- DTM Follow HOT 1
- Determining Drone Drift in Indoor Environments with Poor GPS Reception HOT 11
- Set White balance and ISO - H20T HOT 10
- function pushFlyZoneLicensesToAircraft in Mini 3 error Fly safe error : LicenseUnlockNotSupported. HOT 7
- MediaManager enable returns an error HOT 2
- minSDK 26 support HOT 2
- Set wind speed in simulator HOT 4
- ISO AUTO renders black/dark on 300 RTK HOT 16
- Not possible to chain promises returned by SDK to implement sequential logic HOT 3
- Set home coordinates manually? HOT 5
- Reading radar data HOT 7
- Documentation - Exposure mode HOT 2
- Reason of sudden RTH HOT 10
- Set custom HeightLimitRange HOT 1
- How to directly connect an SD card inserted in a DJI drone to an FTP server HOT 1
- Target API Requirement change August 31st 2024 HOT 5
- Difference between MSDK sample Aircraft App Launching with 300 RTK vs Mini 3 Pro HOT 3
- Operating mechanism of MSDK HOT 5
- Thermal Camera Pointer HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mobile-sdk-android-v5.