package io.evercam.androidapp;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import io.evercam.EvercamException;
import io.evercam.androidapp.custom.CustomedDialog;
import io.evercam.androidapp.tasks.CheckInternetTask;
import io.evercam.androidapp.tasks.ScanForCameraTask;
import io.evercam.androidapp.utils.Constants;
import io.evercam.network.discovery.DiscoveredCamera;
import io.evercam.network.query.EvercamQuery;
public class ScanActivity extends ParentActivity
{
private final String TAG = "ScanActivity";
private View scanProgressView;
private View scanResultListView;
private View scanResultNoCameraView;
private ProgressBar progressBar;
private ListView cameraListView;
private MenuItem cancelMenuItem;
private ArrayList<HashMap<String, Object>> deviceArrayList;
private ScanResultAdapter deviceAdapter;
private ArrayList<DiscoveredCamera> discoveredCameras = new ArrayList<>();
private SparseArray<Drawable> drawableArray;
private final String ADAPTER_KEY_LOGO = "camera_logo";
private final String ADAPTER_KEY_IP = "camera_id";
private final String ADAPTER_KEY_MODEL = "camera_model";
private ScanForCameraTask scanTask;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if(this.getActionBar() != null)
{
this.getActionBar().setDisplayHomeAsUpEnabled(true);
}
setContentView(R.layout.activity_scan);
scanProgressView = findViewById(R.id.scan_status_layout);
scanResultListView = findViewById(R.id.scan_result_layout);
scanResultNoCameraView = findViewById(R.id.scan_result_no_camera_layout);
progressBar = (ProgressBar)findViewById(R.id.horizontal_progress_bar);
progressBar.getProgressDrawable().setColorFilter(getResources().getColor(R.color.evercam_color), PorterDuff.Mode.SRC_IN);
drawableArray = new SparseArray<Drawable>();
cameraListView = (ListView) findViewById(R.id.scan_result_list);
Button addManuallyButton = (Button) findViewById(R.id.button_add_camera_manually);
deviceArrayList = new ArrayList<>();
deviceAdapter = new ScanResultAdapter(this, deviceArrayList, R.layout.scan_list_layout,
new String[]{ADAPTER_KEY_LOGO, ADAPTER_KEY_IP, ADAPTER_KEY_MODEL},
new int[]{R.id.camera_img, R.id.camera_ip, R.id.camera_model});
cameraListView.setAdapter(deviceAdapter);
cameraListView.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3)
{
@SuppressWarnings("unchecked") HashMap<String, Object> map = (HashMap<String,
Object>) cameraListView.getItemAtPosition(position);
String cameraIpText = (String) map.get(ADAPTER_KEY_IP);
String cameraIp = cameraIpText;
if(cameraIpText.contains(":"))
{
cameraIp = cameraIpText.substring(0, cameraIpText.indexOf(':'));
}
for(DiscoveredCamera camera : discoveredCameras)
{
if(camera.getIP().equals(cameraIp))
{
Intent intentAddCamera = new Intent(ScanActivity.this,
AddEditCameraActivity.class);
intentAddCamera.putExtra("camera", camera);
startActivityForResult(intentAddCamera, Constants.REQUEST_CODE_ADD_CAMERA);
}
}
}
});
addManuallyButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
startActivityForResult(new Intent(ScanActivity.this, AddEditCameraActivity.class)
, Constants.REQUEST_CODE_ADD_CAMERA);
}
});
new ScanCheckInternetTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_scan, menu);
cancelMenuItem = menu.findItem(R.id.action_cancel_scan);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch(item.getItemId())
{
case android.R.id.home:
if(isScanning())
{
showConfirmCancelScanDialog();
}
else
{
finish();
}
return true;
case R.id.action_cancel_scan:
showConfirmCancelScanDialog();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onBackPressed()
{
if(isScanning())
{
showConfirmCancelScanDialog();
}
else
{
finish();
}
}
// Finish this activity and transfer the result from AddEditCameraActivity
// to
// CamerasActivity.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(requestCode == Constants.REQUEST_CODE_ADD_CAMERA)
{
Intent returnIntent = new Intent();
if(resultCode == Constants.RESULT_TRUE)
{
setResult(Constants.RESULT_TRUE, returnIntent);
finish();
}
else
{
setResult(Constants.RESULT_FALSE, returnIntent);
// If no camera found, finish this page, otherwise stay in
// scanning page to let the user choose another.
if(discoveredCameras == null)
{
finish();
}
}
}
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
}
private void startDiscovery()
{
scanTask = new ScanForCameraTask(ScanActivity.this);
scanTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void stopDiscovery()
{
if(scanTask != null && !scanTask.isCancelled())
{
scanTask.cancel(true);
}
}
public void showTextProgress(boolean show)
{
scanProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showCameraListView(boolean show)
{
scanResultListView.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showNoCameraView(boolean show)
{
scanResultNoCameraView.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showHorizontalProgress(boolean show)
{
progressBar.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showCancelMenuItem(final boolean show)
{
if(cancelMenuItem == null)
{
new Handler().postDelayed(new Runnable()
{
@Override
public void run()
{
cancelMenuItem.setVisible(show);
}
}, 500);
}
else
{
cancelMenuItem.setVisible(show);
}
}
public void showConfirmCancelScanDialog()
{
CustomedDialog.getConfirmCancelScanDialog(ScanActivity.this,
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
stopDiscovery();
finish();
}
}).show();
}
public boolean isScanning()
{
if(cancelMenuItem.isVisible())
{
return true;
}
return false;
}
public void showScanResults(ArrayList<DiscoveredCamera> discoveredCameras)
{
if(discoveredCameras != null && discoveredCameras.size() > 0)
{
showCameraListView(true);
showNoCameraView(false);
}
else
{
showCameraListView(false);
showNoCameraView(true);
}
}
public void addNewCameraToResultList(DiscoveredCamera discoveredCamera)
{
try
{
Log.d(TAG, "New discovered camera: " + discoveredCamera.getIP());
showCameraListView(true);
showNoCameraView(false);
showTextProgress(false);
boolean merged = false; //The new device has been included in the device list or not
if(discoveredCameras.size() > 0)
{
for(int index = 0; index < discoveredCameras.size(); index++)
{
DiscoveredCamera originalCamera = discoveredCameras.get(index);
if(originalCamera.getIP().equals(discoveredCamera.getIP()))
{
originalCamera.merge(discoveredCamera);
Log.d(TAG, "Camera after merging: " + originalCamera.toString());
//Update the UI camera list
deviceArrayList.set(index, cameraToDeviceMap(originalCamera));
merged = true;
break;
}
}
}
if(!merged)
{
Log.d(TAG, "Not merged, add this camera: " + discoveredCamera.getIP());
ScanForCameraTask.cameraList.add(discoveredCamera);
deviceArrayList.add(cameraToDeviceMap(discoveredCamera));
new RetrieveThumbnailTask(discoveredCamera.getVendor(), discoveredCamera.getModel(),
ScanForCameraTask.cameraList.indexOf(discoveredCamera)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else
{
Log.d(TAG, "Already merged, discard this camera: " + discoveredCamera.getIP());
}
deviceAdapter.notifyDataSetChanged();
discoveredCameras = ScanForCameraTask.cameraList;
} catch(Exception e)
{
e.printStackTrace();
}
}
private HashMap<String, Object> cameraToDeviceMap(DiscoveredCamera camera)
{
HashMap<String, Object> deviceMap = new HashMap<String, Object>();
String ipTextShowing = camera.getIP();
if(camera.hasHTTP())
{
ipTextShowing = ipTextShowing + ":" + camera.getHttp();
}
deviceMap.put(ADAPTER_KEY_IP, ipTextShowing);
String vendor = camera.getVendor().toUpperCase(Locale.UK);
if(camera.hasModel())
{
String model = camera.getModel().toUpperCase(Locale.UK);
if(model.startsWith(vendor))
{
deviceMap.put(ADAPTER_KEY_MODEL, model);
}
else
{
deviceMap.put(ADAPTER_KEY_MODEL, vendor + " " + model);
}
}
else
{
deviceMap.put(ADAPTER_KEY_MODEL, vendor);
}
return deviceMap;
}
private class ScanResultAdapter extends SimpleAdapter
{
public ScanResultAdapter(Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to)
{
super(context, data, resource, from, to);
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View superView = super.getView(position, convertView, parent);
ImageView imageView = (ImageView) superView.findViewById(R.id.camera_img);
ProgressBar progressBar = (ProgressBar) superView.findViewById(R.id.progress);
Drawable drawable = drawableArray.get(position);
if(drawable != null)
{
imageView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
imageView.setImageDrawable(drawable);
}
return superView;
}
}
private class RetrieveThumbnailTask extends AsyncTask<Void, Void, Drawable>
{
private String vendorId;
private String modelId;
private int position;
public RetrieveThumbnailTask(String vendorId, String modelId, int position)
{
this.vendorId = vendorId;
this.modelId = modelId;
this.position = position;
}
@Override
protected Drawable doInBackground(Void... params)
{
String thumbnailUrl = "";
try
{
thumbnailUrl = EvercamQuery.getThumbnailUrlFor(vendorId, modelId);
}
catch(EvercamException e)
{
Log.e(TAG, e.toString());
}
Drawable drawable = null;
if(!thumbnailUrl.isEmpty())
{
try
{
InputStream stream = Unirest.get(thumbnailUrl).asBinary().getRawBody();
drawable = Drawable.createFromStream(stream, "src");
}
catch(UnirestException e)
{
Log.e(TAG, e.getStackTrace()[0].toString());
}
}
return drawable;
}
@Override
protected void onPostExecute(Drawable drawable)
{
if(drawable != null)
{
drawableArray.put(position, drawable);
}
else
{
Drawable questionImage = ScanActivity.this.getResources().getDrawable(R.drawable
.question_img_trans);
drawableArray.put(position, questionImage);
}
deviceAdapter.notifyDataSetChanged();
}
}
public void onScanningStarted()
{
showHorizontalProgress(true);
showTextProgress(true);
showCancelMenuItem(true);
}
public void onScanningFinished()
{
//Hide the scanning percentage
updateScanPercentage(null);
//Hide the scanning text
showTextProgress(false);
//Hide the horizontal progress bar
showHorizontalProgress(false);
//Hide the cancel button
showCancelMenuItem(false);
}
public void updateScanPercentage(final Float percentageFloat)
{
runOnUiThread(new Runnable() {
@Override
public void run()
{
if(getActionBar() != null)
{
if(percentageFloat == null)
{
getActionBar().setTitle("");
}
else
{
float percentf = percentageFloat;
int percentageInt = (int) percentf;
if(percentageInt < 100)
{
getActionBar().setTitle("Scanning... " + percentageInt + '%');
progressBar.setProgress(percentageInt);
}
}
}
}
});
}
class ScanCheckInternetTask extends CheckInternetTask
{
public ScanCheckInternetTask(Context context)
{
super(context);
}
@Override
protected void onPostExecute(Boolean hasNetwork)
{
if(hasNetwork)
{
startDiscovery();
}
else
{
CustomedDialog.showInternetNotConnectDialog(ScanActivity.this);
}
}
}
}