Creating Extensions in iOS video
- In following walkthrough, you will create an example Today widget that calculates the day and number of days remaining in the year: Creating the solution. To create the required solution, do the following: First, create a new iOS, Single View App project and click the Next button: Call the project TodayContainer and click the Next button.
- Use widgets with iOS 13 or above From the Home screen, swipe from left to right to access the widget screen. Scroll to the bottom of the screen and tap Edit. Find Todoist Today in the Add Widgets screen, and tap the green + icon.
If still cannot record, please do the format again. Do not touch anything at this moment and make sure the power supply and cable connection is stable. Changes: - Add Spanish / Japanese / Malaysian language - When testing the schedule recording feature, do not change the time earlier back using custom time mode, just can only be later. In Teams, there are indicators on the desktop, the web, iOS, and Android which can alert you to the presence of the people you’re working with. Here’s a look at how you can check the online. We’re thrilled to offer iOS 14 users a OneDrive widget. We’ve made 2 improvements to it in this update: We’ve fixed an issue causing an unexpected dialog to show when you tapped the widget to sign into a personal account. We’ve improved our widget to show even sharper, crisper image previews.
Extensions, as introduced in iOS 8, are specialized UIViewControllers
that are presented by iOS inside standard contexts such as within the Notification Center, as custom keyboard types requested by the user to perform specialized input or other contexts like editing a photo where the Extension can provide special effect filters.
All Extensions are installed in conjunction with a Container app (with both elements written using the 64-bit Unified APIs) and are activated from a particular Extension Point in a Host app. And since they will be used as supplements to existing system functions, they must be high performance, lean, and robust.
Extension points
Type | Description | Extension Point | Host App |
---|---|---|---|
Action | Specialized editor or viewer for a particular media type | com.apple.ui-services | Any |
Document Provider | Allows app to use a remote document store | com.apple.fileprovider-ui | Apps using a UIDocumentPickerViewController |
Keyboard | Alternate keyboards | com.apple.keyboard-service | Any |
Photo Editing | Photo manipulation and editing | com.apple.photo-editing | Photos.app editor |
Share | Shares data with social networks, messaging services, etc. | com.apple.share-services | Any |
Today | “Widgets” that appear on the Today screen or Notification Center | com.apple.widget-extensions | Today and Notification Center |
Additional extension points were added in iOS 10 and iOS 12. You can find the complete table of all supported types in the iOS App Extension Programming Guide.
Limitations
Extensions have a number of limitations, some of which are universal to all types (for instance, no type of Extension can access the cameras or microphones) while other types of Extension may have specific limitations on their usage (for instance, custom keyboards cannot be used for secure data entry fields such as for passwords).
The universal limitations are:
- The Health Kit and Event Kit UI Frameworks are not available
- Extensions cannot use extended background modes
- Extensions cannot access the device’s cameras or microphones (although they may access existing media files)
- Extensions cannot receive Air Drop data (although they can transmit data via Air Drop)
- UIActionSheet and UIAlertView are not available; extensions must use UIAlertController
- Several members of UIApplication are unavailable: UIApplication.SharedApplication, UIApplication.OpenUrl, UIApplication.BeginIgnoringInteractionEvents and UIApplication.EndIgnoringInteractionEvents
- iOS enforces a 16 MB memory usage limit on Today's extensions.
- By default keyboard extensions don't have access to the network. This affects debugging on device (the restriction is not enforced in the simulator), since Xamarin.iOS requires network access for debugging to work. It's possible to request network access by setting the
Requests Open Access
value in the project's Info.plist toYes
. Please see Apple's Custom Keyboard Guide for more information about keyboard extension limitations.
For individual limitations, please see Apple's App Extension Programming Guide.
Distributing, installing, and running extensions
Extensions are distributed from within a container app, which, in turn is submitted and distributed via the App Store. The Extension(s) distributed with the app are installed at that point, but the user must enable each Extension explicitly. The different types of Extensions are enabled in different ways; several require the user to navigate to the Settings app and enable them from there. While others are enabled at point of use, such as enabling a Sharing Extension when sending a photo.
The app in which the Extension is used (where the user encounters the Extension Point) is referred to as the Host app, since it is the app that hosts the Extension when it executes. The app that installs the Extension is the Container app, because it is the app that contained the Extension when it was installed.
Typically, the container app describes the extension and walks the user through the process of enabling it.
Debug and release versions of extensions
Memory limits for running app extensions are significantly lower than the memory limits applied to a foreground app. Simulators running iOS have less restrictions applied to extensions, and you can execute your extension without any issues. However, running the same extension on a device can lead to unexpected results, including the extension crashing or being aggressively terminated by the system. Therefore, ensure you build and test the extension on a device before shipping it.
You should ensure that the following settings are applied to the container project and all referenced extensions:
- Build a application package in Release configuration.
- In the iOS Build project settings, set the Linker behavior option to Link Framework SDKs Only or Link All.
- In the iOS Debug project settings, uncheck the Enable debugging and Enable profiling option.
Extension lifecycle
An Extension can be as simple as a single UIViewController or more complex Extensions that present multiple screens of UI. When the user encounters an Extension Points (such as when sharing an image), they will have an opportunity to choose from the Extensions registered for that Extension Point.
If they choose one of your app's Extensions, its UIViewController
will be instantiated and begin the normal View Controller lifecycle. However, unlike a normal app, which are suspended but not generally terminated when the user finishes interacting with them, Extensions are loaded, executed, and then terminated repeatedly.
Extensions can communicate with their Host apps via an NSExtensionContext object. Some Extensions have operations that receive asynchronous callbacks with the results. These callbacks will be executed on background threads and the Extension must take this into consideration; for instance, by using NSObject.InvokeOnMainThread if they want to update the user interface. See the Communicating with the Host App section below for more details.
By default, Extensions and their container apps can not communicate, despite being installed together. In some cases, the Container app is essentially an empty 'shipping' container whose purpose is served once the Extension is installed. However, if circumstances dictate, the Container app and the Extension may share resources from a common area. Additionally, a Today Extension may request its Container app to open a URL. This behavior is shown in the Event Countdown Widget.
Creating an extension
Extensions (and their Container apps) must be 64-bit binaries and built using the Xamarin.iOS Unified APIs. When developing an Extension, your solutions will contain at least two projects: the container app and one project for each Extension the container provides.
Container app project requirements
The Container app used to install the Extension has the following requirements:
- It must maintain a reference to the Extension project.
- It must be a complete app (must be able to launch and run successfully) even if it does nothing more than provide a way to install an Extension.
- It must have a Bundle Identifier that is the basis for the Bundle Identifier of the Extension project (see the section below for more details).
Extension project requirements
Additionally, the Extension's project has the following requirements:
It must have a Bundle Identifier that starts with its Container app's Bundle Identifier. For example, if the Container app's has a Bundle Identifier of
com.myCompany.ContainerApp
, the Extension's identifier might becom.myCompany.ContainerApp.MyExtension
:It must define the key
NSExtensionPointIdentifier
, with an appropriate value (such ascom.apple.widget-extension
for a Today Notification Center widget), in itsInfo.plist
file.It must also define either the
NSExtensionMainStoryboard
key or theNSExtensionPrincipalClass
key in itsInfo.plist
file with an appropriate value:- Use the
NSExtensionMainStoryboard
key to specify the name of the Storyboard that presents the main UI for the Extension (minus.storyboard
). For example,Main
for theMain.storyboard
file. - Use the
NSExtensionPrincipalClass
key to specify the class that will be initialized when the Extension is started. The value must match the Register value of yourUIViewController
:
- Use the
Specific types of Extensions may have additional requirements. For instance, a Today or Notification Center Extension’s principal class must implement INCWidgetProviding.
Important
If you start your project using one the Extensions templates provided by Visual Studio for Mac, most (if not all) these requirements will be provided and met for you automatically by the template.
Walkthrough
In following walkthrough, you will create an example Today widget that calculates the day and number of days remaining in the year:
Creating the solution
To create the required solution, do the following:
First, create a new iOS, Single View App project and click the Next button:
Call the project
TodayContainer
and click the Next button:Verify the Project Name and SolutionName and click the Create button to create the solution:
Next, in the Solution Explorer, right-click on the Solution and add a new iOS Extension project from the Today Extension template:
Call the project
DaysRemaining
and click the Next button:Review the project and click the Create button to create it:
The resulting Solution should now have two projects, as shown here:
Creating the extension user interface
Next, you will need to design the interface for your Today widget. This can either be done using a Storyboard or by creating the UI in code. Both methods will be covered below in detail.
Using storyboards
To build the UI with a Storyboard, do the following:
In the Solution Explorer, double-click the Extension project's
Main.storyboard
file to open it for editing:Select the Label that was automatically added to the UI by template and give it the Name
TodayMessage
in the Widget tab of the Properties Explorer:Save the changes to the Storyboard.
Using code
To build the UI in code, do the following:
In the Solution Explorer, select the DaysRemaining project, add a new class and call it
CodeBasedViewController
:Again, in the Solution Explorer, double-click Extension's
Info.plist
file to open it for editing:Select the Source View (from the bottom of the screen) and open the
NSExtension
node:Remove the
NSExtensionMainStoryboard
key and add aNSExtensionPrincipalClass
with the valueCodeBasedViewController
:Save your changes.
Next, edit the CodeBasedViewController.cs
file and make it look like the following:
Note that the [Register('CodeBasedViewController')]
matches the value that you specified for the NSExtensionPrincipalClass
above.
Coding the extension
With the User Interface created, open either the TodayViewController.cs
or the CodeBasedViewController.cs
file (based of the method used to create the User Interface above), change the ViewDidLoad method and make it look like the following:
If using the code based User Interface method, replace the // Insert code to power extension here...
comment with the new code from above. After calling the base implementation (and inserting a Label for the code based version), this code does a simple calculation to get the day of the year and how many days are remaining. Then it displays the message in the Label (TodayMessage
) that you created in the UI design.
Note how similar this process is to the normal process of writing an app. An Extension's UIViewController
has the same lifecycle as a View Controller in an app, except Extensions do not have background modes and are not suspended when the user is finished using them. Instead, Extensions are repeatedly initialized and de-allocated as required.
Creating the container app user interface
For this walkthrough, the container app is simply used as a method to ship and install the Extension and provides no functionality of its own. Edit the TodayContainer's Main.storyboard
file and add some text defining the Extension's function and how to install it:
Save the changes to the Storyboard.
Testing the extension
Microsoft To Do Widget Ios 12
To test your Extension in the iOS Simulator, run the TodayContainer app. The container's main view will be displayed:
Next, hit the Home button in the Simulator, swipe down from the top of the screen to open the Notification Center, select the Today tab and click the Edit button:
Add the DaysRemaining Extension to the Today view and click the Done button:
The new widget will be added to the Today view and the results will be displayed:
Communicating with the host app
The example Today Extension you created above does not communicate with its host app (the Today screen). If it did, it would use the ExtensionContext property of the TodayViewController
or CodeBasedViewController
classes.
For Extensions that will receive data from their host apps, the data is in the form of an array of NSExtensionItem objects stored in the InputItems property of the ExtensionContext of the Extension's UIViewController
.
Other Extensions, such as Photo Editing extensions, may distinguish between the user completing or canceling usage. This will be signaled back to the host app via the CompleteRequest and CancelRequest methods of ExtensionContext property.
For more information, please see Apple's App Extension Programming Guide.
Communicating with the parent app
An App Group allows different applications (or an application and its extensions) to access a shared file storage location. App Groups can be used for data like:
- Apple Watch Settings.
- Shared NSUserDefaults.
- Shared Files.
For more information, please see the App Groups section of our Working with Capabilities documentation.
MobileCoreServices
When working with extensions, use a Uniform Type Identifier (UTI) to create and manipulate data that is exchanged between the app, other apps and/or services.
The MobileCoreServices.UTType
static class defines the following helper properties that relate to Apple's kUTType...
definitions:
kUTTypeAlembic
-Alembic
kUTTypeAliasFile
-AliasFile
kUTTypeAliasRecord
-AliasRecord
kUTTypeAppleICNS
-AppleICNS
kUTTypeAppleProtectedMPEG4Audio
-AppleProtectedMPEG4Audio
kUTTypeAppleProtectedMPEG4Video
-AppleProtectedMPEG4Video
kUTTypeAppleScript
-AppleScript
kUTTypeApplication
-Application
kUTTypeApplicationBundle
-ApplicationBundle
kUTTypeApplicationFile
-ApplicationFile
kUTTypeArchive
-Archive
kUTTypeAssemblyLanguageSource
-AssemblyLanguageSource
kUTTypeAudio
-Audio
kUTTypeAudioInterchangeFileFormat
-AudioInterchangeFileFormat
kUTTypeAudiovisualContent
-AudiovisualContent
kUTTypeAVIMovie
-AVIMovie
kUTTypeBinaryPropertyList
-BinaryPropertyList
kUTTypeBMP
-BMP
kUTTypeBookmark
-Bookmark
kUTTypeBundle
-Bundle
kUTTypeBzip2Archive
-Bzip2Archive
kUTTypeCalendarEvent
-CalendarEvent
kUTTypeCHeader
-CHeader
kUTTypeCommaSeparatedText
-CommaSeparatedText
kUTTypeCompositeContent
-CompositeContent
kUTTypeConformsToKey
-ConformsToKey
kUTTypeContact
-Contact
kUTTypeContent
-Content
kUTTypeCPlusPlusHeader
-CPlusPlusHeader
kUTTypeCPlusPlusSource
-CPlusPlusSource
kUTTypeCSource
-CSource
kUTTypeData
-Database
kUTTypeDelimitedText
-DelimitedText
kUTTypeDescriptionKey
-DescriptionKey
kUTTypeDirectory
-Directory
kUTTypeDiskImage
-DiskImage
kUTTypeElectronicPublication
-ElectronicPublication
kUTTypeEmailMessage
-EmailMessage
kUTTypeExecutable
-Executable
kUTExportedTypeDeclarationsKey
-ExportedTypeDeclarationsKey
kUTTypeFileURL
-FileURL
kUTTypeFlatRTFD
-FlatRTFD
kUTTypeFolder
-Folder
kUTTypeFont
-Font
kUTTypeFramework
-Framework
kUTTypeGIF
-GIF
kUTTypeGNUZipArchive
-GNUZipArchive
kUTTypeHTML
-HTML
kUTTypeICO
-ICO
kUTTypeIconFileKey
-IconFileKey
kUTTypeIdentifierKey
-IdentifierKey
kUTTypeImage
-Image
kUTImportedTypeDeclarationsKey
-ImportedTypeDeclarationsKey
kUTTypeInkText
-InkText
kUTTypeInternetLocation
-InternetLocation
kUTTypeItem
-Item
kUTTypeJavaArchive
-JavaArchive
kUTTypeJavaClass
-JavaClass
kUTTypeJavaScript
-JavaScript
kUTTypeJavaSource
-JavaSource
kUTTypeJPEG
-JPEG
kUTTypeJPEG2000
-JPEG2000
kUTTypeJSON
-JSON
kUTType3dObject
-k3dObject
kUTTypeLivePhoto
-LivePhoto
kUTTypeLog
-Log
kUTTypeM3UPlaylist
-M3UPlaylist
kUTTypeMessage
-Message
kUTTypeMIDIAudio
-MIDIAudio
kUTTypeMountPoint
-MountPoint
kUTTypeMovie
-Movie
kUTTypeMP3
-MP3
kUTTypeMPEG
-MPEG
kUTTypeMPEG2TransportStream
-MPEG2TransportStream
kUTTypeMPEG2Video
-MPEG2Video
kUTTypeMPEG4
-MPEG4
kUTTypeMPEG4Audio
-MPEG4Audio
kUTTypeObjectiveCPlusPlusSource
-ObjectiveCPlusPlusSource
kUTTypeObjectiveCSource
-ObjectiveCSource
kUTTypeOSAScript
-OSAScript
kUTTypeOSAScriptBundle
-OSAScriptBundle
kUTTypePackage
-Package
kUTTypePDF
-PDF
kUTTypePerlScript
-PerlScript
kUTTypePHPScript
-PHPScript
kUTTypePICT
-PICT
kUTTypePKCS12
-PKCS12
kUTTypePlainText
-PlainText
kUTTypePlaylist
-Playlist
kUTTypePluginBundle
-PluginBundle
kUTTypePNG
-PNG
kUTTypePolygon
-Polygon
kUTTypePresentation
-Presentation
kUTTypePropertyList
-PropertyList
kUTTypePythonScript
-PythonScript
kUTTypeQuickLookGenerator
-QuickLookGenerator
kUTTypeQuickTimeImage
-QuickTimeImage
kUTTypeQuickTimeMovie
-QuickTimeMovie
kUTTypeRawImage
-RawImage
kUTTypeReferenceURLKey
-ReferenceURLKey
kUTTypeResolvable
-Resolvable
kUTTypeRTF
-RTF
kUTTypeRTFD
-RTFD
kUTTypeRubyScript
-RubyScript
kUTTypeScalableVectorGraphics
-ScalableVectorGraphics
kUTTypeScript
-Script
kUTTypeShellScript
-ShellScript
kUTTypeSourceCode
-SourceCode
kUTTypeSpotlightImporter
-SpotlightImporter
kUTTypeSpreadsheet
-Spreadsheet
kUTTypeStereolithography
-Stereolithography
kUTTypeSwiftSource
-SwiftSource
kUTTypeSymLink
-SymLink
kUTTypeSystemPreferencesPane
-SystemPreferencesPane
kUTTypeTabSeparatedText
-TabSeparatedText
kUTTagClassFilenameExtension
-TagClassFilenameExtension
kUTTagClassMIMEType
-TagClassMIMEType
kUTTypeTagSpecificationKey
-TagSpecificationKey
kUTTypeText
-Text
kUTType3DContent
-ThreeDContent
kUTTypeTIFF
-TIFF
kUTTypeToDoItem
-ToDoItem
kUTTypeTXNTextAndMultimediaData
-TXNTextAndMultimediaData
kUTTypeUniversalSceneDescription
-UniversalSceneDescription
kUTTypeUnixExecutable
-UnixExecutable
kUTTypeURL
-URL
kUTTypeURLBookmarkData
-URLBookmarkData
kUTTypeUTF16ExternalPlainText
-UTF16ExternalPlainText
kUTTypeUTF16PlainText
-UTF16PlainText
kUTTypeUTF8PlainText
-UTF8PlainText
kUTTypeUTF8TabSeparatedText
-UTF8TabSeparatedText
kUTTypeVCard
-VCard
kUTTypeVersionKey
-VersionKey
kUTTypeVideo
-Video
kUTTypeVolume
-Volume
kUTTypeWaveformAudio
-WaveformAudio
kUTTypeWebArchive
-WebArchive
kUTTypeWindowsExecutable
-WindowsExecutable
kUTTypeX509Certificate
-X509Certificate
kUTTypeXML
-XML
kUTTypeXMLPropertyList
-XMLPropertyList
kUTTypeXPCService
-XPCService
kUTTypeZipArchive
-ZipArchive
See the following example:
For more information, please see the App Groups section of our Working with Capabilities documentation.
Precautions and considerations
Extensions have significantly less memory available to them than apps do. They are expected to perform rapidly and with minimal intrusion to the user and the app they are hosted in. However, an Extension should also provide a distinctive, useful function to the consuming app with a branded UI that allow the user to identify the Extension's developer or Container app they belong to.
Given these tight requirement, you should only deploy Extensions that have been thoroughly tested and optimized for performance and memory consumption.
Summary
This document has covered Extensions, what they are, the type of Extension Points and the known limitations imposed on an Extension by iOS. It discussed creating, distributing, installing and running Extensions and the Extension lifecycle. It provided a walkthrough of creating a simple Today widget showing two ways to create the widget's UI using either Storyboards or code. It showed how to test an extension in the iOS Simulator. Finally, it briefly discussed communicating with the Host App and a few precautions and considerations that should be taken when developing an extension.
Related links
If you have any questions, please visit our facebook
64-256GB microSD card support
Frequently Asked Questions
Description
For Z82 / Z86, to run on Windows Or Mac. For Mac, please drag the widget to the Applications folder and then run it through Launchpad. For OS 10.8 or above, please disable the gatekeeper before installing.
Format card
To format the microSD card to FAT32, please see this: 64-256GB card support or follow the instructions:
1. Insert the card into Z82
2. Connect Z82 to a power bank or micro USB charger (not included in package) until orange light is on
3. Use a pin to press and hold the upgrade button (at the back of the camera, next to the micro USB socket) until the red light is flashing
4. Release the upgrade button
5. Press and hold the upgrade button again until the green light is flashing
6. Disconnect the USB charger or power bank, the format is completed
Release Notes
Version: 3.01.4
Date: 15 MAR 2021
Changes:
- Z82 / Z86: split file time changed to 8 minutes due to hardware limitation
Description
For Z18, to run on Android 4.4 or above. Or please install from Android play store (search 'DVR Widget') or iOS app store (search 'DVR Widget').
Release Notes
Version: 5.13
Date: 7 NOV 2018
Changes:
- Add time and setting function, work with firmware 3.3.6 or above (To upgrade firmware, use a pin to press and hold the 'U' key at the back, connect Z18 to the computer and run this on Windows. After upgrade, please turn on Z18 for once)
- Add support to reset the Bluetooth password:
1. press and hold the power button (the LED will be solid green)
2. then use a pin to press the 'U' button at the back
3. keep pressing the 'U' button, then release the power button
4. orange LED will be on if it is successful; red LED will be on if it fails, please try again
5. release 'U' button, the DVR will continue to run no matter the password reset is successful or not
Zetta Widget on Windows (for Z12 / Z15 / Z16 / Z18 / ZIR32)
Description
A windows configuration tool that changes custom settings and synchronizes time of DVR. Uninstall the previous version before installation. Put a microSD card to the DVR and then plug in the DVR to the PC. Put the slide switch close to the power button before powering up, in order to use the PC settings. For details, please see How to change time and settings? Some anti-virus programs treat the widget as malware, so please disable the anti-virus program before downloading and installing the widget and re-enable it again. You can use Avira to scan the widget. It is SAFE.
For Win 10 user: the display on some devices may not work, please change the display resolution to 1280 x 800, SIGN OUT and SIGN IN again. Then run the widget. After changing the setting, change the resolution to the original one. More details: https://www.microsoft.com/surface/en-us/support/apps-and-windows-store/app-display-issues?os=windows-10&=undefined
Release Notes
Version: 1.17.0
Date: 12 SEP 2018
For 64-256GB card or for the best performance, please format the microSD card using the Widget. Quit all other programs including the browser and file manager, disable the anti-virus and firewall for a while. Disable the sleep mode. Tick 'Format' and it will finish right the way. If still cannot record, please do the format again. Do not touch anything at this moment and make sure the power supply and cable connection is stable.
Changes:
- Add Spanish / Japanese / Malaysian language
- When testing the schedule recording feature, do not change the time earlier back using custom time mode, just can only be later. Otherwise, the year of recording files will become 2026. Suggest to delete all the files in the 'ZETTA' directory before every testing.
3MB
Zetta Widget on Mac OS X (for Z12 / Z15 / Z16 / Z18 / ZIR32)
Description
A Mac configuration tool that changes custom settings and synchronizes time of DVR. Uninstall the previous version before installation. Drag the widget to the Applications folder and then run it through Launchpad. For OS 10.8 or above, please disable the gatekeeper before installing. For Zetta Z12, Z15, Z16 and ZIR32only. Put the slide switch close to the power button before powering up, in order to use the Mac settings. For 64 /128GB card, please format as 'MS-DOS FAT', by: 1. Use spotlight to search for 'disk utility' 2. Choose the drive with microSD card 3. Choose Erase 4. Choose 'MS-DOS FAT' in the Format 5. Press 'Erase' at the lower right corner 6. Then press 'Erase' in the new pop up windows 7. Wait for a while, it is done. If it is still not ok, please use the formatter from SD Association to format the card first.
Release Notes
Version: 2.14.0
Date: 13 SEP 2018
Microsoft To Do Iphone Widget
Changes:
- Add Spanish / Japanese / Malaysian language
- When testing the schedule recording feature, do not change the time earlier back using custom time mode, just can only be later. Otherwise, the year of recording files will become 2026. Suggest to delete all the files in the 'ZETTA' directory before every testing.
28MB
Description
Please install the Virtual XP (follow step 1 to 3 to get the VHD image) and install the windows widget on the Virtual XP to use the widget.
Description
A Windows software to auto copy files from microSD card to local computer and use sftp to transfer to remote server.
Release Notes
Version: v0.2.0
Date: 15 MAY 2018
Changes:
- First release
1. Unzip the zip file and see 1_instruction.txt for the usage
2. Please get free sftp server from freesshd or contact This email address is being protected from spambots. You need JavaScript enabled to view it. if you would like us to store the file for you
Zetta Encryption Tool (for Z12 / Z15 / Z16 / ZIR32 only)
Description
A tool to encrypt the video
Release Notes
Version: 1.0.1
Date: 26 NOV 2016
Changes:
- First release
1. Run the encryption tool on Windows or Mac, only works on Z12 / Z15 / Z16 / ZIR32 with config.dat in DVRINFOS drive
2. Put the slide switch to the right, in the custom position