*/
public static String httpPost(String url, String postData, int timeoutMs)
{
- return (httpCommand(url, "POST", postData, null, null, null, timeoutMs));
+ return (httpCommand(url, "POST", postData, null, null, timeoutMs));
+ }
+
+
+ /**
+ *
+ *
+ *
+ */
+ public static String httpGetWithHeader(String url, Map<String, String> headerMap, String contentType, int timeoutMs)
+ {
+ return (httpCommand(url, "GET", null, headerMap, contentType, timeoutMs));
}
/**
*
*
*/
- public static String httpPostWithHeader(String url, String postData, String headerKey, String headerValue, String contentType, int timeoutMs)
+ public static String httpPostWithHeader(String url, String postData, Map<String, String> headerMap, String contentType, int timeoutMs)
{
- return (httpCommand(url, "POST", postData, headerKey, headerValue, contentType, timeoutMs));
+ return (httpCommand(url, "POST", postData, headerMap, contentType, timeoutMs));
}
/**
*/
public static String httpPut(String url, String postData, int timeoutMs)
{
- return (httpCommand(url, "PUT", postData, null, null, null, timeoutMs));
+ return (httpCommand(url, "PUT", postData, null, null, timeoutMs));
}
/**
*
*
*/
- private static String httpCommand(String url, String requestMethod, String postData, String setPropertyKey, String setPropertyValue, String contentType, int timeoutMs)
+ private static String httpCommand(String url, String requestMethod, String postData, Map<String, String> setProperty, String contentType, int timeoutMs)
{
HttpURLConnection httpConn = null;
OutputStream outputStream = null;
final URL urlObj = new URL(url);
httpConn = (HttpURLConnection) urlObj.openConnection();
httpConn.setRequestMethod(requestMethod);
- if ((setPropertyKey != null)&&(setPropertyValue != null))
+ if (setProperty != null)
{
- httpConn.setRequestProperty(setPropertyKey, setPropertyValue);
+ for (String key : setProperty.keySet())
+ {
+ String value = setProperty.get(key);
+ httpConn.setRequestProperty(key, value);
+ }
}
if (contentType != null)
{
}
httpConn.setConnectTimeout(timeout);
httpConn.setReadTimeout(timeout);
- httpConn.setDoInput(true);
- httpConn.setDoOutput(true);
-
- outputStream = httpConn.getOutputStream();
- writer = new OutputStreamWriter(outputStream, "UTF-8");
- writer.write(postData);
- writer.flush();
- writer.close();
- writer = null;
- outputStream.close();
- outputStream = null;
+ if (postData == null)
+ {
+ httpConn.connect();
+ }
+ else
+ {
+ httpConn.setDoInput(true);
+ httpConn.setDoOutput(true);
+ outputStream = httpConn.getOutputStream();
+ writer = new OutputStreamWriter(outputStream, "UTF-8");
+ writer.write(postData);
+ writer.flush();
+ writer.close();
+ writer = null;
+ outputStream.close();
+ outputStream = null;
+ }
int responseCode = httpConn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK)
{
Log.v(TAG, "Already received. : " + ddUsn);
}
}
+ else
+ {
+ Log.v(TAG, " SSDP REPLY MESSAGE (ignored) : " + ssdpReplyMessage);
+ }
currentTime = System.currentTimeMillis();
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Queue;
public class PanasonicPlaybackControl implements IPlaybackControl
"<ObjectID>0</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter>*</Filter><StartingIndex>" + returnedCount + "</StartingIndex><RequestedCount>3500</RequestedCount><SortCriteria></SortCriteria>" +
"<pana:X_FromCP>LumixLink2.0</pana:X_FromCP></u:Browse></s:Body></s:Envelope>";
- String reply = SimpleHttpClient.httpPostWithHeader(url, postData, "SOAPACTION", "urn:schemas-upnp-org:service:ContentDirectory:" + sequenceNumber + "#Browse", "text/xml; charset=\"utf-8\"", timeoutMs);
+ Map<String, String> header = new HashMap<>();
+ header.clear();
+ header.put("SOAPACTION", "urn:schemas-upnp-org:service:ContentDirectory:" + sequenceNumber + "#Browse");
+ String reply = SimpleHttpClient.httpPostWithHeader(url, postData, header, "text/xml; charset=\"utf-8\"", timeoutMs);
if (reply.length() < 10)
{
Log.v(TAG, postData);
package net.osdn.gokigen.pkremote.camera.vendor.sony.wrapper.connection;
import android.content.Context;
+import android.content.SharedPreferences;
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
import net.osdn.gokigen.pkremote.R;
import net.osdn.gokigen.pkremote.camera.interfaces.status.ICameraStatusReceiver;
import net.osdn.gokigen.pkremote.camera.vendor.sony.wrapper.ISonyCamera;
import net.osdn.gokigen.pkremote.camera.vendor.sony.wrapper.SonyCameraDeviceProvider;
+import net.osdn.gokigen.pkremote.preference.IPreferencePropertyAccessor;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
private static final int SSDP_MX = 1;
private static final String SSDP_ADDR = "239.255.255.250";
private static final String SSDP_ST = "urn:schemas-sony-com:service:ScalarWebAPI:1";
+ private static final String SSDP_ST2 = "urn:schemas-upnp-org:service:ContentDirectory:1";
+ // private static final String SSDP_ST2 = "urn:schemas-upnp-org:device:MediaServer:1";
private final Context context;
private final ISearchResultCallback callback;
private final ICameraStatusReceiver cameraStatusReceiver;
private final String ssdpRequest;
private final int sendRepeatCount;
+ private final boolean useSmartphoneTransfer;
SonySsdpClient(@NonNull Context context, @NonNull ISearchResultCallback callback, @NonNull ICameraStatusReceiver statusReceiver, int sendRepeatCount)
{
this.callback = callback;
this.cameraStatusReceiver = statusReceiver;
this.sendRepeatCount = (sendRepeatCount >= 0) ? sendRepeatCount : SEND_TIMES_DEFAULT;
+
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ useSmartphoneTransfer = preferences.getBoolean(IPreferencePropertyAccessor.USE_SMARTPHONE_TRANSFER_MODE, false);
ssdpRequest = "M-SEARCH * HTTP/1.1\r\n"
+ String.format(Locale.US, "HOST: %s:%d\r\n", SSDP_ADDR, SSDP_PORT)
+ "MAN: \"ssdp:discover\"\r\n"
+ String.format(Locale.US, "MX: %d\r\n", SSDP_MX)
- + String.format("ST: %s\r\n", SSDP_ST) + "\r\n";
+ + String.format("ST: %s\r\n", (useSmartphoneTransfer ? SSDP_ST2 : SSDP_ST)) + "\r\n";
}
void search()
}
else
{
+ if ((useSmartphoneTransfer)&&(device != null))
+ {
+ cameraStatusReceiver.onStatusNotify(context.getString(R.string.camera_found) + " " + device.getFriendlyName() + " (Smartphone Transfer)");
+ Log.v(TAG, " SMARTPHONE TRANSFER : " + ssdpReplyMessage);
+ callback.onDeviceFound(device);
+ break;
+ }
+
// カメラが見つからない...
cameraStatusReceiver.onStatusNotify(context.getString(R.string.camera_not_found));
}
Log.v(TAG, "Already received. : " + ddUsn);
}
}
+ else
+ {
+ Log.v(TAG, " SSDP REPLY (ignored) : " + ssdpReplyMessage + " " + useSmartphoneTransfer);
+ }
currentTime = System.currentTimeMillis();
}
}
import org.json.JSONArray;
import org.json.JSONObject;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserFactory;
+import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
public class SonyPlaybackControl implements IPlaybackControl {
private final String TAG = toString();
}
@Override
- public void getCameraContentList(ICameraContentListCallback callback) {
+ public void getCameraContentList(ICameraContentListCallback callback)
+ {
Log.v(TAG, "getCameraContentList()");
- try {
+ try
+ {
if (cameraApi == null) {
Log.v(TAG, "CAMERA API is NULL.");
return;
}
- if (contentListIsCreating) {
+ if (contentListIsCreating)
+ {
// すでにコンテントリストを作り始めているので、処理は継続しない。
Log.v(TAG, "ALREADY CREATING CONTENT LIST.");
return;
}
contentListIsCreating = true;
+
+ // 画像転送に「スマートフォン転送機能」を使う場合...
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+ boolean useSmartphoneTransfer = preferences.getBoolean(IPreferencePropertyAccessor.USE_SMARTPHONE_TRANSFER_MODE, false);
+ if (useSmartphoneTransfer)
+ {
+ // DLNAを使用したコンテンツ特定モードを使う
+ try
+ {
+ getContentDirectorySoapAction(callback);
+ }
+ catch (Exception ee)
+ {
+ ee.printStackTrace();
+ }
+ contentListIsCreating = false;
+ return;
+ }
+
informationReceiver.updateMessage(activity.getString(R.string.get_image_list), false, false, 0);
changeContentsTransferMode(); // コンテンツトランスファモードに切り替える
contentListIsCreating = false;
}
- private void changeContentsTransferMode() {
- try {
- if (cameraApi == null) {
+ private void changeContentsTransferMode()
+ {
+ try
+ {
+ if (cameraApi == null)
+ {
return;
}
boolean isAvailable = false;
if (maxRetryCount <= 0) {
// Retry over
informationReceiver.updateMessage(activity.getString(R.string.change_transfer_mode_retry_over), true, true, Color.RED);
-
- // 試しに呼んでみる。
- getContentDirectorySoapAction();
}
} catch (Exception e) {
}
}
- private boolean setCameraFunction(boolean isRecording) {
- try {
+ private boolean setCameraFunction(boolean isRecording)
+ {
+ try
+ {
JSONObject reply = cameraApi.setCameraFunction((isRecording) ? "Remote Shooting" : "Contents Transfer");
try {
int value = reply.getInt("result");
informationReceiver.updateMessage(activity.getString(R.string.change_transfer_mode_retry), false, false, 0);
Thread.sleep(500); // 500ms 待つ
}
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
e.printStackTrace();
}
return (false);
}
- private void getContentDirectorySoapAction()
+ private void getContentDirectorySoapAction(ICameraContentListCallback callback)
{
+ try
+ {
+ // 呼んでおくか...
+ String accessUrl = cameraApi.getDdUrl();
+ String reply = SimpleHttpClient.httpGetWithHeader(accessUrl, null, "text/xml; charset=\"utf-8\"", timeoutMs);
+ Log.v(TAG, " dd.xml: " + reply);
+
+ accessUrl = accessUrl.substring(0, accessUrl.lastIndexOf("/"));
+ String url = accessUrl + "/DigitalImagingDesc.xml";
+ //String url = accessUrl + "/CdsDesc.xml";
+ reply = SimpleHttpClient.httpGet(url, timeoutMs);
+ Log.v(TAG, " " + url + " : " + reply);
+ // DigitalImagingDesc.xml の replyを parseする
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ XmlPullParser xmlPullParser = factory.newPullParser();
+ xmlPullParser.setInput(new StringReader(reply));
+ int eventType = xmlPullParser.getEventType();
+ boolean getDeviceNumber = false;
+ boolean getDeviceFile = false;
+ String name = "";
+ String getDeviceNumberUrl = "";
+ String getDeviceFileUrl = "";
+ while (eventType != XmlPullParser.END_DOCUMENT)
+ {
+ if(eventType == XmlPullParser.START_TAG)
+ {
+ name = xmlPullParser.getName();
+ getDeviceNumber = name.matches("X_DeviceNumber");
+ getDeviceFile = name.matches("X_DeviceFile");
+ }
+ else if(eventType == XmlPullParser.END_TAG)
+ {
+ name = "";
+ }
+ else if (eventType == XmlPullParser.TEXT)
+ {
+ String value = xmlPullParser.getText();
+ if ((name.length() > 0)&&(value.length() > 0))
+ {
+ Log.v(TAG, " DATA {" + name + ": " + value + " } ");
+ }
+ if (getDeviceNumber)
+ {
+ getDeviceNumberUrl = value;
+ }
+ if (getDeviceFile)
+ {
+ getDeviceFileUrl = value;
+ }
+ }
+ eventType = xmlPullParser.next();
+ }
+
+ if (getDeviceNumberUrl.length() > 1)
+ {
+ reply = SimpleHttpClient.httpGet(getDeviceNumberUrl, timeoutMs);
+ Log.v(TAG, " " + getDeviceNumberUrl + " : (" + reply.length() + " bytes) " + reply);
+ }
+ if (getDeviceFileUrl.length() > 1)
+ {
+ reply = SimpleHttpClient.httpGet(getDeviceFileUrl, timeoutMs);
+ Log.v(TAG, " " + getDeviceFileUrl + " : (" + reply.length() + " bytes) ");
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
//////////// ある程度の数に区切って送られてくる... 何度か繰り返す必要があるようだ ////////////
int sequenceNumber = 0;
"<ObjectID>0</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter>*</Filter><StartingIndex>" + returnedCount + "</StartingIndex><RequestedCount>3500</RequestedCount><SortCriteria></SortCriteria>" +
"<pana:X_FromCP>LumixLink2.0</pana:X_FromCP></u:Browse></s:Body></s:Envelope>";
*/
- String reply = SimpleHttpClient.httpPostWithHeader(url, postData, "SOAPACTION", "urn:schemas-upnp-org:service:ContentDirectory:" + sequenceNumber + "#Browse", "text/xml; charset=\"utf-8\"", timeoutMs);
+ Map<String, String> header = new HashMap<>();
+ header.clear();
+ header.put("SOAPACTION", "urn:schemas-upnp-org:service:ContentDirectory:" + sequenceNumber + "#Browse");
+ String reply = SimpleHttpClient.httpPostWithHeader(url, postData, header, "text/xml; charset=\"utf-8\"", timeoutMs);
if (reply.length() < 10)
{
Log.v(TAG, postData);
//break;
}
Log.v(TAG, " < REPLY > " + reply);
+ break;
/*
getObjectLists = getObjectLists.append(reply);
String matches = reply.substring(reply.indexOf("<TotalMatches>") + 14, reply.indexOf("</TotalMatches>"));
String GET_SMALL_PICTURE_AS_VGA = "get_small_picture_as_vga";
+ String USE_SMARTPHONE_TRANSFER_MODE = "use_smartphone_transfer_mode";
+
/*
//String GR2_DISPLAY_MODE = "gr2_display_mode";
//String GR2_DISPLAY_MODE_DEFAULT_VALUE = "0";
if (!items.containsKey(IPreferencePropertyAccessor.GET_SMALL_PICTURE_AS_VGA)) {
editor.putBoolean(IPreferencePropertyAccessor.GET_SMALL_PICTURE_AS_VGA, false);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.USE_SMARTPHONE_TRANSFER_MODE)) {
+ editor.putBoolean(IPreferencePropertyAccessor.USE_SMARTPHONE_TRANSFER_MODE, false);
+ }
editor.apply();
}
catch (Exception e)
Log.v(TAG, " " + key + " , " + value);
break;
+ case IPreferencePropertyAccessor.USE_SMARTPHONE_TRANSFER_MODE:
+ value = preferences.getBoolean(key, false);
+ Log.v(TAG, " " + key + " , " + value);
+ break;
+
default:
String strValue = preferences.getString(key, "");
setListPreference(key, key, strValue);
setBooleanPreference(IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA, IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA, defaultValue);
setBooleanPreference(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW, IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW, defaultValue);
setBooleanPreference(IPreferencePropertyAccessor.GET_SMALL_PICTURE_AS_VGA, IPreferencePropertyAccessor.GET_SMALL_PICTURE_AS_VGA, false);
+ setBooleanPreference(IPreferencePropertyAccessor.USE_SMARTPHONE_TRANSFER_MODE, IPreferencePropertyAccessor.USE_SMARTPHONE_TRANSFER_MODE, false);
}
catch (Exception e)
{
<string name="change_transfer_mode_retry_over">モード切替失敗(未サポート機?)</string>
<string name="content_is_nothing">画像がありません。</string>
+ <string name="pref_sony_use_smartphone_transfer">スマートフォン転送モードを使う</string>
+ <string name="pref_summary_sony_use_smartphone_transfer">うまく通信できない場合にチェックを入れてください。</string>
+
</resources>
<string name="change_transfer_mode_retry_over">CHANGE RETRY OVER(Not Support device?)</string>
<string name="content_is_nothing">Content is nothing.</string>
+ <string name="pref_sony_use_smartphone_transfer">Do use SmartPhone transfer mode.</string>
+ <string name="pref_summary_sony_use_smartphone_transfer">If you cannot communicate, please check this.</string>
+
</resources>
android:title="@string/pref_sony_api_list"
android:summary="@string/pref_summary_sony_api_list" />
+ <CheckBoxPreference
+ android:key="use_smartphone_transfer_mode"
+ android:title="@string/pref_sony_use_smartphone_transfer"
+ android:summary="@string/pref_summary_sony_use_smartphone_transfer" />
<CheckBoxPreference
android:key="get_small_picture_as_vga"