Skip to content

Instantly share code, notes, and snippets.

@BARNZ
Last active September 15, 2025 10:25
Show Gist options
  • Select an option

  • Save BARNZ/84015728f786c2ebba87118edd216e54 to your computer and use it in GitHub Desktop.

Select an option

Save BARNZ/84015728f786c2ebba87118edd216e54 to your computer and use it in GitHub Desktop.
Insta360 SDK Example - Take photo with X5/X4/X3 camera
Insta360 instance = new Insta360(activity, context);
this.capturePanorama(new IImageCaptureCallback() {
@Override
public void captureSuccess(File image) {
// it worked - image is a file saved under the path you have specified in getTargetPath
}
@Override
public void captureFail(String error) {
// something went wrong :(
// error is a friendly error message that can be shown to the user
}
@Override
public String getTargetPath() {
return "360-photos"; // Photos will be saved to app external-files-dir/360-photos/<timestamp>.jpg
}
});
/**
* A simple interface that provides callbacks for when a new image is capturd
*/
public interface IImageCaptureCallback {
public void captureSuccess(File image);
public void captureFail(String error);
public String getTargetPath(); // Device local path the image should be saved to (after copying from the camera)
}
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import com.arashivision.sdkcamera.InstaCameraSDK;
import com.arashivision.sdkcamera.camera.InstaCameraManager;
import com.arashivision.sdkcamera.camera.callback.ICameraChangedCallback;
import com.arashivision.sdkcamera.camera.callback.ICameraOperateCallback;
import com.arashivision.sdkcamera.camera.callback.ICaptureStatusListener;
import com.arashivision.sdkcamera.camera.callback.ICaptureSupportConfigCallback;
import com.arashivision.sdkcamera.camera.model.CaptureMode;
import com.arashivision.sdkmedia.InstaMediaSDK;
import com.arashivision.sdkmedia.export.ExportImageParamsBuilder;
import com.arashivision.sdkmedia.export.ExportUtils;
import com.arashivision.sdkmedia.export.IExportCallback;
import com.arashivision.sdkmedia.work.WorkWrapper;
import java.io.File;
import java.util.ArrayList;
public class Insta360 {
public static final String LOGGING_TAG = "My Insta360";
private final Context context;
// This callback is set and kept around when the caller requests a new photo
private IImageCaptureCallback activeCallback;
// Just a local variable to hold the file paths on the camera as they become available
// Used when exporting images from the camera
private String[] newDevicePhotoPaths;
public Insta360(Activity activity, Context context) {
this.context = context;
// Initialise Insta360 SDK packages
var app = activity.getApplication();
InstaCameraSDK.init(app);
InstaMediaSDK.init(app);
registerCameraChangedCallback();
}
/**
* Take a new panoramic photo
*/
public void capturePanorama(IImageCaptureCallback callback) {
// Can only be one active callback at a time, if camera is already busy taking a photo then just bail.
if (this.activeCallback != null) {
callback.captureFail(Insta360Errors.LOG_ERROR_CAMERA_BUSY);
return;
}
this.activeCallback = callback;
event(Insta360Event.REQUEST_PHOTO);
}
/**
* Main event handler - using this to avoid callback hell for various async events
*/
private void event(Insta360Event e) {
Log.d(Insta360.LOGGING_TAG, "Handling Insta360 event: " + e);
switch (e) {
case Insta360Event.REQUEST_PHOTO -> ensureCameraIsInitialised();
case Insta360Event.CAMERA_STATUS_CHANGED -> initCameraOptions();
case Insta360Event.CAMERA_OPTIONS_SYNCED -> initCameraSupportConfiguration();
case Insta360Event.CAMERA_SUPPORT_CONFIGURATION_INITIALISED -> setCaptureMode();
case Insta360Event.CAMERA_CAPTURE_MODE_SET -> registerCaptureStatusListener();
case Insta360Event.CAMERA_READY -> InstaCameraManager.getInstance().startNormalCapture(); // Will trigger onCaptureFinish() callback
case Insta360Event.PHOTO_TAKEN -> exportPhotoFromCamera(this.newDevicePhotoPaths);
}
}
// Step #1 - Register a callback to listen for camera connectivity changes
private void registerCameraChangedCallback() {
InstaCameraManager.getInstance().registerCameraChangedCallback(new ICameraChangedCallback() {
@Override
public void onCameraStatusChanged(boolean enabled, int connectType) {
Log.d(Insta360.LOGGING_TAG, "Received camera status change. Enabled: " + enabled);
if (enabled) event(Insta360Event.CAMERA_STATUS_CHANGED);
else handleCaptureFailure(Insta360Errors.LOG_ERROR_CAMERA_DISCONNECTED);
}
@Override
public void onCameraConnectError(int errorCode) {
handleCaptureFailure(Insta360Errors.LOG_ERROR_CAMERA_NOT_FOUND, String.valueOf(errorCode));
}
});
}
// Step #2 - Make sure we are connected to the camera via wifi
private void ensureCameraIsInitialised() {
InstaCameraManager instance = InstaCameraManager.getInstance();
// Already connected?
var connectionType = instance.getCameraConnectedType();
if (connectionType == InstaCameraManager.CONNECT_TYPE_WIFI) {
event(Insta360Event.CAMERA_READY);
} else {
Log.d(Insta360.LOGGING_TAG, "No active connection to camera, attempting connection via wifi...");
instance.openCamera(InstaCameraManager.CONNECT_TYPE_WIFI); // Will take a few seconds (doesn't block) onCameraStatusChanged() will be called
}
}
/**
* Step #3 - Initialise the camera options as per
* https://github.com/Insta360Develop/Android-SDK/issues/109#issuecomment-3235212446
*/
private void initCameraOptions() {
Log.d(Insta360.LOGGING_TAG, "Camera initialisation step #1: fetchCameraOptions...");
InstaCameraManager.getInstance().fetchCameraOptions(new ICameraOperateCallback() {
@Override
public void onSuccessful() {
event(Insta360Event.CAMERA_OPTIONS_SYNCED);
}
@Override
public void onFailed() {
handleCaptureFailure(Insta360Errors.LOG_ERROR_CAMERA_INITIALISATION_FAILURE, "initCameraOptions");
}
@Override
public void onCameraConnectError() {
handleCaptureFailure(Insta360Errors.LOG_ERROR_CAMERA_DISCONNECTED);
}
});
}
/**
* Step #4 - Initialise camera support config
*/
private void initCameraSupportConfiguration() {
Log.d(Insta360.LOGGING_TAG, "Camera initialisation step #2: initCameraSupportConfig...");
InstaCameraManager.getInstance().initCameraSupportConfig(new ICaptureSupportConfigCallback() {
@Override
public void onComplete() {
event(Insta360Event.CAMERA_SUPPORT_CONFIGURATION_INITIALISED);
}
@Override
public void onFailed(String s) {
handleCaptureFailure(Insta360Errors.LOG_ERROR_CAMERA_INITIALISATION_FAILURE, "initCameraSupportConfiguration");
}
});
}
/**
* Step #5 - Set capture normal mode once above configurations are successful
*/
private void setCaptureMode() {
Log.d(Insta360.LOGGING_TAG, "Camera initialisation step #3: setCaptureMode...");
InstaCameraManager.getInstance().setCaptureMode(CaptureMode.CAPTURE_NORMAL, errorCode -> {
if (errorCode == 0) {
Log.d(Insta360.LOGGING_TAG, "Capture mode set to normal");
event(Insta360Event.CAMERA_CAPTURE_MODE_SET);
} else {
handleCaptureFailure(Insta360Errors.LOG_ERROR_CAMERA_INITIALISATION_FAILURE, "setCaptureMode normal");
}
});
}
/**
* Step #6 - Register a listener for capture success / failure
*/
private void registerCaptureStatusListener() {
Insta360 self = this;
Log.d(Insta360.LOGGING_TAG, "Camera initialisation step #4: registerCaptureStatusListener...");
InstaCameraManager.getInstance().setCaptureStatusListener(new ICaptureStatusListener() {
@Override
public void onCaptureFinish(String[] newDevicePhotoPaths) {
// We'll capture the paths of photo(s) for later exporting
self.newDevicePhotoPaths = newDevicePhotoPaths;
event(Insta360Event.PHOTO_TAKEN);
}
@Override
public void onCaptureError(int i) {
handleCaptureFailure(Insta360Errors.LOG_ERROR_FAILED_TO_CAPTURE, String.valueOf(i));
}
});
event(Insta360Event.CAMERA_READY);
}
/**
* Export the image straight away and store back on the device
* https://github.com/Insta360Develop/CameraSDK-Android#export
*/
private void exportPhotoFromCamera(String[] devicePhotoPaths) {
Insta360 self = this;
// No active callback? Just bail (should never happen)
if (this.activeCallback == null) return;
var externalFilesDir = this.context.getExternalFilesDir(null);
if (externalFilesDir == null) {
handleCaptureFailure(Insta360Errors.LOG_ERROR_FAILED_TO_EXPORT, "externalFilesDir returned null");
return;
}
// Build export path to export the image to
ArrayList<String> pathSegments = new ArrayList<>();
pathSegments.add(externalFilesDir.getPath());
pathSegments.add(this.activeCallback.getTargetPath());
pathSegments.add(System.currentTimeMillis() + ".jpg");
String targetPath = String.join(File.separator, pathSegments);
Log.d(Insta360.LOGGING_TAG, "Exporting image to: " + targetPath);
WorkWrapper workWrapper = new WorkWrapper(devicePhotoPaths);
ExportImageParamsBuilder builder = new ExportImageParamsBuilder()
.setExportMode(ExportUtils.ExportMode.PANORAMA)
.setTargetPath(targetPath);
IExportCallback exportCallback = new IExportCallback() {
@Override
public void onStart(int i) {
Log.d(Insta360.LOGGING_TAG, "Starting image export");
}
@Override
public void onSuccess() {
Log.d(Insta360.LOGGING_TAG, "Image exported successfully: " + targetPath);
if (self.activeCallback != null) {
self.activeCallback.captureSuccess(new File(targetPath));
self.activeCallback = null;
}
}
@Override
public void onFail(int i, String s) {
self.handleCaptureFailure(Insta360Errors.LOG_ERROR_FAILED_TO_EXPORT, s);
}
@Override
public void onCancel() {
self.handleCaptureFailure(Insta360Errors.LOG_ERROR_EXPORT_INTERRUPTED);
}
};
try {
ExportUtils.exportImage(workWrapper, builder, exportCallback);
} catch (Exception e) {
// Takes a few seconds to export, we may encounter an exception if camera is disconnected
exportCallback.onCancel();
}
}
// General error handling function
private void handleCaptureFailure(String friendlyErrorMessage) {
this.handleCaptureFailure(friendlyErrorMessage, "");
}
// General error handling function with some additional logging message
private void handleCaptureFailure(String friendlyErrorMessage, String additionalLoggingInfo) {
Log.d(Insta360.LOGGING_TAG, friendlyErrorMessage + (additionalLoggingInfo.isEmpty() ? "" : " (" + additionalLoggingInfo + ")"));
// If caller is waiting on a response, let them know it failed
if (this.activeCallback != null) {
this.activeCallback.captureFail(friendlyErrorMessage);
this.activeCallback = null;
}
}
}
/**
* Some common errors that are displayed back to the end user
*/
public class Insta360Errors {
public static final String LOG_ERROR_MISSING_SAVE_TO_OPTIONS = "Must provide options.saveTo";
public static final String LOG_ERROR_CAMERA_NOT_FOUND = "Unable to connect to the Insta360 camera. Check you are connected to the camera's Wifi network";
public static final String LOG_ERROR_CAMERA_DISCONNECTED = "Camera was disconnected";
public static final String LOG_ERROR_CAMERA_INITIALISATION_FAILURE = "Camera was connected, but could not be properly initialised";
public static final String LOG_ERROR_FAILED_TO_CAPTURE = "Error when trying to take a photo";
public static final String LOG_ERROR_FAILED_TO_EXPORT = "Unable to save the captured photo - is there enough storage space?";
public static final String LOG_ERROR_EXPORT_INTERRUPTED = "Unable to save captured photo - camera connection was interrupted.";
public static final String LOG_ERROR_CAMERA_BUSY = "Please wait while the existing photo is captured.";
}
/**
* Some custom events to represent what initialisation state we are currently in.
*/
public enum Insta360Event {
REQUEST_PHOTO,
PHOTO_TAKEN,
CAMERA_READY,
CAMERA_STATUS_CHANGED,
CAMERA_OPTIONS_SYNCED,
CAMERA_SUPPORT_CONFIGURATION_INITIALISED,
CAMERA_CAPTURE_MODE_SET,
}
@BARNZ
Copy link
Author

