Skip to content

Commit

Permalink
What's new?
Browse files Browse the repository at this point in the history
- Improved DDNS and local switching: If Wi-Fi is not selected, app will check if local network device is accessible. If connection is established, local network will be used, otherwise DDNS.

- FPS counter shows camera's frame rate if client's FPS maxes out (if local speed is fast enough, frame rate will become i.e 43/19, because it can load 43 frames per second over the network. If it goes beyond 19, only "19 fps" will be shown. Otherwise i.e "10/19" fps)

- Wi-Fi selection screen code improved to detect currently connected Wi-Fi network

What's in progress?
- Recordings sorting
- All devices in a single list (recordings)

Signed-off-by: developerfromjokela <[email protected]>
  • Loading branch information
developerfromjokela committed Jul 22, 2020
1 parent 6c273a6 commit 2dc8711
Show file tree
Hide file tree
Showing 19 changed files with 483 additions and 302 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ apply plugin: 'com.android.application'
def versionMajor = 1
def versionMinor = 0
def versionPatch = 1
def versionBuild = 1 // 0-50=Alpha / 51-98=RC / 90-99=stable
def versionBuild = 90 // 0-50=Alpha / 51-98=RC / 90-99=stable
android {
compileSdkVersion 28
defaultConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.content.Context;
import android.util.Log;

import com.developerfromjokela.motioneyeclient.BuildConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.squareup.picasso.Cache;
Expand Down Expand Up @@ -56,6 +57,8 @@ public static <T> T createService(Class<T> serviceClass, String BASE_URL) throws
private static OkHttpClient createOkHttpClientNoCache() throws NoSuchAlgorithmException {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
if (!BuildConfig.DEBUG)
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
SSLContext sslContext = SSLContext.getDefault();
return new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
Expand All @@ -71,6 +74,8 @@ private static OkHttpClient createOkHttpClientNoCache() throws NoSuchAlgorithmEx
private static OkHttpClient createOkHttpClient(Context context, boolean enableCache) throws NoSuchAlgorithmException {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
if (!BuildConfig.DEBUG)
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
SSLContext sslContext = SSLContext.getDefault();
File httpCacheDirectory = new File(context.getCacheDir(), "http-cache");
int cacheSize = 20 * 1024 * 1024; // 10 MiB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
import android.graphics.Bitmap;

public class CameraImage {
private String fps = "0";
private int fps = 0;
private Bitmap bitmap = null;
private boolean successful;
private String errorString;


public String getFps() {
public int getFps() {
return fps;
}

public CameraImage(String fps, Bitmap bitmap, boolean successful) {
public CameraImage(int fps, Bitmap bitmap, boolean successful) {
this.fps = fps;
this.bitmap = bitmap;
this.successful = successful;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public static String getCurrentWifiNetworkId(Context context) {
final WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
final WifiInfo connectionInfo = wifiManager.getConnectionInfo();
if (connectionInfo != null) {
networkId = connectionInfo.getBSSID();
networkId = connectionInfo.getSSID();
}
}
return networkId;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,7 @@ private String getFullUrl() {
if (device.getDdnsURL().length() > 5) {
if ((Utils.getNetworkType(getActivity())) == NETWORK_MOBILE) {
serverurl = device.getDDNSUrlCombo();
} else if (device.getWlan() != null && device.getWlan().BSSID.equals(Utils.getCurrentWifiNetworkId(getActivity()))) {
} else if (device.getWlan() != null && device.getWlan().SSID.equals(Utils.getCurrentWifiNetworkId(getActivity()))) {
serverurl = device.getDeviceUrlCombo();

} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import com.developerfromjokela.motioneyeclient.database.Source;
import com.developerfromjokela.motioneyeclient.other.Utils;
import com.developerfromjokela.motioneyeclient.ui.adapters.ActionsAdapter;
import com.developerfromjokela.motioneyeclient.ui.utils.DeviceURLUtils;
import com.google.gson.Gson;
import com.ortiz.touchview.TouchImageView;

Expand Down Expand Up @@ -134,7 +135,6 @@ protected void onCreate(Bundle savedInstanceState) {
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
String serverurl;
String cameraId = camera.getId();
List<String> customActions = new ArrayList<>(camera.getActions());
Iterator cIterator = customActions.iterator();
Expand All @@ -159,27 +159,57 @@ protected void onCreate(Bundle savedInstanceState) {
actions.setLayoutManager(layoutManager);
adapter.notifyDataSetChanged();
initControls(camera, joystick, this);
if (device.getDdnsURL().length() > 5) {
if ((Utils.getNetworkType(FullCameraViewer.this)) == NETWORK_MOBILE) {
serverurl = device.getDDNSUrlCombo();
} else if (device.getWlan() != null && device.getWlan().BSSID.equals(Utils.getCurrentWifiNetworkId(FullCameraViewer.this))) {
serverurl = device.getDeviceUrlCombo();
DeviceURLUtils.getOptimalURL(this, device, new DeviceURLUtils.DeviceURLListener() {
@Override
public void onOptimalURL(String serverURL) {

if (!serverURL.contains("://"))
baseurl = Utils.removeSlash("http://" + serverURL);
else
baseurl = Utils.removeSlash(serverURL);

try {
time = new ArrayList<>();

timerRunnable = new Runnable() {
@Override
public void run() {
String cameraId = camera.getId();


String baseurl;
if (!serverURL.contains("://"))
baseurl = Utils.removeSlash("http://" + serverURL);
else
baseurl = Utils.removeSlash(serverURL);

} else {
serverurl = device.getDDNSUrlCombo();
String url = baseurl + "/picture/" + cameraId + "/current?_=" + new Date().getTime();
url = helper.addAuthParams("GET", url, "");
String finalUrl = url;
new DownloadImageFromInternet(cameraImage, loadingBar, fps, status, loadingCircle, camera, time, cameraFrame).execute(finalUrl);


}
};
String url = baseurl + "/picture/" + cameraId + "/current?_=" + new Date().getTime();
url = helper.addAuthParams("GET", url, "");
finalUrl = url;
new DownloadImageFromInternet(cameraImage, loadingBar, fps, status, loadingCircle, camera, time, cameraFrame).execute(finalUrl);

} catch (Exception e) {
e.printStackTrace();
showError(e.getMessage());
}
}
} else {
serverurl = device.getDeviceUrlCombo();

}
if (!serverurl.contains("://"))
baseurl = Utils.removeSlash("http://" + serverurl);
else
baseurl = Utils.removeSlash(serverurl);
@Override
public void onError(Exception e) {
showError(e.getMessage());
}
});


int framerate = Integer.valueOf(camera.getFramerate());
int framerate = Integer.parseInt(camera.getFramerate());
cameraName.setText(camera.getName());

cameraImage.setOnClickListener(new View.OnClickListener() {
Expand All @@ -205,51 +235,10 @@ public void onClick(View v) {
}
}
});
time = new ArrayList<>();

Device finalDevice = device;
timerRunnable = new Runnable() {
@Override
public void run() {
String serverurl;
String cameraId = camera.getId();

if (finalDevice.getDdnsURL().length() > 5) {
if ((Utils.getNetworkType(FullCameraViewer.this)) == NETWORK_MOBILE) {
serverurl = finalDevice.getDDNSUrlCombo();
} else if (finalDevice.getWlan() != null && finalDevice.getWlan().BSSID.equals(Utils.getCurrentWifiNetworkId(FullCameraViewer.this))) {
serverurl = finalDevice.getDeviceUrlCombo();

} else {
serverurl = finalDevice.getDDNSUrlCombo();

}
} else {
serverurl = finalDevice.getDeviceUrlCombo();

}
String baseurl;
if (!serverurl.contains("://"))
baseurl = Utils.removeSlash("http://" + serverurl);
else
baseurl = Utils.removeSlash(serverurl);

String url = baseurl + "/picture/" + cameraId + "/current?_=" + new Date().getTime();
url = helper.addAuthParams("GET", url, "");
String finalUrl = url;
new DownloadImageFromInternet(cameraImage, loadingBar, fps, status, loadingCircle, camera, time, cameraFrame).execute(finalUrl);


}
};
String url = baseurl + "/picture/" + cameraId + "/current?_=" + new Date().getTime();
url = helper.addAuthParams("GET", url, "");
finalUrl = url;
new DownloadImageFromInternet(cameraImage, loadingBar, fps, status, loadingCircle, camera, time, cameraFrame).execute(finalUrl);


} catch (Exception e) {
e.printStackTrace();
showError(e.getMessage());
}

} else {
Expand All @@ -262,6 +251,35 @@ public void run() {
// while interacting with the UI.
}

private void showError(String error) {
Log.e("FCV", "Error shown");
loaded = false;
loadingCircle.setVisibility(View.GONE);
cameraImage.setVisibility(View.GONE);
status.setVisibility(View.VISIBLE);
status.setText(error);
ViewParent parent = status.getParent();
LinearLayout r;
if (parent != null)
if (parent instanceof ViewGroup) {
ViewParent grandparent = ((ViewGroup) parent).getParent();
if (grandparent != null) {
if (parent instanceof LinearLayout) {
r = (LinearLayout) grandparent;
Button button = r.findViewById(R.id.tryagain);
button.setVisibility(View.VISIBLE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
timerRunnable.run();
}
});
}

}
}
}

@Override
public void onActionClicked(String action, View button) {

Expand Down Expand Up @@ -291,6 +309,7 @@ public void onFailure(Call<ActionStatus> call, Throwable t) {
}
});
} catch (NoSuchAlgorithmException e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}

Expand Down Expand Up @@ -363,7 +382,7 @@ protected CameraImage doInBackground(String... urls) {
URLConnection connection = url.openConnection();
fps = connection.getHeaderFields();
}
String humanReadableFPS = "0";
int humanReadableFPS;
InputStream in = url.openStream();
final Bitmap decoded = BitmapFactory.decodeStream(in);
in.close();
Expand All @@ -374,7 +393,7 @@ protected CameraImage doInBackground(String... urls) {

double d = Double.parseDouble(string.split("capture_fps_" + camera.getId() + "=")[1].split(";")[0].trim());
ii = (int) d;
humanReadableFPS = String.valueOf(Math.round(ii));
humanReadableFPS = Math.round(ii);
return new CameraImage(humanReadableFPS, decoded, true);

}
Expand Down Expand Up @@ -416,9 +435,13 @@ public void onAnimationEnd(Animator animation) {

if (time.size() == Utils.fpsLen) {

long streamingFps = time.size() * 1000 / (time.get(time.size()-1) - time.get(0));
long streamingFps = time.size() * 1000 / (time.get(time.size() - 1) - time.get(0));
int fpsDeliv = Math.round(streamingFps);
fps.setText(fpsDeliv + "/"+result.getFps()+" fps");
if (fpsDeliv > result.getFps() || fpsDeliv == result.getFps()) {
fpsDeliv = result.getFps();
fps.setText((fpsDeliv + " fps"));
} else
fps.setText((fpsDeliv + "/" + result.getFps() + " fps"));

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.developerfromjokela.motioneyeclient.classes.Media;
import com.developerfromjokela.motioneyeclient.classes.RecordingDevice;
import com.developerfromjokela.motioneyeclient.other.Utils;
import com.developerfromjokela.motioneyeclient.ui.utils.DeviceURLUtils;
import com.squareup.picasso.Picasso;

import java.security.NoSuchAlgorithmException;
Expand All @@ -37,6 +38,7 @@ public class RecordingsAdapter extends RecyclerView.Adapter<RecordingsAdapter.De
private List<Media> mediaList;
private MediaAdapterListener listener;
private RecordingDevice device;
private String cachedURL = "";

public class DevicesViewHolder extends RecyclerView.ViewHolder {

Expand Down Expand Up @@ -75,29 +77,14 @@ public void onBindViewHolder(final RecordingsAdapter.DevicesViewHolder holder, i
holder.itemDate.setText(media.getShortMonent());
holder.itemSize.setText(media.getSize());
String baseurl;
String serverurl;
if (device.getDevice().getDdnsURL().length() > 5) {
if ((Utils.getNetworkType(mContext)) == NETWORK_MOBILE) {
serverurl = device.getDevice().getDDNSUrlCombo();
} else if (device.getDevice().getWlan() != null && device.getDevice().getWlan().BSSID.equals(Utils.getCurrentWifiNetworkId(mContext))) {
serverurl = device.getDevice().getDeviceUrlCombo();

} else {
serverurl = device.getDevice().getDDNSUrlCombo();

}
} else {
serverurl = device.getDevice().getDeviceUrlCombo();

}
Log.e("Setup", String.valueOf(serverurl.split("//").length));
if (!serverurl.contains("://"))
baseurl = removeSlash("http://" + serverurl);
Log.e("Setup", String.valueOf(cachedURL.split("//").length));
if (!cachedURL.contains("://"))
baseurl = removeSlash("http://" + cachedURL);
else
baseurl = removeSlash(serverurl);
baseurl = removeSlash(cachedURL);

try {
String url = baseurl + "/movie/"+device.getCamera().getId()+"/preview"+media.getPath()+"?_=" + new Date().getTime();
String url = baseurl + "/movie/" + device.getCamera().getId() + "/preview" + media.getPath() + "?_=" + new Date().getTime();
MotionEyeHelper helper = new MotionEyeHelper();
helper.setUsername(device.getDevice().getUser().getUsername());
helper.setPasswordHash(device.getDevice().getUser().getPassword());
Expand All @@ -113,7 +100,7 @@ public void onBindViewHolder(final RecordingsAdapter.DevicesViewHolder holder, i
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onMediaClicked(position, media);
listener.onMediaClicked(position, media, cachedURL);
}
});

Expand All @@ -122,7 +109,7 @@ public void onClick(View v) {

public interface MediaAdapterListener {

void onMediaClicked(int position, Media media);
void onMediaClicked(int position, Media media, String cachedURL);
}

@Override
Expand All @@ -133,6 +120,18 @@ public int getItemCount() {

public void updateDetails(RecordingDevice device) {
this.device = device;
DeviceURLUtils.getOptimalURL(mContext, device.getDevice(), new DeviceURLUtils.DeviceURLListener() {
@Override
public void onOptimalURL(String serverURL) {
cachedURL = serverURL;
notifyDataSetChanged();
}

@Override
public void onError(Exception e) {

}
});
}

}
Loading

0 comments on commit 2dc8711

Please sign in to comment.