Skip to content

Commit fa3441b

Browse files
Merge pull request #480 from TakayukiHoshi1984/modify_scoped_storage
Scoped Storage 対応
2 parents bf259b8 + e95f6fb commit fa3441b

56 files changed

Lines changed: 1343 additions & 348 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dConnectDevicePlugin/dConnectDeviceChromeCast/app/src/main/java/fi/iki/elonen/NanoHTTPD.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,10 @@ public static class Response {
558558
* Use chunkedTransfer
559559
*/
560560
private boolean chunkedTransfer;
561+
/**
562+
* Content length.
563+
*/
564+
private int contentLength = -1;
561565

562566
/**
563567
* Default constructor: response = HTTP_OK, mime = MIME_HTML and your supplied message
@@ -599,6 +603,17 @@ public String getHeader(String name) {
599603
return header.get(name);
600604
}
601605

606+
public void setContentLength(final int length) {
607+
this.contentLength = length;
608+
}
609+
610+
private int getContentLength() throws IOException {
611+
if (contentLength < 0) {
612+
return this.data.available();
613+
}
614+
return contentLength;
615+
}
616+
602617
/**
603618
* Sends given response to the socket.
604619
*/
@@ -634,7 +649,7 @@ protected void send(OutputStream outputStream) {
634649
if (requestMethod != Method.HEAD && chunkedTransfer) {
635650
sendAsChunked(outputStream, pw);
636651
} else {
637-
int pending = data != null ? data.available() : 0;
652+
int pending = data != null ? getContentLength() : 0;
638653
sendContentLengthHeaderIfNotAlreadyPresent(pw, header, pending);
639654
pw.print("\r\n");
640655
pw.flush();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
AppLocalMediaFile.java
3+
Copyright (c) 2019 NTT DOCOMO,INC.
4+
Released under the MIT license
5+
http://opensource.org/licenses/mit-license.php
6+
*/
7+
package org.deviceconnect.android.deviceplugin.chromecast.core;
8+
9+
import android.content.Context;
10+
11+
import java.io.File;
12+
import java.io.FileInputStream;
13+
import java.io.IOException;
14+
import java.io.InputStream;
15+
16+
public class AppLocalMediaFile implements MediaFile {
17+
18+
final File mFile;
19+
20+
public AppLocalMediaFile(final File file) {
21+
mFile = file;
22+
}
23+
24+
@Override
25+
public String getName() {
26+
return mFile.getName();
27+
}
28+
29+
@Override
30+
public InputStream open(final Context context) throws IOException {
31+
return new FileInputStream(mFile);
32+
}
33+
}

dConnectDevicePlugin/dConnectDeviceChromeCast/app/src/main/java/org/deviceconnect/android/deviceplugin/chromecast/core/ChromeCastHttpServer.java

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public String exposeFile(final MediaFile file) {
9393
if (address == null) {
9494
return null;
9595
}
96-
return "http://" + address + ":" + getListeningPort() + file.getPath();
96+
return "http://" + address + ":" + getListeningPort() + "/" + file.getName();
9797
}
9898

9999
/**
@@ -133,9 +133,9 @@ private Response respond(final Map<String, String> headers, final IHTTPSession s
133133
mLogger.info("File not found: URI=" + uri);
134134
return createResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "");
135135
}
136-
mLogger.info("Found File: " + mediaFile.mFile.getAbsolutePath());
136+
mLogger.info("Found File: " + mediaFile.getName());
137137

138-
Response response = serveFile(uri, headers, mediaFile.mFile, "");
138+
Response response = serveFile(headers, mediaFile, "");
139139
if (response == null) {
140140
return createResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "");
141141
}
@@ -151,8 +151,8 @@ private Response respond(final Map<String, String> headers, final IHTTPSession s
151151
private MediaFile findFile(final String uri) {
152152
synchronized (mFileList) {
153153
for (MediaFile file : mFileList) {
154-
mLogger.info(" - " + file.getPath());
155-
if (uri.equals(file.getPath())) {
154+
mLogger.info(" - " + file.getName());
155+
if (uri.equals("/" + file.getName())) {
156156
return file;
157157
}
158158
}
@@ -166,10 +166,15 @@ private MediaFile findFile(final String uri) {
166166
* @param status ステータス
167167
* @param mimeType MIMEタイプ
168168
* @param message メッセージ (InputStream)
169+
* @param length 送信するデータ長
169170
* @return レスポンス
170171
*/
171-
private Response createResponse(final Response.Status status, final String mimeType, final InputStream message) {
172+
private Response createResponse(final Response.Status status,
173+
final String mimeType,
174+
final InputStream message,
175+
final int length) {
172176
Response res = new Response(status, mimeType, message);
177+
res.setContentLength(length);
173178
res.addHeader("Accept-Ranges", "bytes");
174179
return res;
175180
}
@@ -182,7 +187,9 @@ private Response createResponse(final Response.Status status, final String mimeT
182187
* @param message メッセージ (String)
183188
* @return レスポンス
184189
*/
185-
private Response createResponse(final Response.Status status, final String mimeType, final String message) {
190+
private Response createResponse(final Response.Status status,
191+
final String mimeType,
192+
final String message) {
186193
Response res = new Response(status, mimeType, message);
187194
res.addHeader("Accept-Ranges", "bytes");
188195
return res;
@@ -261,19 +268,20 @@ private String getIpAddress() {
261268

262269
/**
263270
* ファイルのレスポンスを作成する.
264-
*
265-
* @param uri ファイルのURI
271+
*
266272
* @param header ヘッダー
267273
* @param file ファイル
268274
* @param mime MIMEタイプ
269275
* @return レスポンス
270276
*/
271-
Response serveFile(final String uri, final Map<String, String> header, final File file, final String mime) {
277+
Response serveFile(final Map<String, String> header, final MediaFile file, final String mime) {
272278

273279
Response res;
274280
try {
275-
String etag = Integer.toHexString((file.getAbsolutePath()
276-
+ file.lastModified() + "" + file.length()).hashCode());
281+
InputStream in = file.open(mContext);
282+
283+
long fileLen = in.available();
284+
String etag = Integer.toHexString((file.getName() + "" + fileLen).hashCode());
277285

278286
long startFrom = 0;
279287
long endAt = -1;
@@ -296,7 +304,6 @@ Response serveFile(final String uri, final Map<String, String> header, final Fil
296304
}
297305
}
298306

299-
long fileLen = file.length();
300307
if (range != null && startFrom >= 0) {
301308
if (startFrom >= fileLen) {
302309
res = createResponse(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, "");
@@ -311,25 +318,17 @@ Response serveFile(final String uri, final Map<String, String> header, final Fil
311318
newLen = 0;
312319
}
313320

314-
final long dataLen = newLen;
315-
FileInputStream fis = new FileInputStream(file) {
316-
@Override
317-
public int available() throws IOException {
318-
return (int) dataLen;
319-
}
320-
};
321-
fis.skip(startFrom);
322-
323-
res = createResponse(Response.Status.PARTIAL_CONTENT, mime, fis);
324-
res.addHeader("Content-Length", "" + dataLen);
321+
in.skip(startFrom);
322+
res = createResponse(Response.Status.PARTIAL_CONTENT, mime, in, (int) newLen);
323+
res.addHeader("Content-Length", "" + newLen);
325324
res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen);
326325
res.addHeader("ETag", etag);
327326
}
328327
} else {
329328
if (etag.equals(header.get("if-none-match"))) {
330329
res = createResponse(Response.Status.NOT_MODIFIED, mime, "");
331330
} else {
332-
res = createResponse(Response.Status.OK, mime, new FileInputStream(file));
331+
res = createResponse(Response.Status.OK, mime, in, in.available());
333332
res.addHeader("Content-Length", "" + fileLen);
334333
res.addHeader("ETag", etag);
335334
}

dConnectDevicePlugin/dConnectDeviceChromeCast/app/src/main/java/org/deviceconnect/android/deviceplugin/chromecast/core/MediaFile.java

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,29 @@
77
package org.deviceconnect.android.deviceplugin.chromecast.core;
88

99

10-
import java.io.File;
10+
import android.content.Context;
11+
12+
import java.io.IOException;
13+
import java.io.InputStream;
1114

1215
/**
1316
* Media file.
1417
* @author NTT DOCOMO, INC.
1518
*/
16-
public class MediaFile {
17-
18-
/** The internal path of a media file. */
19-
final File mFile;
20-
21-
/** MimeType of a media file. */
22-
final String mMimeType;
19+
public interface MediaFile {
2320

2421
/**
25-
* Constructor.
26-
*
27-
* @param file the internal path of a media file
28-
* @param mimeType MimeType of a media file
22+
* Get the name to expose a media file.
23+
* @return the path to expose a media file
2924
*/
30-
public MediaFile(final File file, final String mimeType) {
31-
mFile = file;
32-
mMimeType = mimeType;
33-
}
25+
String getName();
3426

3527
/**
36-
* Get the path to expose a media file.
37-
* @return the path to expose a media file
28+
* メディアの内容を取得するための入力ストリームを開く.
29+
*
30+
* @param context コンテキスト
31+
* @return 入力ストリーム
32+
* @throws IOException 入力ストリームの取得に失敗した場合
3833
*/
39-
String getPath() {
40-
return "/" + mFile.getName();
41-
}
34+
InputStream open(Context context) throws IOException;
4235
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
MediaStoreContent.java
3+
Copyright (c) 2019 NTT DOCOMO,INC.
4+
Released under the MIT license
5+
http://opensource.org/licenses/mit-license.php
6+
*/
7+
package org.deviceconnect.android.deviceplugin.chromecast.core;
8+
9+
import android.content.ContentResolver;
10+
import android.content.Context;
11+
import android.net.Uri;
12+
13+
import java.io.IOException;
14+
import java.io.InputStream;
15+
16+
public class MediaStoreContent implements MediaFile {
17+
18+
private final Uri mMediaUri;
19+
20+
public MediaStoreContent(final Uri mediaUri) {
21+
if (mediaUri.getPathSegments() == null) {
22+
throw new IllegalArgumentException("mediaUri has no mediaId");
23+
}
24+
mMediaUri = mediaUri;
25+
}
26+
27+
@Override
28+
public String getName() {
29+
return mMediaUri.getLastPathSegment();
30+
}
31+
32+
@Override
33+
public InputStream open(final Context context) throws IOException {
34+
ContentResolver resolver = context.getContentResolver();
35+
return resolver.openInputStream(mMediaUri);
36+
}
37+
}

dConnectDevicePlugin/dConnectDeviceChromeCast/app/src/main/java/org/deviceconnect/android/deviceplugin/chromecast/profile/ChromeCastCanvasProfile.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.webkit.URLUtil;
1111

1212
import org.deviceconnect.android.deviceplugin.chromecast.ChromeCastService;
13+
import org.deviceconnect.android.deviceplugin.chromecast.core.AppLocalMediaFile;
1314
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastDiscovery;
1415
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastHttpServer;
1516
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastMessage;
@@ -165,7 +166,7 @@ private String exposeImage(final byte[] data, final String mimeType) throws IOEx
165166
throw new IllegalArgumentException("data is null.");
166167
}
167168
File file = saveFile(generateFileName(), data);
168-
return getHttpServer().exposeFile(new MediaFile(file, mimeType));
169+
return getHttpServer().exposeFile(new AppLocalMediaFile(file));
169170
}
170171

171172
/**

dConnectDevicePlugin/dConnectDeviceChromeCast/app/src/main/java/org/deviceconnect/android/deviceplugin/chromecast/profile/ChromeCastMediaPlayerProfile.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastHttpServer;
2828
import org.deviceconnect.android.deviceplugin.chromecast.core.ChromeCastMediaPlayer;
2929
import org.deviceconnect.android.deviceplugin.chromecast.core.MediaFile;
30+
import org.deviceconnect.android.deviceplugin.chromecast.core.MediaStoreContent;
3031
import org.deviceconnect.android.event.EventError;
3132
import org.deviceconnect.android.event.EventManager;
3233
import org.deviceconnect.android.message.MessageUtils;
@@ -760,17 +761,13 @@ private Cursor getCursorFrom(final Uri uri, final String key, final String value
760761
* @param mediaId メディアID
761762
* @return dummyUrl ダミーURL
762763
*/
763-
private String exposeMedia(final int mediaId) {
764+
private String exposeMedia(final long mediaId) {
764765
Uri targetUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
765-
String path = getPathFromUri(ContentUris.withAppendedId(targetUri,
766-
Long.valueOf(mediaId)));
767-
if (path == null) {
768-
return null;
769-
}
766+
Uri mediaUri = ContentUris.withAppendedId(targetUri, mediaId);
770767

771768
ChromeCastHttpServer server = ((ChromeCastService) getContext())
772769
.getChromeCastHttpServer();
773-
return server.exposeFile(new MediaFile(new File(path), null));
770+
return server.exposeFile(new MediaStoreContent(mediaUri));
774771
}
775772

776773
private final DConnectApi mPutMediaApi = new PutApi() {

dConnectDevicePlugin/dConnectDeviceHost/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ repositories {
7272

7373
dependencies {
7474
implementation fileTree(include: '*.jar', dir: 'libs')
75-
implementation 'org.deviceconnect:dconnect-device-plugin-sdk:2.8.1'
75+
implementation 'org.deviceconnect:dconnect-device-plugin-sdk:2.8.2'
7676
implementation project(':dconnect-demo-lib')
7777
implementation project(':libstreaming')
7878
implementation('com.serenegiant:common:2.12.5') {

dConnectDevicePlugin/dConnectDeviceHost/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@
121121
android:name="org.deviceconnect.android.deviceplugin.host.file.HostFileProvider"
122122
android:authorities="org.deviceconnect.android.deviceplugin.host.provider.included"
123123
android:exported="true" >
124-
124+
<meta-data
125+
android:name="filelocation"
126+
android:resource="@xml/host_filelocation" />
125127
</provider>
126128
</application>
127129

dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/HostDevicePlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ private void registerDemoNotification() {
250250
}
251251
private void updateDemoPageIfNeeded() {
252252
final Context context = getContext();
253-
if (DemoInstaller.isUpdateNeeded(context)) {
253+
if (mDemoInstaller.isUpdateNeeded()) {
254254
mLogger.info("Demo page must be updated.");
255255
updateDemoPage(context);
256256
} else {

0 commit comments

Comments
 (0)