BARNZ commented Sep 12, 2025

Here is my example code for using the insta360 SDK to capture a panoramic photo with one of their Insta360 cameras. Have tested with X5 and X3 cameras.

This is just some sample code - adapt to your needs as necessary. I'm not too much of a java/android programmer - so you can probably find ways to improve it :)

Helps for people struggling with this issue:
Insta360Develop/Android-SDK#109

Need to make sure to initialize things in the correct order otherwise you run into the above issue with camera events not firing correctly. Annoyingly their SDK documentation does not clearly list out the proper steps you need to go through.

SDK reference: https://github.com/Insta360Develop/Android-SDK

SDK versions used:

  • com.arashivision.sdk:sdkcamera:1.8.1_build_06
  • com.arashivision.sdk:sdkmedia:1.8.1_build_06

Follow their instructions for downloading SDK and getting setup

@Adarsh1993
Copy link

Adarsh1993 commented Sep 15, 2025

Thanks for replay .
Yes it is working now .

One thing i want to ask here
case Insta360Event.REQUEST_PHOTO -> ensureCameraIsInitialised();
case Insta360Event.CAMERA_STATUS_CHANGED -> initCameraOptions();
case Insta360Event.CAMERA_OPTIONS_SYNCED -> initCameraSupportConfiguration();
case Insta360Event.CAMERA_SUPPORT_CONFIGURATION_INITIALISED -> setCaptureMode();
case Insta360Event.CAMERA_CAPTURE_MODE_SET -> registerCaptureStatusListener();
case Insta360Event.CAMERA_READY -> InstaCameraManager.getInstance().startNormalCapture(); // Will trigger onCaptureFinish() callback
case Insta360Event.PHOTO_TAKEN -> exportPhotoFromCamera(this.newDevicePhotoPaths);

        Above all these methods is  necessary to call.  I meant was  Connect to wifi and set capture mode then   registerCaptureStatusListener  From these  three will not work for capture.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment