Issue 1:
Steps to Reproduce

Android Video Plays correctly in either portrait or landscape video modes

iOS Video is warped on portrait and landscape looks normal.

It is not accounting for orientation.

when you record a video in landscape with the volume buttons facing up on iPhone and go to the video controller to play the video, it is upside down. If you take a video in landscape with the lock button facing up the video looks normal.

dependencies in pubspec.yaml

dependencies:
flutter:
sdk: flutter
async: "^2.0.6"
cupertino_icons: ^0.1.0
url_launcher: "^3.0.0"
intl: 0.15.4
local_auth: "^0.2.0"
shared_preferences: "^0.4.0"
firebase_core: "^0.2.3"
firebase_analytics: "^0.3.3"
material_search: "^0.2.3"
flutter_webview_plugin: "^0.1.5"
device_info: "^0.2.0"
path_provider: "^0.4.0"
path: "^1.5.1"
video_player: "0.5.2"
dio: "^0.0.12"
get_version:
git:
url: git://github.com/AppleEducate/get_version
media_picker:
git:
url: git://github.com/AppleEducate/media_picker

Usage

import 'dart:async';
import 'package:async/async.dart';
import 'dart:io';
import 'package:path/path.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:media_picker/media_picker.dart';
import 'package:video_player/video_player.dart';
import 'package:Unify_Mobile/globals.dart' as globals;
import 'package:Unify_Mobile/menu/videodetails.dart';
import 'package:dio/dio.dart';

class CameraPage extends StatefulWidget {
@override
_CameraPageState createState() => new _CameraPageState();
}

// State for managing fetching name data over HTTP
class _CameraPageState extends State<CameraPage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
Future<File> _mediaFile;
File _uploadFile;
bool isVideo = false;
VideoPlayerController _controller;
VoidCallback listener;
bool isPlaying = false;

void _onImageButtonPressed(ImageSource source) {
setState(() {
if (_controller != null) {
_controller.setVolume(0.0);
_controller.removeListener(listener);
}
_mediaFile = MediaPicker.pickVideo(source: source).then((File _file) {
_controller = VideoPlayerController.file(_file)
..addListener(listener)
..setVolume(1.0)
..initialize()
..setLooping(true)
..play();
setState(() {
isPlaying = true;
_uploadFile = _file;
});
});
});
}

@override
void deactivate() {
if (_controller != null) {
_controller.setVolume(0.0);
_controller.removeListener(listener);
}
super.deactivate();
}

@override
void dispose() {
if (_controller != null) {
_controller.dispose();
}
super.dispose();
}

@override
void initState() {
super.initState();
listener = () {
setState(() {});
};
}

Widget _previewVideo(VideoPlayerController controller) {
if (controller == null) {
isPlaying = false;
return const Text('Please Select or Record a Video.');
} else if (controller.value.initialized) {
return InkWell(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: AspectRatio(
aspectRatio:
controller.value.size.width / controller.value.size.height,
child: VideoPlayer(
controller,
),
),
),
onTap: () {
if (isPlaying) {
_controller.pause();
isPlaying = false;
} else {
_controller.play();
isPlaying = true;
}
});
} else {
isPlaying = false;
return const Text('Error Loading Video');
}
}

Future uploadVideo(BuildContext context, File _uploadFile, String name,
String description) async {
final _name = name;
final _description = description;
if (_controller == null) {
globals.Utility
.showAlertPopup(context, "Info", "Video Required for Upload!");
} else {
final _ks = await globals.Utility.getKalturaSession();
// Add Video
String _token = "";
await http
.get(
'https://www.kaltura.com/api_v3/service/uploadtoken/action/add?ks=$_ks&format=1')
.then((response) {
Map<String, dynamic> _json = json.decode(response.body);
_token = _json['id'].toString();
print('"Token: $_token');
});

// Upload Video
String _url =
"https://www.kaltura.com/api_v3/service/uploadtoken/action/upload?ks=$_ks&format=1&uploadTokenId=$_token&resume=false&finalChunk=true&resumeAt=-1";
print("Path: " + _uploadFile.uri.toString());

await uploadFile(_url, _uploadFile, 'fileData');

// Update Video Info (Name, Desctiption, Tags)
var _formName = Uri.encodeQueryComponent(r'mediaEntry[name]');
var _formDesription =
Uri.encodeQueryComponent(r'mediaEntry[description]');
var _formTags = Uri.encodeQueryComponent(r'mediaEntry[tags]');
var _formCatagory = Uri.encodeQueryComponent(r'mediaEntry[categories]');
var _formType = Uri.encodeQueryComponent(r'mediaEntry[mediaType]');
String _request =
'https://www.kaltura.com/api_v3/service/media/action/addFromUploadedFile?ks=$_ks&format=1&$_formTags=${globals.userCompanyID}&$_formName=$_name&$_formDesription=$_description&uploadTokenId=$_token&$_formCatagory=Unapproved&$_formType=1';
print(_request);
await http.get(_request).then((response) {
print('Updated Info...\n' + response.body.toString());
Map<String, dynamic> _json = json.decode(response.body);
// Verify Upload
_scaffoldKey.currentState.hideCurrentSnackBar();
globals.videoID = "" + _json["id"].toString();
Navigator.pop(context);
});
}
}

