Skip to content

Commit 42412fe

Browse files
Merge branch 'main' into feature_uvc_plugin_update
# Conflicts: # dConnectSDK/dConnectLibStreaming/libmedia/src/main/java/org/deviceconnect/android/libmedia/streaming/muxer/Mpeg4Muxer.java
2 parents 2749cdc + 4caaf33 commit 42412fe

10 files changed

Lines changed: 243 additions & 16 deletions

File tree

dConnectDevicePlugin/dConnectDeviceHost/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ dependencies {
103103
implementation 'com.github.pedroSG94.rtmp-rtsp-stream-client-java:rtplibrary:1.9.7'
104104
implementation 'org.deviceconnect:dconnect-device-plugin-sdk:2.8.6'
105105
implementation 'org.deviceconnect:dconnect-demo-lib:1.0.1'
106-
implementation 'org.deviceconnect:libmedia:1.2.1'
107-
implementation 'org.deviceconnect:libsrt:1.2.1'
106+
implementation 'org.deviceconnect:libmedia:1.2.2'
107+
implementation 'org.deviceconnect:libsrt:1.2.2'
108108
// implementation project(':libmedia')
109109
// implementation project(':libsrt')
110110
}

dConnectManager/dConnectManager/dconnect-manager-app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,13 @@
127127
android:label="@string/app_name"
128128
android:theme="@style/AppTheme.AppCompat.Translucent">
129129
</activity>
130-
130+
<!-- セキュリティ設定ダイアログ用Activity. -->
131+
<activity
132+
android:name="org.deviceconnect.android.manager.setting.SecuritySettingDialogActivity"
133+
android:exported="false"
134+
android:label="@string/app_name"
135+
android:theme="@style/AppTheme.AppCompat.Translucent">
136+
</activity>
131137
<!-- キーワード表示用Activity. -->
132138
<activity
133139
android:name="org.deviceconnect.android.manager.setting.KeywordDialogActivity"

dConnectManager/dConnectManager/dconnect-manager-app/src/main/java/org/deviceconnect/android/manager/DConnectService.java

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,34 @@
77
package org.deviceconnect.android.manager;
88

99
import android.app.Activity;
10+
import android.app.AlertDialog;
11+
import android.app.Dialog;
12+
import android.app.SearchManager;
1013
import android.app.Service;
1114
import android.content.BroadcastReceiver;
15+
import android.content.ContentResolver;
16+
import android.content.ContentValues;
1217
import android.content.Intent;
18+
import android.net.Uri;
1319
import android.os.Binder;
20+
import android.os.Build;
21+
import android.os.Bundle;
1422
import android.os.IBinder;
1523
import android.os.PowerManager;
24+
import android.provider.MediaStore;
25+
import android.provider.Settings;
1626
import android.security.KeyChain;
27+
28+
import androidx.annotation.NonNull;
1729
import androidx.annotation.Nullable;
30+
import androidx.fragment.app.DialogFragment;
31+
1832
import android.util.Log;
33+
import android.widget.Toast;
1934

2035
import org.deviceconnect.android.deviceplugin.host.HostDevicePlugin;
36+
import org.deviceconnect.android.deviceplugin.host.activity.profile.CanvasProfileActivity;
37+
import org.deviceconnect.android.deviceplugin.host.file.HostFileProvider;
2138
import org.deviceconnect.android.localoauth.DevicePluginXmlUtil;
2239
import org.deviceconnect.android.manager.core.DConnectManager;
2340
import org.deviceconnect.android.manager.core.DConnectSettings;
@@ -31,19 +48,28 @@
3148
import org.deviceconnect.android.manager.core.util.VersionName;
3249
import org.deviceconnect.android.manager.profile.DConnectSettingProfile;
3350
import org.deviceconnect.android.manager.setting.KeywordDialogActivity;
51+
import org.deviceconnect.android.manager.setting.SecuritySettingDialogActivity;
52+
import org.deviceconnect.android.manager.setting.SecuritySettingDialogFragment;
3453
import org.deviceconnect.android.manager.setting.SettingActivity;
3554
import org.deviceconnect.android.manager.util.NotificationUtil;
3655
import org.deviceconnect.android.profile.SystemProfile;
56+
import org.deviceconnect.android.provider.FileManager;
3757
import org.deviceconnect.android.ssl.KeyStoreCallback;
3858
import org.deviceconnect.android.ssl.KeyStoreError;
3959
import org.deviceconnect.message.intent.message.IntentDConnectMessage;
4060

