OSDN Git Service

SONYの画像取得のために確認中。いったん保存。その2
authorMRSa <mrsa@myad.jp>
Tue, 10 Sep 2019 15:24:01 +0000 (00:24 +0900)
committerMRSa <mrsa@myad.jp>
Tue, 10 Sep 2019 15:24:01 +0000 (00:24 +0900)
app/src/main/java/net/osdn/gokigen/pkremote/camera/utils/SimpleHttpClient.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/panasonic/wrapper/connection/PanasonicSsdpClient.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/panasonic/wrapper/playback/PanasonicPlaybackControl.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/sony/wrapper/connection/SonySsdpClient.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/sony/wrapper/playback/SonyPlaybackControl.java
app/src/main/java/net/osdn/gokigen/pkremote/preference/IPreferencePropertyAccessor.java
app/src/main/java/net/osdn/gokigen/pkremote/preference/sony/SonyPreferenceFragment.java
app/src/main/res/values-ja/strings.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/preferences_sony.xml

index d1490be..b28cd32 100644 (file)
@@ -328,7 +328,18 @@ public class SimpleHttpClient
      */
     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));
     }
 
     /**
@@ -336,9 +347,9 @@ public class SimpleHttpClient
      *
      *
      */
-    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));
     }
 
     /**
@@ -348,7 +359,7 @@ public class SimpleHttpClient
      */
     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));
     }
 
     /**
@@ -356,7 +367,7 @@ public class SimpleHttpClient
      *
      *
      */
-    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;
@@ -375,9 +386,13 @@ public class SimpleHttpClient
             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)
             {
@@ -385,18 +400,24 @@ public class SimpleHttpClient
             }
             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)
             {
index 7f6fb01..6b95c7e 100644 (file)
@@ -151,6 +151,10 @@ class PanasonicSsdpClient
                         Log.v(TAG, "Already received. : " + ddUsn);
                     }
                 }
+                else
+                {
+                    Log.v(TAG, " SSDP REPLY MESSAGE (ignored) : " + ssdpReplyMessage);
+                }
                 currentTime = System.currentTimeMillis();
             }
         }
index 3b39323..073b565 100644 (file)
@@ -24,6 +24,7 @@ import java.util.ArrayDeque;
 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
@@ -88,7 +89,10 @@ 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);
index cb44f69..5792851 100644 (file)
@@ -1,14 +1,17 @@
 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;
@@ -35,11 +38,14 @@ class SonySsdpClient
     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)
     {
@@ -47,11 +53,14 @@ class SonySsdpClient
         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()
@@ -129,6 +138,14 @@ class SonySsdpClient
                             }
                             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));
                             }
@@ -139,6 +156,10 @@ class SonySsdpClient
                         Log.v(TAG, "Already received. : " + ddUsn);
                     }
                 }
+                else
+                {
+                    Log.v(TAG, " SSDP REPLY (ignored) : " + ssdpReplyMessage + " " + useSmartphoneTransfer);
+                }
                 currentTime = System.currentTimeMillis();
             }
         }
index bccf78a..c958787 100644 (file)
@@ -26,9 +26,13 @@ import net.osdn.gokigen.pkremote.preference.IPreferencePropertyAccessor;
 
 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();
@@ -178,19 +182,41 @@ public class SonyPlaybackControl implements IPlaybackControl {
     }
 
     @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();  // コンテンツトランスファモードに切り替える
 
@@ -258,9 +284,12 @@ public class SonyPlaybackControl implements IPlaybackControl {
         contentListIsCreating = false;
     }
 
-    private void changeContentsTransferMode() {
-        try {
-            if (cameraApi == null) {
+    private void changeContentsTransferMode()
+    {
+        try
+        {
+            if (cameraApi == null)
+            {
                 return;
             }
             boolean isAvailable = false;
@@ -272,9 +301,6 @@ public class SonyPlaybackControl implements IPlaybackControl {
             if (maxRetryCount <= 0) {
                 // Retry over
                 informationReceiver.updateMessage(activity.getString(R.string.change_transfer_mode_retry_over), true, true, Color.RED);
-
-                // 試しに呼んでみる。
-                getContentDirectorySoapAction();
             }
 
         } catch (Exception e) {
@@ -282,8 +308,10 @@ public class SonyPlaybackControl implements IPlaybackControl {
         }
     }
 
-    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");
@@ -294,14 +322,85 @@ public class SonyPlaybackControl implements IPlaybackControl {
                 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;
@@ -331,7 +430,10 @@ public class SonyPlaybackControl 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);
@@ -339,6 +441,7 @@ public class SonyPlaybackControl implements IPlaybackControl {
                 //break;
             }
             Log.v(TAG, " < REPLY > " + reply);
+            break;
 /*
             getObjectLists = getObjectLists.append(reply);
             String matches = reply.substring(reply.indexOf("<TotalMatches>") + 14, reply.indexOf("</TotalMatches>"));
index 953cb70..cbf6934 100644 (file)
@@ -85,6 +85,8 @@ public interface IPreferencePropertyAccessor
 
     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";
index 26e703a..3f4e7bc 100644 (file)
@@ -126,6 +126,9 @@ public class SonyPreferenceFragment  extends PreferenceFragmentCompat implements
             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)
@@ -162,6 +165,11 @@ public class SonyPreferenceFragment  extends PreferenceFragmentCompat implements
                     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);
@@ -316,6 +324,7 @@ public class SonyPreferenceFragment  extends PreferenceFragmentCompat implements
                         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)
                     {
index 401869e..381813d 100644 (file)
     <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>
index 3e0d265..54b8eca 100644 (file)
     <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>
index 05d4318..52e6022 100644 (file)
             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"