Future uploadFile(String url, File file, String name) async {
var stream =
new http.ByteStream(DelegatingStream.typed(file.openRead()));
var length = await file.length();
var uri = Uri.parse(url);
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile(name, stream, length,
filename: basename(file.path));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}

void _uploadVideo(BuildContext context) async {
final snackbar = new SnackBar(
duration: new Duration(seconds: 20),
content: new Row(
children: <Widget>[
new CircularProgressIndicator(),
new Text(" Uploading...")
],
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
await uploadVideo(context, _uploadFile, _nameController.text.toString(),
_descController.text.toString());
_scaffoldKey.currentState.hideCurrentSnackBar();
// Navigator.pop(context);
}

void handelTextChange(String value) {
setState(() {});
}

final TextEditingController _nameController = new TextEditingController();
final TextEditingController _descController = new TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('Video Upload'),
backgroundColor: Colors.white,
actions: <Widget>[
new IconButton(
icon: new Icon(
Icons.help,
),
onPressed: () {
globals.Utility.showAlertPopup(context, 'Info',
"Please Record in Landscape Mode for Best Results.\n\nFor Higher Quality Videos and to Prevent Data Loss, Capture and Edit a Video in the Camera App then Select the Video Here.\n\nOnce the Video is Uploaded it will be Avaliable in the 'Videos' Section After it Completes Processing.");
},
),
new IconButton(
icon: new Icon(Icons.file_upload),
onPressed: () {
if (_nameController.text.toString().isNotEmpty &&
_descController.text.toString().isNotEmpty) {
_uploadVideo(context);
} else {
globals.Utility.showAlertPopup(
context, "Info", "Name and Description Required!");
}
})
],
),
body: new SingleChildScrollView(
child: new ListBody(
children: <Widget>[
new ListTile(
title: new TextField(
controller: _nameController,
onChanged: handelTextChange,
decoration: new InputDecoration(
hintText: "Name",
),
),
trailing: _nameController.text.toString().isEmpty
? new Icon(
Icons.error,
color: Colors.red,
)
: new Icon(
Icons.check_circle,
color: Colors.green,
),
),
new ListTile(
title: new TextField(
controller: _descController,
onChanged: handelTextChange,
decoration: new InputDecoration(
hintText: "Description",
),
),
trailing: _descController.text.toString().isEmpty
? new Icon(
Icons.error,
color: Colors.red,
)
: new Icon(
Icons.check_circle,
color: Colors.green,
),
),
new Container(
height: 20.0,
),
new Center(
child: _previewVideo(_controller),
)
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
_onImageButtonPressed(ImageSource.gallery);
},
heroTag: 'video0',
tooltip: 'Pick Video from gallery',
child: const Icon(Icons.video_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
_onImageButtonPressed(ImageSource.camera);
},
heroTag: 'video1',
tooltip: 'Take a Video',
child: const Icon(Icons.videocam),
),
),
],
),
);
}
}

Logs

