Background Export
This document guides you through the process of enabling the VideoEditor SDK background exporting.
Implement background export capability
If you want to export in the background the onActivityResult()
method will not longer work.
Instead you have to use a BroadcastReceiver
to receive your exported data.
Create a BroadcastReceiver
In order to enable the editor to pass the resulting file to you in an asynchronous way, you have to create a BroadcastReceiver
class like in this example.
public class EditorResultReceiverJava extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
EditorSDKResult data = new EditorSDKResult(intent);
switch (data.getResultStatus()) {
case CANCELED: {
Toast.makeText(context, "Editor is closed because the User clicks the cancel button.", Toast.LENGTH_LONG).show();
}
break;
case CANCELED_BY_SYSTEM: {
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* The editor is canceled by the System, because of unknown reason. *
* The User has maybe force closed the App *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
break;
case DONE_WITHOUT_EXPORT: {
Toast.makeText(context, "Editor result accepted but not changed.", Toast.LENGTH_LONG).show();
}
break;
case EXPORT_STARTED: {
// The editor has started the export, we can now save the serialization in the meantime.
File file = new File(Environment.getExternalStorageDirectory(), "SavedEditorState.json");
if (file.delete()) try {
new IMGLYFileWriter(data.getSettingsList()).writeJson(file);
} catch (IOException e) {
e.printStackTrace();
}
}
break;
case EXPORT_DONE: {
data.notifyGallery(EditorSDKResult.UPDATE_RESULT & EditorSDKResult.UPDATE_SOURCE);
Toast.makeText(PESDK.getAppContext(), "Editor Export is done. File is saved at: " + data.getResultUri() + ".", Toast.LENGTH_LONG).show();
}
break;
}
}
}
class EditorResultReceiverKotlin : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val data = EditorSDKResult(intent)
when (data.resultStatus) {
EditorSDKResult.Status.CANCELED -> {
Toast.makeText(context, "Editor is closed because the User clicks the cancel button.", Toast.LENGTH_LONG).show()
}
EditorSDKResult.Status.CANCELED_BY_SYSTEM -> {
/********************************************************************
* The editor is canceled by the System, because of unknown reason. *
* The User has maybe force closed the App *
*******************************************************************/
}
EditorSDKResult.Status.DONE_WITHOUT_EXPORT -> {
Toast.makeText(context, "Editor result accepted but not changed.", Toast.LENGTH_LONG).show()
}
EditorSDKResult.Status.EXPORT_STARTED -> {
// The editor has started the export, we can now save the serialization in the meantime.
File(Environment.getExternalStorageDirectory(), "SavedEditorState.json").also {
it.delete()
}.outputStream().use {
IMGLYFileWriter(data.settingsList).writeJson(it)
}
}
EditorSDKResult.Status.EXPORT_DONE -> {
// The editor export is done, we can now save the image and notify the gallery to update the image.
data.notifyGallery(to = EditorSDKResult.UPDATE_RESULT and EditorSDKResult.UPDATE_SOURCE)
Toast.makeText(PESDK.getAppContext(), "Editor Export is done. File is saved at: ${data.resultUri}.", Toast.LENGTH_LONG).show()
}
}
}
}
Update your AndroidManifest.xml
Open your Application Manifest and add the BroadcastReceiver
and a permission.
__________
ATTENTION!!! You have to name my.own.package.RECEIVE_RESULT_PERMISSION
with you own permission name, for example use “your.package.RECEIVE_RESULT_PERMISSION” instead of “my.own.package.RECEIVE_RESULT_PERMISSION”.
If another App with the same permission name is installed, the installation of your App will be blocked. __________
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="my.own.package" >
<!-- It is important to have your own permission name in the next two lines here-->
<uses-permission android:name="my.own.package.RECEIVE_RESULT_PERMISSION" />
<permission android:protectionLevel="signature" android:name="my.own.package.RECEIVE_RESULT_PERMISSION" />
<application your_paramters="...">
<!-- Insert your permission name into android:permission="..." -->
<receiver
android:name=".EditorResultReceiverKotlin"
android:permission="my.own.package.RECEIVE_RESULT_PERMISSION">
<intent-filter>
<!-- It is important to have your own action name here -->
<action android:name="my.fancy.BroadcastReceiverAction" />
</intent-filter>
</receiver>
</application>
</manifest>
Update your build.gradle
and include the headless module.
This will add the RenderService and some app permission we need for the background export.
imglyConfig {
modules {
include 'backend:headless'
}
}
Start the editor with startActivityForBroadcast
instead of startActivityForResult
Now instead of starting with startActivityForResult
we use startActivityForBroadcast
and pass the BroadcastReceiver
action name as the second parameter.
public class VideoEditorDemoActivityAsync extends Activity implements PermissionRequest.Response {
public static final int GALLERY_RESULT = 2;
public static final String VESDK_RESULT_BROADCAST_RECEIVER = "my.fancy.BroadcastReceiverAction";
// Important permission request for Android 6.0 and above, don't forget to add this!
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
PermissionRequest.onRequestPermissionsResult(requestCode, permissions, grantResults);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void permissionGranted() {}
@Override
public void permissionDenied() {
/* TODO: The Permission was rejected by the user. The Editor was not opened,
* Show a hint to the user and try again. */
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private VideoEditorSettingsList createVesdkSettingsList() {
// Create an empty new SettingsList and apply the changes on this reference.
VideoEditorSettingsList settingsList = new VideoEditorSettingsList();
// If you include our asset Packs and you use our UI you also need to add them to the UI,
// otherwise they are only available for the backend
// See the specific feature sections of our guides if you want to know how to add your own Assets.
settingsList.getSettingsModel(UiConfigFilter.class).setFilterList(
FilterPackBasic.getFilterPack()
);
settingsList.getSettingsModel(UiConfigText.class).setFontList(
FontPackBasic.getFontPack()
);
settingsList.getSettingsModel(UiConfigFrame.class).setFrameList(
FramePackBasic.getFramePack()
);
settingsList.getSettingsModel(UiConfigOverlay.class).setOverlayList(
OverlayPackBasic.getOverlayPack()
);
settingsList.getSettingsModel(UiConfigSticker.class).setStickerLists(
StickerPackEmoticons.getStickerCategory(),
StickerPackShapes.getStickerCategory()
);
return settingsList;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
openSystemGalleryToSelectAnVideo();
}
private void openSystemGalleryToSelectAnVideo() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setDataAndType(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,"video/*");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, GALLERY_RESULT);
} else {
Toast.makeText(
this,
"No Gallery app installed",
Toast.LENGTH_LONG
).show();
}
}
private void openEditor(Uri inputSource) {
VideoEditorSettingsList settingsList;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
settingsList = createVesdkSettingsList();
} else {
Toast.makeText(this, "Video support needs Android 4.3", Toast.LENGTH_LONG).show();
return;
}
// Set input video
settingsList.getSettingsModel(LoadSettings.class).setSource(inputSource);
// Set output video
settingsList.getSettingsModel(SaveSettings.class).setOutputToGallery(Environment.DIRECTORY_DCIM);
new VideoEditorBuilder(this)
.setSettingsList(settingsList)
.startActivityForBroadcast(this, VESDK_RESULT_BROADCAST_RECEIVER);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == GALLERY_RESULT) {
// Open Editor with some uri in this case with an image selected from the system gallery.
Uri selectedImage = data.getData();
openEditor(selectedImage);
}
}
}
class KVideoEditorDemoActivityAsync : Activity(), PermissionRequest.Response {
companion object {
const val VESDK_RESULT_BROADCAST_RECEIVER = "my.fancy.BroadcastReceiverAction"
const val GALLERY_RESULT = 2
}
// Important permission request for Android 6.0 and above, don't forget to add this!
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
PermissionRequest.onRequestPermissionsResult(requestCode, permissions, grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun permissionGranted() {}
override fun permissionDenied() {
/* TODO: The Permission was rejected by the user. The Editor was not opened,
* Show a hint to the user and try again. */
}
// Create an empty new SettingsList and apply the changes on this reference.
// If you include our asset Packs and use our UI you also need to add them to the UI,
// otherwise they are only available for the backend (like Serialization)
// See the specific feature sections of our guides if you want to know how to add your own Assets.
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private fun createVesdkSettingsList() =
VideoEditorSettingsList()
.configure<UiConfigFilter> {
it.setFilterList(FilterPackBasic.getFilterPack())
}
.configure<UiConfigText> {
it.setFontList(FontPackBasic.getFontPack())
}
.configure<UiConfigFrame> {
it.setFrameList(FramePackBasic.getFramePack())
}
.configure<UiConfigOverlay> {
it.setOverlayList(OverlayPackBasic.getOverlayPack())
}
.configure<UiConfigSticker> {
it.setStickerLists(
StickerPackEmoticons.getStickerCategory(),
StickerPackShapes.getStickerCategory()
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
openSystemGalleryToSelectAnVideo()
}
fun openSystemGalleryToSelectAnVideo() {
val intent = Intent(Intent.ACTION_PICK)
intent.setDataAndType(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,"video/*")
if (intent.resolveActivity(packageManager) != null) {
startActivityForResult(intent, GALLERY_RESULT)
} else {
Toast.makeText(
this,
"No Gallery app installed",
Toast.LENGTH_LONG
).show()
}
}
fun openEditor(inputSource: Uri?) {
val settingsList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
createVesdkSettingsList()
} else {
Toast.makeText(this, "Video support needs Android 4.3", Toast.LENGTH_LONG).show()
return
}
settingsList.configure<LoadSettings> {
it.source = inputSource
}
settingsList[LoadSettings::class].source = inputSource
VideoEditorBuilder(this)
.setSettingsList(settingsList)
.startActivityForBroadcast(this, VESDK_RESULT_BROADCAST_RECEIVER)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == GALLERY_RESULT) {
// Open Editor with some uri in this case with an video selected from the system gallery.
openEditor(data?.data)
}
}
}