diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7d26fa9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
+# THETA X Concept 7
+
+After the startCapture command is run, the camera's status is in progress, until the user runs the stopCapture command.
+
+![gif](docs/test.gif)
+
+## Concepts
+
+The process id is parsed out from the `commands/execute` when the user starts the video. The id is passed into the state of the application and as a parameter for the `commands/status`. The `commands/status` outputs the state of the video command: inProgress or done.
+
+![chart](docs/chart.png)
+
+### inProgress
+
+The state of the process is `inProgress` while the camera is capturing the video. After the stopCapture command is run, the camera stitches the video together. The process is still `inProgress` even after stopping the video. The process is `done` once the video has finished stitching. While a video may be three seconds in duration, the process may take five seconds to complete.
+
+## API Features
+
+* [commands/status](https://api.ricoh/docs/theta-web-api-v2.1/protocols/commands_status/)
+* [camera.startCapture](https://api.ricoh/docs/theta-web-api-v2.1/commands/camera.start_capture/)
+* [camera.stopCapture](https://api.ricoh/docs/theta-web-api-v2.1/commands/camera.stop_capture/)
+* [captureMode](https://api.ricoh/docs/theta-web-api-v2.1/options/capture_mode/)
+
+## Steps
+
+* Start capture with `commands/execute`.
+* Parse out the id from the response
+
+```dart
+ var convertResponse = jsonDecode(response.bodyString);
+ var id = convertResponse['id'];
+```
+
+* Pass the process id into the state of the application and also into `commands/status`. With the specific id, the `commands/status` should emit the state of the video process.
+* The `commands/status` is added in a while loop to the `commands/execute` until the state of the video process is done. A delay between calls prevents the application from crashing.
+5. After the camera is finished processing, display the state to the screen.
+
+```dart
+Text('State: ${state.cameraStatus}')
+```
+
+## Response Window
+
+The stopCapture command outputs the file url of the last video. This file url is passesd into the state of the application and displayed as an image.
+
+```dart
+ state.fileUrl.isNotEmpty && state.cameraStatus == 'done'
+ ? SizedBox(
+ width: 300,
+ child: Image.network(
+ '${state.fileUrl}?type=thumb',))
+
+```
\ No newline at end of file
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/android/app/build.gradle b/android/app/build.gradle
new file mode 100644
index 0000000..31d29d9
--- /dev/null
+++ b/android/app/build.gradle
@@ -0,0 +1,71 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.example.theta_concept_7"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..b4435f5
--- /dev/null
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f140cfe
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/example/theta_concept_7/MainActivity.kt b/android/app/src/main/kotlin/com/example/theta_concept_7/MainActivity.kt
new file mode 100644
index 0000000..9e9a15d
--- /dev/null
+++ b/android/app/src/main/kotlin/com/example/theta_concept_7/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.theta_concept_7
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..b4435f5
--- /dev/null
+++ b/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..83ae220
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.6.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cc5527d
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/docs/chart.png b/docs/chart.png
new file mode 100644
index 0000000..0f2ecf0
Binary files /dev/null and b/docs/chart.png differ
diff --git a/docs/test.gif b/docs/test.gif
new file mode 100644
index 0000000..f5af04a
Binary files /dev/null and b/docs/test.gif differ
diff --git a/lib/bloc/camera_use/camera_use_bloc.dart b/lib/bloc/camera_use/camera_use_bloc.dart
new file mode 100644
index 0000000..4fa6936
--- /dev/null
+++ b/lib/bloc/camera_use/camera_use_bloc.dart
@@ -0,0 +1,74 @@
+import 'dart:convert';
+
+import 'package:bloc/bloc.dart';
+import 'package:chopper/chopper.dart';
+import 'package:equatable/equatable.dart';
+import 'package:theta_concept_7/services/theta_service.dart';
+
+part 'camera_use_event.dart';
+part 'camera_use_state.dart';
+
+class CameraUseBloc extends Bloc {
+ CameraUseBloc() : super(CameraUseState.initial()) {
+ var chopper = ChopperClient(
+ services: [ThetaService.create()], converter: const JsonConverter());
+ final thetaService = chopper.getService();
+ Stopwatch stopwatch = Stopwatch();
+ on((event, emit) async {
+ var response =
+ await thetaService.command({'name': 'camera.startCapture'});
+ var convertResponse = jsonDecode(response.bodyString);
+ var id = convertResponse['id'];
+
+ if (convertResponse != null && id != null) {
+ stopwatch.start();
+ emit(CameraUseState(message: response.bodyString, id: id));
+ while (state.cameraStatus != "done") {
+ add(CameraStatusEvent());
+ await Future.delayed(Duration(milliseconds: 100));
+ print(state.cameraStatus);
+ emit(CameraUseState(
+ message: response.bodyString,
+ id: id,
+ cameraStatus: state.cameraStatus,
+ fileUrl: state.fileUrl,
+ elapsedTime: stopwatch.elapsedMilliseconds.toDouble()));
+ }
+ stopwatch.stop();
+ stopwatch.reset();
+ }
+ });
+ on((event, emit) async {
+ var response = await thetaService.command({'name': 'camera.stopCapture'});
+ var convertResponse = jsonDecode(response.bodyString);
+ var fileUrl = convertResponse['results']['fileUrls'][0];
+ print(fileUrl);
+ emit(CameraUseState(
+ message: response.bodyString,
+ elapsedTime: state.elapsedTime,
+ fileUrl: fileUrl));
+ });
+ on((event, emit) async {
+ if (state.id.isNotEmpty) {
+ var response = await thetaService.status({'id': state.id});
+ var convertResponse = jsonDecode(response.bodyString);
+ var cameraState = convertResponse['state'];
+
+ emit(CameraUseState(
+ message: response.bodyString,
+ id: state.id,
+ cameraStatus: cameraState,
+ elapsedTime: state.elapsedTime,
+ fileUrl: state.fileUrl));
+ }
+ });
+ on((event, emit) async {
+ var response = await thetaService.command({
+ 'name': 'camera.setOptions',
+ 'parameters': {
+ 'options': {'captureMode': 'video'}
+ }
+ });
+ });
+ }
+}
diff --git a/lib/bloc/camera_use/camera_use_event.dart b/lib/bloc/camera_use/camera_use_event.dart
new file mode 100644
index 0000000..fc6d476
--- /dev/null
+++ b/lib/bloc/camera_use/camera_use_event.dart
@@ -0,0 +1,16 @@
+part of 'camera_use_bloc.dart';
+
+abstract class CameraUseEvent extends Equatable {
+ const CameraUseEvent();
+
+ @override
+ List