Analyzing /Users/rodydavis/Documents/Github/MyUnifyVideo...
hint • Unused import: 'package:Unify_Mobile/menu/videodetails.dart' at package:Unify_Mobile/camera.dart:15:8 • unused_import
hint • Unused import: 'package:dio/dio.dart' at package:Unify_Mobile/camera.dart:16:8 • unused_import
hint • The value of the field '_mediaFile' isn't used at package:Unify_Mobile/camera.dart:26:16 • unused_field
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom/custom_widgets.dart:3:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom/custom_widgets.dart:58:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom/custom_widgets.dart:85:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom/custom_widgets.dart:116:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom/custom_widgets.dart:163:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom/custom_widgets.dart:287:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom/custom_widgets.dart:462:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom_widgets.dart:3:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom_widgets.dart:58:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom_widgets.dart:85:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom_widgets.dart:116:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom_widgets.dart:163:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom_widgets.dart:237:7 • must_be_immutable
hint • This class inherits from a class marked as @immutable, and therefore should be immutable (all instance fields must be final) at package:Unify_Mobile/custom_widgets.dart:412:7 • must_be_immutable
hint • Duplicate import at package:Unify_Mobile/main.dart:5:8 • duplicate_import
hint • Unused import: 'package:Unify_Mobile/menu/myaccount.dart' at package:Unify_Mobile/menu/contactsleads.dart:6:8 • unused_import
hint • Unused import: 'package:material_search/material_search.dart' at package:Unify_Mobile/menu/contactsleads.dart:8:8 • unused_import
hint • Unused import: 'package:flutter/scheduler.dart' at package:Unify_Mobile/menu/contactsleads.dart:9:8 • unused_import
hint • Unused import: 'dart:convert' at package:Unify_Mobile/menu/help.dart:1:8 • unused_import
hint • Unused import: 'package:flutter/rendering.dart' at package:Unify_Mobile/menu/help.dart:3:8 • unused_import
hint • Unused import: 'dart:async' at package:Unify_Mobile/menu/help.dart:6:8 • unused_import
hint • Unused import: 'dart:io' at package:Unify_Mobile/menu/help.dart:8:8 • unused_import
hint • The method '_readAndroidBuildData' isn't used at package:Unify_Mobile/menu/help.dart:67:24 • unused_element
hint • The method '_readIosDeviceInfo' isn't used at package:Unify_Mobile/menu/help.dart:97:24 • unused_element
hint • Unused import: 'dart:convert' at package:Unify_Mobile/menu/settings.dart:1:8 • unused_import
hint • Unused import: 'package:flutter/rendering.dart' at package:Unify_Mobile/menu/settings.dart:3:8 • unused_import
hint • Unused import: 'package:Unify_Mobile/globals.dart' at package:Unify_Mobile/menu/settings.dart:4:8 • unused_import
hint • Unused import: 'package:device_info/device_info.dart' at package:Unify_Mobile/menu/settings.dart:5:8 • unused_import
hint • Unused import: 'dart:async' at package:Unify_Mobile/menu/settings.dart:6:8 • unused_import
hint • Unused import: 'package:flutter/services.dart' at package:Unify_Mobile/menu/settings.dart:7:8 • unused_import
hint • Unused import: 'package:Unify_Mobile/menu/myaccount.dart' at package:Unify_Mobile/menu/tabs.dart:6:8 • unused_import
hint • Unused import: 'dart:io' at package:Unify_Mobile/menu/tabs.dart:11:8 • unused_import
hint • The top level variable '_companyImageURL' isn't used at package:Unify_Mobile/menu/tabs.dart:31:14 • unused_element
hint • The value of the field '_drawerContentsOpacity' isn't used at package:Unify_Mobile/menu/tabs.dart:38:21 • unused_field
hint • The value of the field '_drawerDetailsPosition' isn't used at package:Unify_Mobile/menu/tabs.dart:40:21 • unused_field
hint • The value of the field '_showDrawerContents' isn't used at package:Unify_Mobile/menu/tabs.dart:41:8 • unused_field
hint • The method '_backIcon' isn't used at package:Unify_Mobile/menu/tabs.dart:104:12 • unused_element
hint • The value of the field '_drawerContents' isn't used at package:Unify_Mobile/menu/tabs.dart:131:29 • unused_field
hint • The value of the field '_drawerContentsIcons' isn't used at package:Unify_Mobile/menu/tabs.dart:136:29 • unused_field
hint • The value of the local variable 'index' isn't used at package:Unify_Mobile/menu/tabs/archivedvideos.dart:99:9 • unused_local_variable
hint • The value of the local variable 'index' isn't used at package:Unify_Mobile/menu/tabs/myvideos.dart:87:9 • unused_local_variable
hint • The value of the local variable 'index' isn't used at package:Unify_Mobile/menu/tabs/sharedvideos.dart:99:9 • unused_local_variable
hint • Unused import: 'package:flutter_webview_plugin/flutter_webview_plugin.dart' at package:Unify_Mobile/menu/videodetails.dart:7:8 • unused_import
hint • The value of the local variable 'ccToggleBool' isn't used at package:Unify_Mobile/menu/videodetails.dart:443:12 • unused_local_variable
hint • Unused import: 'package:device_info/device_info.dart' at package:Unify_Mobile/signin/forgot.dart:5:8 • unused_import
hint • Unused import: 'package:flutter/services.dart' at package:Unify_Mobile/signin/forgot.dart:7:8 • unused_import
hint • Unused import: 'package:get_version/get_version.dart' at package:Unify_Mobile/signin/forgot.dart:9:8 • unused_import
hint • The value of the field '_controllerUsername' isn't used at package:Unify_Mobile/signin/forgot.dart:19:31 • unused_field
hint • The value of the field '_controllerDomain' isn't used at package:Unify_Mobile/signin/forgot.dart:20:31 • unused_field
hint • The value of the field '_scaffoldKey' isn't used at package:Unify_Mobile/signin/forgot.dart:22:9 • unused_field
hint • Unused import: 'package:Unify_Mobile/menu/tabs.dart' at package:Unify_Mobile/signin/signin.dart:6:8 • unused_import
54 issues found.
(Ran in 7.4s)

