### MApplication Class Setup Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/UXSDKDemo.html Extend Application and override attachBaseContext and onCreate to install the SDK helper and initialize the DemoApplication. This ensures SDK classes are loaded before use. ```java package com.dji.uxsdkdemo; import android.app.Application; import android.content.Context; import com.secneo.sdk.Helper; public class MApplication extends Application { private DemoApplication demoApplication; @Override protected void attachBaseContext(Context paramContext) { super.attachBaseContext(paramContext); Helper.install(MApplication.this); if (demoApplication == null) { demoApplication = new DemoApplication(); demoApplication.setContext(this); } } @Override public void onCreate() { super.onCreate(); demoApplication.onCreate(); } } ``` -------------------------------- ### Example pod install output Source: https://developer.dji.com/mobile-sdk/documentation/application-development-workflow/workflow-integrate.html This output indicates a successful installation of the DJI SDK. Remember to use the .xcworkspace file for future Xcode sessions. ```bash Analyzing dependencies Downloading dependencies Installing DJI-SDK-iOS (4.12) Generating Pods project Integrating client project [!] Please close any current Xcode sessions and use `ImportSDKDemo.xcworkspace` for this project from now on. Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed. ``` -------------------------------- ### Create FPVDemoApplication Class Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/index.html This class extends Android's Application class and overrides onCreate() to perform initial setup when the application starts. It serves as the entry point for application-level configurations. ```java package com.dji.FPVDemo; import android.app.Application; public class FPVDemoApplication extends Application{ @Override public void onCreate() { super.onCreate(); } } ``` -------------------------------- ### Run pod install command Source: https://developer.dji.com/mobile-sdk/documentation/application-development-workflow/workflow-integrate.html Execute this command in your project's root directory after creating or modifying the Podfile to install the SDK. ```bash pod install ``` -------------------------------- ### Install Ruby Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/RemoteLoggerDemo.html If you encounter errors related to Ruby, run this command to install it using Homebrew. This is a prerequisite for running the server script. ```bash sudo brew install ruby ``` -------------------------------- ### Install Command Line Developer Tools Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/RemoteLoggerDemo.html If you encounter errors related to command line tools, run this command to install them. This is a prerequisite for running the server script. ```bash xcode-select -install ``` -------------------------------- ### CocoaPods Installation Success Message Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/UXSDKDemo.html This is an example of the success message you should see after a successful pod installation. ```text Analyzing dependencies Downloading dependencies Installing DJI-SDK-iOS (4.12) Installing DJI-UXSDK-iOS (4.12) Installing DJIWidget (1.6.2) Generating Pods project Integrating client project [!] Please close any current Xcode sessions and use `UXSDKDemo.xcworkspace` for this project from now on. Sending stats Pod installation complete! There are 2 dependencies from the Podfile and 2 total pods installed. ``` -------------------------------- ### Update Pod Repo and Install Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/UXSDKDemo.html If you encounter dependency issues, update your local pod repository first and then run the install command again. ```bash pod repo update pod install ``` -------------------------------- ### Handle Button Click to Open Main Activity Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/index.html Implement the onClick listener for a button, typically used to navigate to another activity. This example shows how to start MainActivity when a specific button is clicked. ```java @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_open: { Intent intent = new Intent(this, MainActivity.class); startActivity(intent); break; ``` -------------------------------- ### Register App and Start Connection Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/P4MissionsDemo.html Handle the `appRegisteredWithError:` delegate method. If registration fails, disable mission buttons and show an alert. Otherwise, enable bridge mode or start the connection to the product based on the `ENTER_DEBUG_MODE` macro. ```Objective-C - (void)appRegisteredWithError:(NSError *)error { if (error) { NSString* message = @"Register App Failed! Please enter your App Key and check the network."; [self.tapFlyMissionButton setEnabled:NO]; [self.activeTrackMissionButton setEnabled:NO]; [self showAlertViewWithTitle:@"Register App" withMessage:message]; } else { NSLog(@"registerAppSuccess"); #if ENTER_DEBUG_MODE [DJISDKManager enableBridgeModeWithBridgeAppIP:@"172.20.10.0"]; #else [DJISDKManager startConnectionToProduct]; #endif } } ``` -------------------------------- ### Start Video Preview and Listener Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/P4MissionsDemo.html Configures the video previewer and registers the view controller as a listener for video feed updates in the viewWillAppear method. ```objective-c -(void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[DJIVideoPreviewer instance] setView:self.fpvView]; [[DJISDKManager videoFeeder].primaryVideoFeed addListener:self withQueue:nil]; [[DJIVideoPreviewer instance] start]; } ``` -------------------------------- ### Start Video Recording Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/index.html Initiates video recording using the camera instance. Shows a success or error message upon completion. ```java // Method for starting recording private void startRecord(){ final Camera camera = FPVDemoApplication.getCameraInstance(); if (camera != null) { camera.startRecordVideo(new CommonCallbacks.CompletionCallback(){ @Override public void onResult(DJIError djiError) { if (djiError == null) { showToast("Record video: success"); }else { showToast(djiError.getDescription()); } } }); // Execute the startRecordVideo API } } ``` -------------------------------- ### Initiate Video Playback Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/MediaManagerDemo.html Start playing a video, making the display image invisible. ```java private void playVideo() { mDisplayImageView.setVisibility(View.INVISIBLE); ``` -------------------------------- ### Redirect to DJI Go App (Android) Source: https://developer.dji.com/mobile-sdk/documentation/application-development-workflow/workflow-run.html Launches the DJI Go application if installed. Includes a null pointer check for safety. ```Java Intent launchIntent = getPackageManager().getLaunchIntentForPackage("dji.pilot"); if (launchIntent != null) { //null pointer check in case package name was not found startActivity(launchIntent); } ``` -------------------------------- ### MainActivity Setup and Permissions Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/GSDemo-Google-Map.html Initializes the MainActivity, requests necessary runtime permissions for Android M and above, sets the content view, and initializes the Google Map fragment. ```java public class MainActivity extends FragmentActivity implements View.OnClickListener, GoogleMap.OnMapClickListener, OnMapReadyCallback { protected static final String TAG = "MainActivity"; private GoogleMap gMap; private Button locate, add, clear; private Button config, upload, start, stop; @Override protected void onResume(){ super.onResume(); } @Override protected void onPause(){ super.onPause(); } @Override protected void onDestroy(){ super.onDestroy(); } /** * @Description : RETURN BTN RESPONSE FUNCTION */ public void onReturn(View view){ Log.d(TAG, "onReturn"); this.finish(); } private void initUI() { locate = (Button) findViewById(R.id.locate); add = (Button) findViewById(R.id.add); clear = (Button) findViewById(R.id.clear); config = (Button) findViewById(R.id.config); upload = (Button) findViewById(R.id.upload); start = (Button) findViewById(R.id.start); stop = (Button) findViewById(R.id.stop); locate.setOnClickListener(this); add.setOnClickListener(this); clear.setOnClickListener(this); config.setOnClickListener(this); upload.setOnClickListener(this); start.setOnClickListener(this); stop.setOnClickListener(this); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // When the compile and target version is higher than 22, please request the // following permissions at runtime to ensure the // SDK work well. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.VIBRATE, Manifest.permission.INTERNET, Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.WAKE_LOCK, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE, Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.SYSTEM_ALERT_WINDOW, Manifest.permission.READ_PHONE_STATE, } , 1); } setContentView(R.layout.activity_main); initUI(); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } ``` -------------------------------- ### Setup and Reset Video Previewer Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/index.html Implement methods to set up and reset the video previewer, handling different video feeds based on the aircraft model. ```Objective-C - (void)setupVideoPreviewer { [[DJIVideoPreviewer instance] setView:self.fpvPreviewView]; DJIBaseProduct *product = [DJISDKManager product]; if ([product.model isEqual:DJIAircraftModelNameA3] || [product.model isEqual:DJIAircraftModelNameN3] || [product.model isEqual:DJIAircraftModelNameMatrice600] || [product.model isEqual:DJIAircraftModelNameMatrice600Pro]){ [[DJISDKManager videoFeeder].secondaryVideoFeed addListener:self withQueue:nil]; }else{ [[DJISDKManager videoFeeder].primaryVideoFeed addListener:self withQueue:nil]; } [[DJIVideoPreviewer instance] start]; } - (void)resetVideoPreview { [[DJIVideoPreviewer instance] unSetView]; DJIBaseProduct *product = [DJISDKManager product]; if ([product.model isEqual:DJIAircraftModelNameA3] || [product.model isEqual:DJIAircraftModelNameN3] || [product.model isEqual:DJIAircraftModelNameMatrice600] || [product.model isEqual:DJIAircraftModelNameMatrice600Pro]){ [[DJISDKManager videoFeeder].secondaryVideoFeed removeListener:self]; }else{ [[DJISDKManager videoFeeder].primaryVideoFeed removeListener:self]; } } ``` -------------------------------- ### Run Remote Logger Server Script Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/RemoteLoggerDemo.html Execute this bash script in the Server folder to start the remote logger server. Ensure you have the command line developer tools and Ruby installed. ```bash ./run_log_server.bash ``` -------------------------------- ### Initialize ConnectionActivity and Check Permissions Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/index.html Set up the ConnectionActivity by calling `checkAndRequestPermissions()` in `onCreate()` and initializing the UI. ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); checkAndRequestPermissions(); setContentView(R.layout.activity_connection); initUI(); } ``` -------------------------------- ### Start Mission Method Signature Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/PanoDemo.html The signature for starting a waypoint mission. It accepts a completion block to report the success or failure of starting the mission. ```objective-c - (void)startMissionWithCompletion:(DJICompletionBlock)completion; ``` -------------------------------- ### Initialize UI Elements Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/MediaManagerDemo.html Set up the FileListAdapter for the list view and initialize a ProgressDialog for user feedback during media operations. ```java //Init FileListAdapter mListAdapter = new FileListAdapter(); listView.setAdapter(mListAdapter); //Init Loading Dialog mLoadingDialog = new ProgressDialog(MainActivity.this); mLoadingDialog.setMessage("Please wait"); mLoadingDialog.setCanceledOnTouchOutside(false); mLoadingDialog.setCancelable(false); ``` -------------------------------- ### Update Pod Repo and Install SDK Source: https://developer.dji.com/mobile-sdk/documentation/quick-start/index.html If you encounter dependency issues during 'pod install', update your local CocoaPods repository first and then attempt the installation again. This ensures you have the latest pod specifications. ```bash pod repo update pod install ``` -------------------------------- ### Initialize and Uninitialize Video Previewer Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/index.html Implement initPreviewer to set up the video feed listener and uninitPreviewer to reset it. Ensure product connection and model are checked before adding the listener. ```java private void initPreviewer() { BaseProduct product = FPVDemoApplication.getProductInstance(); if (product == null || !product.isConnected()) { showToast(getString(R.string.disconnected)); } else { if (null != mVideoSurface) { mVideoSurface.setSurfaceTextureListener(this); } if (!product.getModel().equals(Model.UNKNOWN_AIRCRAFT)) { VideoFeeder.getInstance().getPrimaryVideoFeed().addVideoDataListener(mReceivedVideoDataListener); } } } private void uninitPreviewer() { Camera camera = FPVDemoApplication.getCameraInstance(); if (camera != null){ // Reset the callback VideoFeeder.getInstance().getPrimaryVideoFeed().addVideoDataListener(null); } } ``` -------------------------------- ### Start DJIWaypoint Mission Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/GSDemo.html Starts the uploaded DJIWaypoint mission. Shows an alert for success or failure. ```objective-c - (void)startBtnActionInGSButtonVC:(DJIGSButtonViewController *)GSBtnVC { [[self missionOperator] startMissionWithCompletion:^(NSError * _Nullable error) { if (error){ ShowMessage(@"Start Mission Failed", error.description, nil, @"OK"); }else { ShowMessage(@"", @"Mission Started", nil, @"OK"); } }]; } ``` -------------------------------- ### TapFly Mission: Get Direction and Image Location Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/P4MissionsDemo.html Use getDirection() to get the aircraft's flying direction in the N-E-D coordinate system and getImageLocation() to get the image point from the live video stream for TapFly missions. ```java public Vector getDirection () ``` ```java public PointF getImageLocation () ``` -------------------------------- ### DemoApplication onCreate Method Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/UXSDKDemo.html Handles SDK registration by checking necessary permissions and calling DJISDKManager.getInstance().registerApp. It also defines the SDKManagerCallback to listen for registration results and product connection changes. ```java @Override public void onCreate() { super.onCreate(); mHandler = new Handler(Looper.getMainLooper()); //Check the permissions before registering the application for android system 6.0 above. int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE); int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (permissionCheck == 0 && permissionCheck2 == 0)) { //This is used to start SDK services and initiate SDK. DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback); } else { Toast.makeText(getApplicationContext(), "Please check if the permission is granted.", Toast.LENGTH_LONG).show(); } /** * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to * the SDK Registration result and the product changing. */ mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() { //Listens to the SDK registration result @Override public void onRegister(DJIError error) { if(error == DJISDKError.REGISTRATION_SUCCESS) { DJISDKManager.getInstance().startConnectionToProduct(); Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "Register Success", Toast.LENGTH_LONG).show(); } }); loginAccount(); } else { Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "Register Failed, check network is available", Toast.LENGTH_LONG).show(); } }); } Log.e("TAG", error.toString()); } @Override public void onProductDisconnect() { Log.d("TAG", "onProductDisconnect"); notifyStatusChange(); } @Override public void onProductConnect(BaseProduct baseProduct) { Log.d("TAG", String.format("onProductConnect newProduct:%s", baseProduct)); notifyStatusChange(); } @Override public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent, BaseComponent newComponent) { if (newComponent != null) { newComponent.setComponentListener(new BaseComponent.ComponentListener() { @Override ``` -------------------------------- ### Start New Activity in Android Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/index.html This code demonstrates how to create an Intent to start a new activity, specifically MainActivity, from the current activity. ```java Intent intent = new Intent(this, MainActivity.class); startActivity(intent); ``` -------------------------------- ### MainActivity Setup for DJI SDK Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/ActivationAndBinding.html This code sets up the MainActivity for DJI SDK integration. It requests necessary runtime permissions and initializes the UI components and event listeners. ```java public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final String TAG = MainActivity.class.getName(); protected Button loginBtn; protected Button logoutBtn; protected TextView bindingStateTV; protected TextView appActivationStateTV; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // When the compile and target version is higher than 22, please request the // following permissions at runtime to ensure the // SDK work well. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.VIBRATE, Manifest.permission.INTERNET, Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.WAKE_LOCK, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE, Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.SYSTEM_ALERT_WINDOW, Manifest.permission.READ_PHONE_STATE, } , 1); } setContentView(R.layout.activity_main); initUI(); } @Override public void onResume() { Log.e(TAG, "onResume"); super.onResume(); } @Override public void onPause() { Log.e(TAG, "onPause"); super.onPause(); } @Override public void onStop() { Log.e(TAG, "onStop"); super.onStop(); } public void onReturn(View view){ Log.e(TAG, "onReturn"); this.finish(); } @Override protected void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); } private void initUI(){ bindingStateTV = (TextView) findViewById(R.id.tv_binding_state_info); appActivationStateTV = (TextView) findViewById(R.id.tv_activation_state_info); loginBtn = (Button) findViewById(R.id.btn_login); logoutBtn = (Button) findViewById(R.id.btn_logout); loginBtn.setOnClickListener(this); logoutBtn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_login:{ break; } case R.id.btn_logout:{ break; } default: break; } } } ``` -------------------------------- ### Handle App Registration and Initialize SDK Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/ActivationAndBinding.html Implement the DJISDKManagerDelegate method to handle app registration. If successful, start the product connection, set the activation manager delegate, and initialize state properties. ```objectivec #pragma mark DJISDKManager Delegate Method - (void)appRegisteredWithError:(NSError *)error { NSString* message = @"Register App Successed!"; if (error) { message = @"Register App Failed! Please enter your App Key in the plist file and check the network."; }else { NSLog(@"registerAppSuccess"); [DJISDKManager startConnectionToProduct]; [DJISDKManager appActivationManager].delegate = self; self.activationState = [DJISDKManager appActivationManager].appActivationState; self.aircraftBindingState = [DJISDKManager appActivationManager].aircraftBindingState; } ShowResult(@"%@", message); } ``` -------------------------------- ### Initialize and Configure Download Dialog Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/MediaManagerDemo.html Set up the `ProgressDialog` for media file downloads. Configure its title, icon, style, and touch/cancel behavior. Implement the `OnCancelListener` to stop ongoing downloads when the dialog is canceled. ```java //Init Download Dialog mDownloadDialog = new ProgressDialog(MainActivity.this); mDownloadDialog.setTitle("Downloading file"); mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info); mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mDownloadDialog.setCanceledOnTouchOutside(false); mDownloadDialog.setCancelable(true); mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { if (mMediaManager != null) { mMediaManager.exitMediaDownloading(); } } }); ``` -------------------------------- ### Start Live Video Preview in viewWillAppear Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/P4MissionsDemo.html In the viewWillAppear method, initialize the DJIVideoPreviewer, set the FPV view, and add the current view controller as a listener for video feed updates. This ensures the live camera feed is displayed when the view appears. ```objective-c -(void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[DJIVideoPreviewer instance] setView:self.fpvView]; [[DJISDKManager videoFeeder].primaryVideoFeed addListener:self withQueue:nil]; [[DJIVideoPreviewer instance] start]; } ``` -------------------------------- ### Start Download Progress Timer Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/PlaybackDemo.html Starts the `updateImageDownloadTimer` if it hasn't been initialized yet. This timer is responsible for triggering the `updateDownloadProgress:` method at regular intervals. ```objective-c - (void)startUpdateTimer { if (self.updateImageDownloadTimer == nil) { self.updateImageDownloadTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateDownloadProgress:) userInfo:nil repeats:YES]; } } ``` -------------------------------- ### Start DJI SDK Registration with Callbacks Source: https://developer.dji.com/mobile-sdk/documentation/application-development-workflow/workflow-integrate.html Initiates the DJI SDK registration process asynchronously. This method should be called after ensuring all necessary permissions are granted. It includes callbacks for registration success/failure, product connection/disconnection, and component changes. ```java private void startSDKRegistration() { if (isRegistrationInProgress.compareAndSet(false, true)) { AsyncTask.execute(new Runnable() { @Override public void run() { showToast("registering, pls wait..."); DJISDKManager.getInstance().registerApp(MainActivity.this.getApplicationContext(), new DJISDKManager.SDKManagerCallback() { @Override public void onRegister(DJIError djiError) { if (djiError == DJISDKError.REGISTRATION_SUCCESS) { showToast("Register Success"); DJISDKManager.getInstance().startConnectionToProduct(); } else { showToast("Register sdk fails, please check the bundle id and network connection!"); } Log.v(TAG, djiError.getDescription()); } @Override public void onProductDisconnect() { Log.d(TAG, "onProductDisconnect"); showToast("Product Disconnected"); notifyStatusChange(); } @Override public void onProductConnect(BaseProduct baseProduct) { Log.d(TAG, String.format("onProductConnect newProduct:%s", baseProduct)); showToast("Product Connected"); notifyStatusChange(); } @Override public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent, BaseComponent newComponent) { if (newComponent != null) { newComponent.setComponentListener(new BaseComponent.ComponentListener() { @Override public void onConnectivityChange(boolean isConnected) { Log.d(TAG, "onComponentConnectivityChanged: " + isConnected); notifyStatusChange(); } }); } Log.d(TAG, String.format("onComponentChange key:%s, oldComponent:%s, newComponent:%s", componentKey, oldComponent, newComponent)); } @Override public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) { } @Override public void onDatabaseDownloadProgress(long l, long l1) { } }); } }); } } ``` -------------------------------- ### Start DJISimulator Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/SimulatorDemo.html Starts the simulator with specified location, update frequency, and initial GPS satellite count. This method will result in an error if the simulator is already active. ```objective-c - (void)startWithLocation:(CLLocationCoordinate2D)location updateFrequency:(NSUInteger)frequency GPSSatellitesNumber:(NSUInteger)number withCompletion:(DJICompletionBlock)completion; ``` -------------------------------- ### Install CocoaPods for iOS SDK Source: https://developer.dji.com/mobile-sdk/documentation/quick-start/index.html Install CocoaPods, a dependency manager for Swift and Objective-C, which is required for integrating the DJI iOS SDK. This command should be run in the terminal. ```bash sudo gem install cocoapods ``` -------------------------------- ### Initialize GSButtonVC and Setup UI Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/GSDemo.html Initialize the DJIGSButtonViewController instance, set its frame, assign the delegate, and add its view to the main view hierarchy. This is typically done within an initialization method like initUI. ```objective-c self.gsButtonVC = [[DJIGSButtonViewController alloc] initWithNibName:@"DJIGSButtonViewController" bundle:[NSBundle mainBundle]]; [self.gsButtonVC.view setFrame:CGRectMake(0, self.topBarView.frame.origin.y + self.topBarView.frame.size.height, self.gsButtonVC.view.frame.size.width, self.gsButtonVC.view.frame.size.height)]; self.gsButtonVC.delegate = self; [self.view addSubview:self.gsButtonVC.view]; ``` -------------------------------- ### Initialize and Start Tap Fly Mission Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/P4MissionsDemo.html Initializes the DJITapFlyMission object, sets the target point and mode, and prepares the UI for mission start. Ensure DJITapFlyMission is initialized before use. ```objective-c -(void) startTapFlyMissionWithPoint:(CGPoint)point { if (!self.tapFlyMission) { self.tapFlyMission = [[DJITapFlyMission alloc] init]; } self.tapFlyMission.imageLocationToCalculateDirection = point; self.tapFlyMission.tapFlyMode = DJITapFlyModeForward; [self shouldShowStartMissionButton:YES]; } - (void) shouldShowStartMissionButton:(BOOL)show { if (show) { self.startMissionBtn.hidden = NO; self.stopMissionBtn.hidden = YES; }else { self.startMissionBtn.hidden = YES; self.stopMissionBtn.hidden = NO; } } ``` -------------------------------- ### Install DJI SDK with CocoaPods Source: https://developer.dji.com/mobile-sdk/documentation/quick-start/index.html Install the DJI SDK and associated widgets into your Xcode project using CocoaPods. Run this command in the directory of your sample project (ObjcSampleCode or SwiftSampleCode). ```bash pod install ``` -------------------------------- ### viewDidLoad and registerApp Methods Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/PanoDemo.html Initializes the FPV preview view and registers the application with the DJI SDK. ```objc - (void)viewDidLoad { [super viewDidLoad]; self.title = @"Panorama Demo"; [[DJIVideoPreviewer instance] setView:self.fpvPreviewView]; [self registerApp]; } - (void) registerApp { //Please enter the App Key in the info.plist file to register the App. [DJISDKManager registerAppWithDelegate:self]; } ``` -------------------------------- ### Start DJISimulator with Coordinates Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/GEODemo.html Initiates the DJISimulator with specified latitude and longitude. Requires a flight controller and presents an alert for user input. The map view is refreshed upon successful start. ```Objective-C - (void)viewDidLoad { [super viewDidLoad]; self.djiMapViewController = [[DJIMapViewController alloc] initWithMap:self.mapView]; } - (IBAction)onStartSimulatorButtonClicked:(id)sender { DJIFlightController* flightController = [DemoUtility fetchFlightController]; if (!flightController) { return; } UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:@"Input coordinate" preferredStyle:UIAlertControllerStyleAlert]; [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = @"latitude"; }]; [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = @"longitude"; }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; UIAlertAction *startAction = [UIAlertAction actionWithTitle:@"Start" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { UITextField* latTextField = alertController.textFields[0]; UITextField* lngTextField = alertController.textFields[1]; float latitude = [latTextField.text floatValue]; float longitude = [lngTextField.text floatValue]; if (latitude && longitude) { CLLocationCoordinate2D location = CLLocationCoordinate2DMake(latitude, longitude); WeakRef(target); [flightController.simulator startWithLocation:location updateFrequency:20 GPSSatellitesNumber:10 withCompletion:^(NSError * _Nullable error) { WeakReturn(target); if (error) { ShowResult(@"Start simulator error:%@", error.description); } else { ShowResult(@"Start simulator success"); [target.djiMapViewController refreshMapViewRegion]; } }]; } }]; [alertController addAction:cancelAction]; [alertController addAction:startAction]; [self presentViewController:alertController animated:YES completion:nil]; } ``` -------------------------------- ### Initialize Media Manager and Fetch File List Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/MediaManagerDemo.html This code snippet initializes the Media Manager, sets the camera mode to MEDIA_DOWNLOAD, and starts fetching the media file list. It also includes a check for video playback support. ```java if (null != mMediaManager) { mMediaManager.addUpdateFileListStateListener(this.updateFileListStateListener); DemoApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD, new CommonCallbacks.CompletionCallback() { @Override public void onResult(DJIError error) { if (error == null) { DJILog.e(TAG, "Set cameraMode success"); showProgressDialog(); getFileList(); } else { setResultToToast("Set cameraMode failed"); } } }); if (mMediaManager.isVideoPlaybackSupported()) { DJILog.e(TAG, "Camera support video playback!"); } else { setResultToToast("Camera does not support video playback!"); } scheduler = mMediaManager.getScheduler(); } ``` -------------------------------- ### Implement Mission Start and Stop Logic Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/P4MissionsDemo.html Override the onClick method to handle button clicks for starting and stopping a DJITapFlyMission. This snippet shows how to invoke startMission and stopMission with completion callbacks. ```java @Override public void onClick(View v) { if (v.getId() == R.id.pointing_drawer_control_ib) { if (mPushDrawerSd.isOpened()) { mPushDrawerSd.animateClose(); } else { mPushDrawerSd.animateOpen(); } return; } if (getTapFlyOperator() != null) { switch (v.getId()) { case R.id.pointing_start_btn: getTapFlyOperator().startMission(mTapFlyMission, new CommonCallbacks.CompletionCallback() { @Override public void onResult(DJIError error) { setResultToToast(error == null ? "Start Mission Successfully" : error.getDescription()); if (error == null){ setVisible(mStartBtn, false); } } }); break; case R.id.pointing_stop_btn: getTapFlyOperator().stopMission(new CommonCallbacks.CompletionCallback() { @Override public void onResult(DJIError error) { setResultToToast(error == null ? "Stop Mission Successfully" : error.getDescription()); } }); break; default: break; } } else { setResultToToast("TapFlyMission Operator is null"); } } ``` -------------------------------- ### MainActivity UI and Map Implementation Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/GEODemo.html This code sets up the MainActivity, initializes UI elements such as buttons and text views, and configures the Google Map. It handles button clicks and map readiness. ```java public class MainActivity extends FragmentActivity implements View.OnClickListener, OnMapReadyCallback { private static final String TAG = MainActivity.class.getName(); private GoogleMap map; protected TextView mConnectStatusTextView; private Button btnLogin; private Button btnLogout; private Button btnUnlock; private Button btnGetUnlock; private Button btnGetSurroundNFZ; private Button btnUpdateLocation; private TextView loginStatusTv; private TextView flyZonesTv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); // Obtain the SupportMapFragment and get notified when the map is ready to be used. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } private void initUI() { mConnectStatusTextView = (TextView) findViewById(R.id.ConnectStatusTextView); btnLogin = (Button) findViewById(R.id.geo_login_btn); btnLogout = (Button) findViewById(R.id.geo_logout_btn); btnUnlock = (Button) findViewById(R.id.geo_unlock_nfzs_btn); btnGetUnlock = (Button) findViewById(R.id.geo_get_unlock_nfzs_btn); btnGetSurroundNFZ = (Button) findViewById(R.id.geo_get_surrounding_nfz_btn); btnUpdateLocation = (Button) findViewById(R.id.geo_update_location_btn); loginStatusTv = (TextView) findViewById(R.id.login_status); loginStatusTv.setTextColor(Color.BLACK); flyZonesTv = (TextView) findViewById(R.id.fly_zone_tv); flyZonesTv.setTextColor(Color.BLACK); btnLogin.setOnClickListener(this); btnLogout.setOnClickListener(this); btnUnlock.setOnClickListener(this); btnGetUnlock.setOnClickListener(this); btnGetSurroundNFZ.setOnClickListener(this); btnUpdateLocation.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.geo_login_btn: break; case R.id.geo_logout_btn: break; case R.id.geo_unlock_nfzs_btn: break; case R.id.geo_get_unlock_nfzs_btn: break; case R.id.geo_get_surrounding_nfz_btn: break; case R.id.geo_update_location_btn: break; } } /** * Manipulates the map once available. * This callback is triggered when the map is ready to be used. * This is where we can add markers or lines, add listeners or move the camera. In this case, * we just add a marker near Sydney, Australia. * If Google Play services is not installed on the device, the user will be prompted to install * it inside the SupportMapFragment. This method will only be triggered once the user has * installed Google Play services and returned to the app. */ @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // Add a marker in Shenzhen and move the camera LatLng shenzhen = new LatLng(22.537018, 113.953640); mMap.addMarker(new MarkerOptions().position(shenzhen).title("Marker in shenzhen")); mMap.moveCamera(CameraUpdateFactory.newLatLng(shenzhen)); } } ``` -------------------------------- ### Start and Stop Waypoint Mission Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/GSDemo-Gaode-Map.html Invokes the startMission() and stopMission() methods of WaypointMissionOperator to implement the start and stop mission features. Callbacks handle the results and display success or error messages. ```java private void startWaypointMission(){ getWaypointMissionOperator().startMission(new CommonCallbacks.CompletionCallback() { @Override public void onResult(DJIError error) { setResultToToast("Mission Start: " + (error == null ? "Successfully" : error.getDescription())); } }); } private void stopWaypointMission(){ getWaypointMissionOperator().stopMission(new CommonCallbacks.CompletionCallback() { @Override public void onResult(DJIError error) { setResultToToast("Mission Stop: " + (error == null ? "Successfully" : error.getDescription())); } }); } ``` -------------------------------- ### Control Simulator Start/Stop Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/SimulatorDemo.html Handles the button action to start or stop the simulator. Configures initial location, update frequency, and GPS satellites for starting. Displays success or error messages using alert views. ```objective-c - (IBAction)onSimulatorButtonClicked:(id)sender { DJIFlightController* fc = [DemoUtility fetchFlightController]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@ ``` ```objective-c OK ``` ```objective-c " style:UIAlertActionStyleCancel handler:nil]; if (fc && fc.simulator) { if (!self.isSimulatorOn) { // The initial aircraft's position in the simulator. CLLocationCoordinate2D location = CLLocationCoordinate2DMake(22, 113); WeakRef(target); [fc.simulator startWithLocation:location updateFrequency:20 GPSSatellitesNumber:10 withCompletion:^(NSError * _Nullable error) { WeakReturn(target); if (error) { [DemoUtility showAlertViewWithTitle:nil message:[NSString stringWithFormat:@ ``` ```objective-c Start simulator error: %@ ``` ```objective-c , error.description] cancelAlertAction:cancelAction defaultAlertAction:nil viewController:target]; } else { [DemoUtility showAlertViewWithTitle:nil message:@ ``` ```objective-c Start Simulator succeeded. ``` ```objective-c " cancelAlertAction:cancelAction defaultAlertAction:nil viewController:target]; } }]; } else { WeakRef(target); [fc.simulator stopWithCompletion:^(NSError * _Nullable error) { WeakReturn(target); if (error) { [DemoUtility showAlertViewWithTitle:nil message:[NSString stringWithFormat:@ ``` ```objective-c Stop simulator error: %@ ``` ```objective-c , error.description] cancelAlertAction:cancelAction defaultAlertAction:nil viewController:target]; } else { [DemoUtility showAlertViewWithTitle:nil message:@ ``` ```objective-c Stop Simulator succeeded. ``` ```objective-c " cancelAlertAction:cancelAction defaultAlertAction:nil viewController:target]; } }]; } } } ``` -------------------------------- ### Helper Methods and DJISDKManagerDelegate Implementation Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/PanoDemo.html Provides a method to display alert views, fetch the camera object, and handles app registration and product connection events. ```objc - (void)showAlertViewWithTitle:(NSString *)title withMessage:(NSString *)message { UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; [alert addAction:okAction]; [self presentViewController:alert animated:YES completion:nil]; } - (DJICamera*) fetchCamera { if (![DJISDKManager product]) { return nil; } return [DJISDKManager product].camera; } #pragma mark DJISDKManagerDelegate Method - (void)appRegisteredWithError:(NSError *)error { NSString* message = @"Register App Successfully!"; if (error) { message = @"Register App Failed! Please enter your App Key and check the network."; }else{ NSLog(@"registerAppSuccess"); [DJISDKManager startConnectionToProduct]; [[DJISDKManager videoFeeder].primaryVideoFeed addListener:self withQueue:nil]; [[DJIVideoPreviewer instance] start]; } [self showAlertViewWithTitle:@"Register App" withMessage:message]; } - (void)productConnected:(DJIBaseProduct *)product { if (product) { DJICamera* camera = [self fetchCamera]; if (camera != nil) { camera.delegate = self; [camera.playbackManager setDelegate:self]; } } } ``` -------------------------------- ### Enable Bridge Mode or Start Connection Source: https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/BridgeAppDemo.html In the app registered callback, conditionally enable bridge mode with the DJI Bridge app's IP or start a direct connection to the product based on the ENABLE_DEBUG_MODE macro. ```objective-c - (void)appRegisteredWithError:(NSError *)error { NSString* message = @"Register App Successed!"; if (error) { message = @"Register App Failed! Please enter your App Key and check the network."; }else { NSLog(@"registerAppSuccess"); #if ENABLE_DEBUG_MODE [DJISDKManager enableBridgeModeWithBridgeAppIP:@"Please type in Debug ID of the DJI Bridge app here"]; #else [DJISDKManager startConnectionToProduct]; #endif [[DJISDKManager videoFeeder].primaryVideoFeed addListener:self withQueue:nil]; [[DJIVideoPreviewer instance] start]; } [self showAlertViewWithTitle:@"Register App" withMessage:message]; } ``` -------------------------------- ### Control Simulator Start and Stop with Toggle Button Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/SimulatorDemo.html Handles the `onCheckedChanged` event for a toggle button to start or stop the DJISimulator. It manages the visibility of a text view and shows success or error messages upon completion. ```java mBtnSimulator.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { mTextView.setVisibility(View.VISIBLE); if (mFlightController != null) { mFlightController.getSimulator() .start(InitializationData.createInstance(new LocationCoordinate2D(23, 113), 10, 10), new CommonCallbacks.CompletionCallback() { @Override public void onResult(DJIError djiError) { if (djiError != null) { showToast(djiError.getDescription()); }else { showToast("Start Simulator Success"); } } }); } } else { mTextView.setVisibility(View.INVISIBLE); if (mFlightController != null) { mFlightController.getSimulator() .stop(new CommonCallbacks.CompletionCallback() { @Override public void onResult(DJIError djiError) { if (djiError != null) { showToast(djiError.getDescription()); }else { showToast("Stop Simulator Success"); } } } ); } } } }); ``` -------------------------------- ### Initialize Media Manager Variables Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/MediaManagerDemo.html Declare variables for the download progress dialog, destination directory, and current download progress. Ensure these are initialized before use. ```java private ProgressDialog mDownloadDialog; File destDir = new File(Environment.getExternalStorageDirectory().getPath() + "/MediaManagerDemo/"); private int currentProgress = -1; ``` -------------------------------- ### Initialize Video Previewer in DemoBaseActivity Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/P4MissionsDemo.html This method checks the product connection status and adds the video data listener to the primary video feed. It ensures that the video stream is properly set up when a product is connected. ```java private void initPreviewer() { try { mProduct = DJIDemoApplication.getProductInstance(); } catch (Exception exception) { mProduct = null; } if (mProduct == null || !mProduct.isConnected()) { showToast("Disconnect"); } else { if (null != mVideoSurface) { mVideoSurface.setSurfaceTextureListener(this); } if (!mProduct.getModel().equals(Model.UNKNOWN_AIRCRAFT)) { VideoFeeder.getInstance().getPrimaryVideoFeed().addVideoDataListener(mReceivedVideoDataListener); } } } ``` -------------------------------- ### Implement onProductChange and onResume Source: https://developer.dji.com/mobile-sdk/documentation/android-tutorials/index.html Implement onProductChange to initialize the previewer and call it in onResume along with other necessary initializations for the live video stream. ```java protected void onProductChange() { initPreviewer(); } @Override public void onResume() { Log.e(TAG, "onResume"); super.onResume(); initPreviewer(); onProductChange(); if(mVideoSurface == null) { Log.e(TAG, "mVideoSurface is null"); } } ```