- Forum-Beiträge: 103
23.06.2017, 12:14:06 via Website
23.06.2017 12:14:06 via Website
Hallo !
Ich programmiere eine App, die als Client mit einem Server unter Verwendung von
Sockets kommunizieren soll.
Der Server ist eine reine Java-Anwendung, die mittels 'java ServerC' gestartet
wird. Zum Test habe ich das Smartphone per USB an den Laptop gebunden, der in
meinem lokalen Netzwerk ist und den Server in einer DOS-Box enthält.
Die App erzeugt automatisch Klicks auf Bilder der Camera und sendet diese dann
an den Server, der sie im aktuellen Verzeichnis abspeichert. Das funktioniert
zunächst. Nun will ich vom Server eine Rückmeldung an den Client schicken, wenn
das jeweilige Bild gespeichert wurde. Dabei bricht der Client (App) mit
"Socket closed" ab, wenn die Rückmeldung gelesen werden soll.
Wie kann das korrigiert werden ?
Client-Code:
package de.carpelibrum.camera;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class CameraActivityC extends Activity implements
SurfaceHolder.Callback ,
Camera.PictureCallback {
private final String TAG = "carpelibrum";
private Camera camera;
private Camera.PictureCallback cameraCallbackVorschau;
private Camera.ShutterCallback cameraCallbackVerschluss;
private SurfaceHolder cameraViewHolder;
SurfaceView cameraView;
EditText ed;
Timer t;
String params;
int beg = 1000; //begin-interval
int repeat = 5000; //repeat-interval
boolean edOkay = false;
Socket clientSocket;
boolean rueckMeld=true; //Rückmeldung vom Server
boolean nextImg=true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.main);
ed = (EditText)findViewById(R.id.textView1);
/*
ed.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
hideKeyboard(CameraActivityC.this); //remove softkeyboard
String sp=ed.getText().toString().substring(8);
String ca[]=sp.split(",");
beg = Integer.parseInt(ca[0]); //begin-interval
repeat = Integer.parseInt(ca[1]); //repeat-interval
Log.d("****** Parameter:",sp);
ed.setVisibility(View.GONE); //remove EditText
edOkay = true;
t = new Timer();
//automatisch wiederholter Start von ObtainMotionEvent
t.schedule(new Zeitgeber(),beg,repeat);//1000,5*1000);
return true;
default:
break;
}
}
return false;
}
});
*/
test(); //vereinfachter Test
}
void test() {
ed.setVisibility(View.GONE); //remove EditText
edOkay = true;
t = new Timer();
//automatisch wiederholter Start von ObtainMotionEvent
t.schedule(new Zeitgeber(),1000,5*1000);//1000,5*1000);
}
// Interface 1 SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
camera.stopPreview();
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(width, height);
camera.setParameters(params);
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.d(TAG, "surF: "+e.getMessage());
}
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
//Ende Interface 1
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!edOkay) return true; //Bestätigung per EditText fehlt
if(event.getAction() == MotionEvent.ACTION_UP) {
camera.takePicture(this.cameraCallbackVerschluss, this.cameraCallbackVorschau
, this); //onPictureTaken
return true;
}
else {
return super.onTouchEvent(event);
}
}
// Interface 2 Camera.PictureCallback
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
//Name oder IP-Adresse des Servers
clientSocket = new Socket("acer_laptop",45678); //Server und Port
Log.i("OnPic_client1",clientSocket.toString());
OutputStream out = new BufferedOutputStream(clientSocket.getOutputStream());
//für Rückmeldung vom Server
InputStream in = new BufferedInputStream(clientSocket.getInputStream());
byte[] b2=new byte[6];
SimpleDateFormat df = new SimpleDateFormat("yyyy_MM_dd_hh_mm_ss");
//Teil1 durch Nutzernamen ersetzen, der auch als Unterverzeichnis auf dem Server dient
String fname = "foto_" + df.format(new Date())+".jpg";
out.write(fname.length());
out.write(fname.getBytes());
out.write(data);
out.flush();
out.close();
nextImg=false;
//*** Rückmeldung vom Server
if (rueckMeld) {
Log.i("OnPic_client2 closed:", "" + clientSocket.isClosed());
Log.i("OnPic_client3",clientSocket.toString());
//clientSocket ist nicht geschlossen !
//Versuch Rückmeldung vom Server zu lesen
int rc = in.read(b2); //hier kommt der Fehler "Socket closed"
Log.i(TAG, "Meldung vom Server:" + rc);
nextImg=true;
}
nextImg=false;
camera.startPreview();
} catch (Exception ex) {
Log.e("Ex_OnPicclient4:",ex.getMessage()); //socket closed
//aber nicht clientSocket !
Log.e("Ex_OnPic_client5:",clientSocket.isClosed()+","+clientSocket.toString());
ex.printStackTrace();
t.cancel();
finish();
}
}
//Ende Interface 2
@Override
protected void onPause() {
super.onPause();
if(camera != null) {
// camera.stopPreview();
camera.release();
Log.d(TAG,"Pause !");
if (t != null) t.cancel(); //TimerTask beenden
}
}
@Override
protected void onResume() {
super.onResume();
cameraView = (SurfaceView) findViewById(R.id.surfaceview1);
cameraViewHolder = cameraView.getHolder();
cameraViewHolder.addCallback(this); //Interface 1
cameraViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cameraCallbackVorschau = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
}
};
cameraCallbackVerschluss = new Camera.ShutterCallback() {
public void onShutter() {
}
};
}
//erzeuge ein MotionEvent
void ObtainMotionEvent(SurfaceView sv) {
if (false) { //nicht genutzt
// if (clientSocket != null) {
boolean tc = clientSocket.isClosed();
Log.e("***Obt_client closed:", "" + tc);
if (!tc) { //server arbeitet noch am vorherigen Bild
return;
}
}
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis() + 100;
float x = 50.0f;
float y = 100.0f;
// List of meta states found here: developer.android.com/reference/android/view/KeyEvent.html#getMetaState()
int metaState = 0; //key_down
MotionEvent motionEvent = MotionEvent.obtain(
downTime,
eventTime,
MotionEvent.ACTION_UP,
x,
y,
metaState
);
sv.dispatchTouchEvent(motionEvent); //evtl. nicht notwendig
onTouchEvent(motionEvent); //motionEvent senden
}
//zyklische Erzeugung und Auswertung eines Touch-Events
class Zeitgeber extends TimerTask {
public void run() {
try {
ObtainMotionEvent(cameraView);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//Soft-Keyboard für EditText entfernen nach KEYCODE_ENTER
public static void hideKeyboard(Activity activity) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
//Find the currently focused view, so we can grab the correct window token from it.
View view = activity.getCurrentFocus();
//If no view currently has focus, create a new one, just so we can grab a window token from it
if (view == null) {
view = new View(activity);
}
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
Servercode:
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;
public class ServerC {
// static int drl2 = 0;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(45678);
int clients = 0;
System.out.println("... Server gestartet, warte auf Client-Verbindungen");
while (true) {
ServerThreadC serverThread = new ServerThreadC(serverSocket.accept(),++clients);
serverThread.start();
System.out.println("... warte auf weitere Client-Verbindungen");
}
}
}
class ServerThreadC extends Thread {
static int drl2=0;
Socket clientSocket;
InputStream in;
PrintStream os;
OutputStream ots;
int nr;
boolean rueckMeld=true;
// int drl2 = 0;
byte[] b = new byte[4096];
public ServerThreadC(Socket clientSocket, int nr) throws IOException {
this.clientSocket = clientSocket;
System.out.println("OnPic_client:"+clientSocket.toString());
this.nr = nr;
in = new BufferedInputStream(clientSocket.getInputStream());
ots = clientSocket.getOutputStream();
// os = new PrintStream(clientSocket.getOutputStream());
System.out.println("... Client angemeldet:"+clientSocket.getInetAddress());
}
public void run() {
FileOutputStream out=null;
byte[] b=new byte[4096];
String fname="";
int drl = 0;
int len;
long start = System.currentTimeMillis();
try {
while ((len=in.read(b))>0) {
if (drl++ == 0) { //Block 1:Laenge|Dateiname|Daten
int le = b[0];
byte[] tf=new byte[le];
System.arraycopy(b,1,tf,0,le);
fname = new String(tf); //Dateiname
out = new FileOutputStream(fname);
out.write(b,le+1,len-le-1); //Datenteil ausgeben
/*
if (++drl2 < 2) {
System.out.println("...vor sleep");
ServerThread.sleep(10000);
System.out.println("...nach sleep");
}
*/
continue;
}
out.write(b,0,len);
}
out.flush();
out.close();
System.out.println("1clientSocket closed???"+clientSocket.isClosed());
if (rueckMeld) {
// os.println("Ausgabe beendet:" + fname); //*** Ausgabe zum Client
ots.write(1);
System.out.println("Ausgabe beendet:"+fname);
System.out.println("1clientSocket closed???"+clientSocket.isClosed());
} else {
// clientSocket.close();
System.out.println("ohne Rueck Ausgabe beendet:"+fname);
System.out.println("2clientSocket closed???"+clientSocket.isClosed());
}
// OutputStream ots = clientSocket.getOutputStream();
// ots.write(1);
double d = (System.currentTimeMillis()-start)/1000.0;
DecimalFormat df = new DecimalFormat("##.##");
// System.out.println("clientSocket closed:"+df.format(d));
} catch (Exception ex){
ex.printStackTrace();
}
}
}
Edit by Mod Ludy: Code lesbarer gestaltet
— geändert am 23.06.2017, 18:47:40 durch Moderator
Empfohlener redaktioneller Inhalt
Mit Deiner Zustimmung wird hier ein externer Inhalt geladen.
Mit Klick auf den oben stehenden Button erklärst Du Dich damit einverstanden, dass Dir externe Inhalte angezeigt werden dürfen. Dabei können personenbezogene Daten an Drittanbieter übermittelt werden. Mehr Infos dazu findest Du in unserer Datenschutzerklärung.