[✓] Flutter (Channel beta, v0.3.2, on Mac OS X 10.13.4 17E199, locale en-US)
• Flutter version 0.3.2 at /Users/rodydavis/Android/flutter/flutter
• Framework revision 44b7e7d3f4 (4 weeks ago), 2018-04-20 01:02:44 -0700
• Engine revision 09d05a3891
• Dart version 2.0.0-dev.48.0.flutter-fe606f890b

[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
• Android SDK at /Users/rodydavis/Library/Android/sdk
• Android NDK at /Users/rodydavis/Library/Android/sdk/ndk-bundle
• Platform android-27, build-tools 27.0.3
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
• All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 9.3)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 9.3, Build version 9E145
• ios-deploy 1.9.2
• CocoaPods version 1.4.0

[✓] Android Studio (version 3.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 24.0.1
• Dart plugin version 173.4700
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)

[✓] VS Code (version 1.23.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Dart Code extension version 2.12.1

[✓] Connected devices (3 available)
• Rody’s 📱 • 68cab38f1e7de5b8aece2a1ebb7ca9a5d4761e19 • ios • iOS 11.3.1
• Dev-iPhone-6s • a75015aff2fbecb29dcc8e459b14cba86c08f7fe • ios • iOS 11.3.1
• • 90288c0d9ae73afb8a84663c0475d208744fc569 • ios • iOS

• No issues found!

Issue 2:
Steps to Reproduce

When building a new flutter project in IntelliJ, company domain cookytech.in

-> entered as `in`.cookytech.mnshi will throw compiler errors because XML files will get the `in` part with the graves,

-> entered as in.cookytech.mnshi will throw compiler errors because 'in' is a keyword in dart, kotlin, and java

Current Solution

enter in.cookytech as company domain, and then manually add graves in kotlin files. This will allow for compilation.

Logs

Initializing gradle...
Resolving dependencies...
Running 'gradlew assembleDebug'...
e: /home/raveesh/MyCode/Code/Training/Flutter/mnshi/android/app/src/main/kotlin/in/cookytech/mnshi/MainActivity.kt: (1, 9): Package name must be a '.'-separated identifier list

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugKotlin'.
> Compilation error. See log for more details

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
Finished with error: Gradle build failed: 1

Flutter Doctor

[✓] Flutter (on Linux, locale en_IN, channel alpha)
• Flutter at /home/raveesh/MyCode/Flutter/flutter
• Framework revision 8f65fec5f5 (6 days ago), 2017-12-12 09:50:14 -0800
• Engine revision edaecdc8b8
• Tools Dart version 1.25.0-dev.11.0
• Engine Dart version 2.0.0-edge.d8ae797298c3a6cf8dc9f4558707bd2672224d3e

[✓] Android toolchain - develop for Android devices (Android SDK 27.0.2)
• Android SDK at /home/raveesh/MyCode/Android/SDK
• Android NDK at /home/raveesh/MyCode/Android/SDK/ndk-bundle
• Platform android-27, build-tools 27.0.2
• Java binary at: /usr/local/android-studio/jre/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b01)

[✓] Android Studio (version 3.0)
• Android Studio at /usr/local/android-studio
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b01)

[✓] IntelliJ IDEA Ultimate Edition (version 2017.3)
• Flutter plugin version 20.0.3
• Dart plugin version 173.3942.31

[✓] Connected devices
• Lenovo K33a42 • 9b8bcc9f • android-arm • Android 7.1.2 (API 25)

Using:

IntelliJ IDEA 2017.3.1 (Ultimate Edition)
Build #IU-173.3942.27, built on December 11, 2017
Licensed to Raveesh Agarwal
Subscription is active until May 28, 2018
For educational use only.
JRE: 1.8.0_152-release-1024-b8 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Linux 4.10.0-42-generic