4161
import java.io.File;
62+
import java.io.FileInputStream;
63+
import java.io.FileNotFoundException;
4264
import java.io.IOException;
65+
import java.io.InputStream;
66+
import java.io.OutputStream;
4367
import java.io.UnsupportedEncodingException;
4468
import java.security.KeyStore;
4569
import java.security.NoSuchAlgorithmException;
4670
import java.security.cert.Certificate;
71+
import java.security.cert.CertificateEncodingException;
72+
import java.util.Enumeration;
4773
import java.util.concurrent.ExecutorService;
4874
import java.util.concurrent.Executors;
4975
import java.util.logging.Level;
@@ -278,6 +304,7 @@ public void onError(final Exception e) {
278304
}
279305
}
280306
}
307+
281308
/**
282309
* Hostプラグインを追加します.
283310
*/
@@ -427,7 +454,7 @@ public void openPluginSettings(final String pluginId) {
427454
* プラグインの有効・無効を設定します.
428455
*
429456
* @param pluginId プラグインID
430-
* @param enable 有効の場合はtrue、無効の場合はfalse
457+
* @param enable 有効の場合はtrue、無効の場合はfalse
431458
*/
432459
public void setEnablePlugin(final String pluginId, final boolean enable) {
433460
final DevicePlugin plugin = mManager.getPluginManager().getDevicePlugin(pluginId);
@@ -479,12 +506,21 @@ public void installRootCertificate() {
479506
mManager.requestKeyStore(ipAddress, new KeyStoreCallback() {
480507
@Override
481508
public void onSuccess(final KeyStore keyStore, final Certificate cert, final Certificate rootCert) {
509+
482510
try {
483-
Intent installIntent = KeyChain.createInstallIntent();
484-
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
485-
installIntent.putExtra(KeyChain.EXTRA_NAME, "Device Connect Root CA");
486-
installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, rootCert.getEncoded());
487-
startActivity(installIntent);
511+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
512+
Intent installIntent = new Intent();
513+
installIntent.setClass(getApplicationContext(), SecuritySettingDialogActivity.class);
514+
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
515+
installIntent.putExtra(SecuritySettingDialogFragment.EXTRA_ROOT_CERT, rootCert.getEncoded());
516+
startActivity(installIntent);
517+
} else {
518+
Intent installIntent = KeyChain.createInstallIntent();
519+
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
520+
installIntent.putExtra(KeyChain.EXTRA_NAME, "Device Connect Root CA");
521+
installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, rootCert.getEncoded());
522+
startActivity(installIntent);
523+
}
488524
} catch (Exception e) {
489525
mLogger.log(Level.SEVERE, "Failed to encode server certificate.", e);
490526
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
SecuritySettingDialogActivity.java
3+
Copyright (c) 2021 NTT DOCOMO,INC.
4+
Released under the MIT license
5+
http://opensource.org/licenses/mit-license.php
6+
*/
7+
package org.deviceconnect.android.manager.setting;
8+
9+
import android.content.Intent;
10+
import android.os.Bundle;
11+
12+
import androidx.fragment.app.FragmentActivity;
13+
14+
/**
15+
* セキュリティの設定画面を出すダイアログ表示用Activity.
16+
* @author NTT DOCOMO, INC.
17+
*/
18+
public class SecuritySettingDialogActivity extends FragmentActivity {
19+
@Override
20+
protected void onCreate(final Bundle savedInstanceState) {
21+
super.onCreate(savedInstanceState);
22+
23+
Intent intent = getIntent();
24+
if (intent == null) {
25+
finish();
26+
return;
27+
}
28+
29+
byte[] rootCert = intent.getByteArrayExtra(SecuritySettingDialogFragment.EXTRA_ROOT_CERT);
30+
if (rootCert == null) {
31+
finish();
32+
return;
33+
}
34+
35+
SecuritySettingDialogFragment fragment = new SecuritySettingDialogFragment();
36+
Bundle args = new Bundle();
37+
args.putByteArray(SecuritySettingDialogFragment.EXTRA_ROOT_CERT, rootCert);
38+
fragment.setArguments(args);
39+
fragment.show(getSupportFragmentManager(), "security_setting_dialog");
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
SecuritySettingDialogFragment.java
3+
Copyright (c) 2021 NTT DOCOMO,INC.
4+
Released under the MIT license
5+
http://opensource.org/licenses/mit-license.php
6+
*/
7+
package org.deviceconnect.android.manager.setting;
8+
9+
import android.app.Activity;
10+
import android.app.Dialog;
11+
import android.app.SearchManager;
12+
import android.content.ContentResolver;
13+
import android.content.ContentValues;
14+
import android.content.DialogInterface;
15+
import android.content.Intent;
16+
import android.net.Uri;
17+
import android.os.Bundle;
18+
import android.provider.MediaStore;
19+
import android.provider.Settings;
20+
import android.util.Log;
21+
import android.widget.Toast;
22+
23+
import androidx.annotation.NonNull;
24+
import androidx.appcompat.app.AlertDialog;
25+
import androidx.fragment.app.DialogFragment;
26+
27+
import org.deviceconnect.android.deviceplugin.host.file.HostFileProvider;
28+
import org.deviceconnect.android.manager.R;
29+
import org.deviceconnect.android.provider.FileManager;
30+
31+
import java.io.File;
32+
import java.io.FileInputStream;
33+
import java.io.FileNotFoundException;
34+
import java.io.IOException;
35+
import java.io.InputStream;
36+
import java.io.OutputStream;
37+
38+
/**
39+
* セキュリティ設定画面を開くダイアログ.
40+
*
41+
* @author NTT DOCOMO, INC.
42+
*/
43+
public class SecuritySettingDialogFragment extends DialogFragment {
44+
private static final String TAG = "SecuritySettingDialogFragment";
45+
public static final String EXTRA_ROOT_CERT = "root_cert";
46+
47+
@Override
48+
public Dialog onCreateDialog(final Bundle savedInstanceState) {
49+
Bundle args = getArguments();
50+
if (args == null) {
51+
dismiss();
52+
}
53+
byte[] rootCert = getArguments().getByteArray(EXTRA_ROOT_CERT);
54+
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
55+
builder.setTitle(getString(R.string.dialog_title_security_setting));
56+
builder.setMessage(getString(R.string.dialog_message_security_setting));
57+
builder.setPositiveButton(R.string.dialog_open_security_setting, (dialog, which) -> {
58+
final FileManager fileMgr = new FileManager(getContext(), HostFileProvider.class.getName());
59+
fileMgr.saveFile("manager.pem", rootCert, true, new FileManager.SaveFileCallback() {
60+
@Override
61+
public void onSuccess(@NonNull String s) {
62+
shareCA(new File(fileMgr.getBasePath(), "manager.pem"));
63+
Intent installIntent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
64+
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
65+
startActivity(installIntent);
66+
}
67+
68+
@Override
69+
public void onFail(@NonNull Throwable throwable) {
70+
Toast.makeText(getContext(), R.string.dialog_error_message_not_export_ca, Toast.LENGTH_LONG).show();
71+
}
72+
});
73+
});
74+
builder.setNegativeButton(R.string.activity_launch_button_cancel, (dialog, which) -> {
75+
Activity activity = getActivity();
76+
if (activity != null) {
77+
activity.finish();
78+
}
79+
});
80+
return builder.create();
81+
}
82+
83+
@Override
84+
public void onStop() {
85+
super.onStop();
86+
87+
Activity activity = getActivity();
88+
if (activity != null) {
89+
activity.finish();
90+
}
91+
}
92+
93+
private void shareCA(final File fileName) {
94+
ContentResolver resolver = getContext().getContentResolver();
95+
ContentValues values = new ContentValues();
96+
values.put(MediaStore.Downloads.TITLE, fileName.getName());
97+
values.put(MediaStore.Downloads.DISPLAY_NAME, fileName.getName());
98+
values.put(MediaStore.Downloads.DATE_TAKEN, System.currentTimeMillis());
99+
values.put(MediaStore.Downloads.MIME_TYPE, "application/x-pem-file");
100+
values.put(MediaStore.Downloads.IS_PENDING, 1);
101+
Uri uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
102+
if (uri == null) {
103+
Log.e(TAG, "Failed to share ca: not inserted to ca store: path = " + fileName);
104+
return;
105+
}
106+
107+
try (InputStream in = new FileInputStream(fileName);
108+
OutputStream out = resolver.openOutputStream(uri)) {
109+
if (out == null) {
110+
Log.e(TAG, "Failed to share photo: no output stream: path = " + fileName);
111+
return;
112+
}
113+
byte[] buf = new byte[1024];
114+
int len;
115+
while ((len = in.read(buf)) > 0) {
116+
out.write(buf, 0, len);
117+
}
118+
out.flush();
119+
} catch (FileNotFoundException e) {
120+
throw new IllegalStateException(e);
121+
} catch (IOException e) {
122+
Log.e(TAG, "Failed to share photo: I/O error: path = " + fileName, e);
123+
return;
124+
}
125+
126+
values.clear();
127+
values.put(MediaStore.Downloads.IS_PENDING, 0);
128+
resolver.update(uri, values, null, null);
129+
}
130+
}

dConnectManager/dConnectManager/dconnect-manager-app/src/main/res/values-ja/strings.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,10 @@
277277
<string name="fragment_accesslog_delete_accesslog_positive">はい</string>
278278
<string name="fragment_accesslog_delete_accesslog_negative">いいえ</string>
279279
<string name="fragment_accesslog_empty">アクセスログがありません</string>
280+
281+
<!-- ================= Open Security Setting ================= -->
282+
<string name="dialog_open_security_setting">セキュリティの設定を開く</string>
283+
<string name="dialog_title_security_setting">証明書の手動インストール</string>
284+
<string name="dialog_message_security_setting">Android11(R)以降、アプリケーションは認証局(CA)を自動的にインストールできなくなりました。\n\n設定で「セキュリティ>暗号化と視覚情報>証明書」のインストールの順に移動します。そこから「CA証明書」を選択肢新しくエクスポートした証明書ファイルを選択します。\n\n証明書は、外部ストレージのダウンロードフォルダにエクスポートしました。</string>
285+
<string name="dialog_error_message_not_export_ca">CA証明書の出力に失敗しました</string>
280286
</resources>

dConnectManager/dConnectManager/dconnect-manager-app/src/main/res/values/strings.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,11 @@
277277
<string name="fragment_accesslog_delete_accesslog_positive">Yes</string>
278278
<string name="fragment_accesslog_delete_accesslog_negative">No</string>
279279
<string name="fragment_accesslog_empty">No Access Log</string>
280+
281+
<!-- ================= Open Security Setting ================= -->
282+
<string name="dialog_open_security_setting">Open the security settings</string>
283+
<string name="dialog_title_security_setting">Manual installation of certificates</string>
284+
<string name="dialog_message_security_setting">Starting with Android 11(R), applications can no longer automatically install a Certificate Authority (CA). \n\nIn the settings, go to \"Security>Encryption and Visual Information>Install Certificates\". From there, select \"CA Certificates\" and select the newly exported certificate file.\n\nWe exported the certificate to the Downloads folder on our external storage.</string>
285+
<string name="dialog_error_message_not_export_ca">Failed to output CA certificate.</string>
286+
280287
</resources>

dConnectSDK/dConnectLibStreaming/libmedia/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if (githubPropertiesFile.exists()) {
88
}
99

1010
def getVersionName = { ->
11-
return "1.2.1"
11+
return "1.2.2"
1212
}
1313

1414
def getArtificatId = { ->

dConnectSDK/dConnectLibStreaming/libmedia/src/main/java/org/deviceconnect/android/libmedia/streaming/muxer/Mpeg4Muxer.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public void onAudioFormatChanged(MediaFormat newFormat) {
7979

8080
@Override
8181
public void onWriteAudioData(ByteBuffer encodedData, MediaCodec.BufferInfo bufferInfo) {
82-
writeData(mAudioTrackIndex, encodedData, bufferInfo);
82+
writeData(mAudioTrackIndex, encodedData, bufferInfo);
8383
}
8484

8585
@Override
@@ -105,14 +105,15 @@ public void onReleased() {
105105
}
106106

107107
private synchronized void writeData(int trackIndex, ByteBuffer encodedData, MediaCodec.BufferInfo bufferInfo) {
108+
if (!mMuxerStarted) {
109+
return;
110+
}
111+
108112
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
109113
bufferInfo.size = 0;
110114
}
111115

112116
if (bufferInfo.size != 0) {
113-
if (!mMuxerStarted || mAudioTrackIndex == -1) {
114-
return;
115-
}
116117
bufferInfo.presentationTimeUs = getPresentationTime(bufferInfo);
117118
encodedData.position(bufferInfo.offset);
118119
encodedData.limit(bufferInfo.offset + bufferInfo.size);

dConnectSDK/dConnectLibStreaming/libsrt/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ if (githubPropertiesFile.exists()) {
66
githubProperties.load(new FileInputStream(githubPropertiesFile))
77
}
88
def getVersionName = { ->
9-
return "1.2.1" // Replace with version Name
9+
return "1.2.2" // Replace with version Name
1010
}
1111

1212
def getArtificatId = { ->
@@ -93,7 +93,7 @@ android {
9393

9494
dependencies {
9595
implementation fileTree(dir: 'libs', include: ['*.jar'])
96-
implementation 'org.deviceconnect:libmedia:1.2.1'
96+
implementation 'org.deviceconnect:libmedia:1.2.2'
9797
// implementation project(':libmedia')
9898

9999
testImplementation 'junit:junit:4.13.2'

0 commit comments

Comments
 (0)