我正在尝试开发一个用于播放演示文稿的android远程控制代码。该项目分为两部分:
当前的代码在Android手机中工作正常,Marshmallow更新(在Lollipop和Marshmallow上试过)但是当在Nougat上尝试相同的代码时,应用程序崩溃了(Android Remote已经停止,再次打开应用程序)。
套接字服务器代码:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.MouseInfo;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class RemoteDroidServer {
private static ServerSocket server = null;
private static Socket client = null;
private static BufferedReader in = null;
private static String line;
private static boolean isConnected=true;
private static Robot robot;
private static final int SERVER_PORT = 8998;
public static void main(String[] args) {
boolean leftpressed=false;
boolean rightpressed=false;
try{
robot = new Robot();
server = new ServerSocket(SERVER_PORT); //Create a server socket on port 8998
client = server.accept(); //Listens for a connection to be made to this socket and accepts it
in = new BufferedReader(new InputStreamReader(client.getInputStream())); //the input stream where data will come from client
System.out.println("Connected to server");
}catch (IOException e) {
System.out.println("Error in opening Socket");
System.exit(-1);
}catch (AWTException e) {
System.out.println("Error in creating robot instance");
System.exit(-1);
}
//read input from client while it is connected
while(isConnected){
try{
line = in.readLine(); //read input from client
System.out.println(line); //print whatever we get from client
//-----------------VLC Commands--------------------------------
/*
Space Bar to Play or Pause. ...
F to toggle Full Screen. ...
A to Change Aspect ratio. ...
Z to Change Zoom Mode. ...
Ctrl+RightArrow to move forward
Ctrl+LeftArrow to move backward
Alt+Left/Alt+Right to Fast Forward slow. ...
*/
//if user clicks on fullscreen (Key- F)
if(line.equalsIgnoreCase("fullscreen")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_F);
robot.keyRelease(KeyEvent.VK_F);
}
//if user click on Change Aspect ratio (Key- A)
if(line.equalsIgnoreCase("aspectratio")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_A);
robot.keyRelease(KeyEvent.VK_A);
}
//if user clicks on Increase Volume (CTRL + UpArrowKey)
if(line.equalsIgnoreCase("volplus")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_UP);
// CTRL+UpArrowKey is now pressed (receiving application should see a "key down" event.)
robot.keyRelease(KeyEvent.VK_UP);
robot.keyRelease(KeyEvent.VK_CONTROL);
}
//if user clicks on Decrease Volume (CTRL + DownArrowKey)
if(line.equalsIgnoreCase("volminus")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_DOWN);
// CTRL+DownArrowKey is now pressed (receiving application should see a "key down" event.)
robot.keyRelease(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_CONTROL);
}
//if user clicks on move forward (CTRL + RightArrow)
if(line.equalsIgnoreCase("forward")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_RIGHT);
// CTRL+UpArrowKey is now pressed (receiving application should see a "key down" event.)
robot.keyRelease(KeyEvent.VK_RIGHT);
robot.keyRelease(KeyEvent.VK_CONTROL);
}
//if user clicks on move forward (CTRL + LeftArrow)
if(line.equalsIgnoreCase("backward")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_LEFT);
// CTRL+UpArrowKey is now pressed (receiving application should see a "key down" event.)
robot.keyRelease(KeyEvent.VK_RIGHT);
robot.keyRelease(KeyEvent.VK_LEFT);
}
//-------------------------------------------------------------
//if user clicks on f5
if(line.equalsIgnoreCase("F5")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_F5);
robot.keyRelease(KeyEvent.VK_F5);
}
//if user clicks on esc
if(line.equalsIgnoreCase("escape")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_ESCAPE);
robot.keyRelease(KeyEvent.VK_ESCAPE);
}
//if user clicks on first slide
if(line.equalsIgnoreCase("home")){
//Simulate press and release of key 'Home'
robot.keyPress(KeyEvent.VK_HOME);
robot.keyRelease(KeyEvent.VK_HOME);
}
//if user clicks on last slide
if(line.equalsIgnoreCase("end")){
//Simulate press and release of key 'END'
robot.keyPress(KeyEvent.VK_END);
robot.keyRelease(KeyEvent.VK_END);
}
//----------------------------------------------------------------------------
//if user clicks on next
if(line.equalsIgnoreCase("next")){
//Simulate press and release of key 'n'
robot.keyPress(KeyEvent.VK_N);
robot.keyRelease(KeyEvent.VK_N);
}
//if user clicks on previous
else if(line.equalsIgnoreCase("previous")){
//Simulate press and release of key 'p'
robot.keyPress(KeyEvent.VK_P);
robot.keyRelease(KeyEvent.VK_P);
}
//if user clicks on play/pause
else if(line.equalsIgnoreCase("play")){
//Simulate press and release of spacebar
robot.keyPress(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_SPACE);
}
//input will come in x,y format if user moves mouse on mousepad
else if(line.contains(",")){
float movex=Float.parseFloat(line.split(",")[0]);//extract movement in x direction
float movey=Float.parseFloat(line.split(",")[1]);//extract movement in y direction
Point point = MouseInfo.getPointerInfo().getLocation(); //Get current mouse position
float nowx=point.x;
float nowy=point.y;
robot.mouseMove((int)(nowx+movex),(int)(nowy+movey));//Move mouse pointer to new location
}
//if user taps on mousepad to simulate a left click
else if(line.contains("left_click")){
//Simulate press and release of mouse button 1(makes sure correct button is pressed based on user's dexterity)
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
//Exit if user ends the connection
else if(line.equalsIgnoreCase("exit")){
isConnected=false;
//Close server and client socket
server.close();
client.close();
}
} catch (IOException e) {
System.out.println("Read failed");
System.exit(-1);
}
}
}
}
我的Android代码是:
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class Powerpoint extends AppCompatActivity implements View.OnClickListener{
Context context;
Button esc;
Button nextButton;
Button previousButton;
Button end;
Button btnConnect;
Button f5;
Button home;
private boolean isConnected=false;
private boolean mouseMoved=false;
private Socket socket;
private PrintWriter out;
private String serverIP= Constants.SERVER_IP;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_powerpoint);
context = this; //save the context to show Toast messages
//Get references of all buttons
esc = (Button)findViewById(R.id.btnEnd);
nextButton = (Button)findViewById(R.id.btnNext);
previousButton = (Button)findViewById(R.id.btnPrevious);
f5 = (Button)findViewById(R.id.btnStart);
btnConnect = (Button)findViewById(R.id.btnConnect);
home = (Button)findViewById(R.id.btnHome);
end = (Button)findViewById(R.id.btnLastSlide);
//this activity extends View.OnClickListener, set this as onClickListener
//for all buttons
esc.setOnClickListener(this);
nextButton.setOnClickListener(this);
previousButton.setOnClickListener(this);
f5.setOnClickListener(this);
home.setOnClickListener(this);
end.setOnClickListener(this);
btnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// get prompts.xml view
LayoutInflater li = LayoutInflater.from(context);
View promptsView = li.inflate(R.layout.prompt, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set prompts.xml to alertdialog builder
alertDialogBuilder.setView(promptsView);
final EditText userInput = (EditText) promptsView
.findViewById(R.id.editTextDialogUserInput);
// set dialog message
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// get user input and set it to result
// edit text
serverIP=userInput.getText().toString();
Toast.makeText(getApplicationContext(),"Ip:"+serverIP,Toast.LENGTH_SHORT).show();
ConnectPhoneTask connectPhoneTask = new ConnectPhoneTask();
connectPhoneTask.execute(serverIP); //try to connect to server in another thread
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
//OnClick method is called when any of the buttons are pressed
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnEnd:
if (isConnected && out!=null) {
out.println(Constants.ESCAPE);//send "escape" to server
}
break;
case R.id.btnNext:
if (isConnected && out!=null) {
out.println(Constants.NEXT); //send "next" to server
}
break;
case R.id.btnPrevious:
if (isConnected && out!=null) {
out.println(Constants.PREVIOUS); //send "previous" to server
}
break;
case R.id.btnStart:
if (isConnected && out!=null) {
out.println(Constants.F5); //send "previous" to server
}
break;
case R.id.btnHome:
if (isConnected && out!=null) {
out.println(Constants.HOME); //send "home" to server
}
break;
case R.id.btnLastSlide:
if (isConnected && out!=null) {
out.println(Constants.END); //send "end" to server
}
break;
}
}
@Override
public void onDestroy()
{
super.onDestroy();
if(isConnected && out!=null) {
try {
out.println("exit"); //tell server to exit
socket.close(); //close socket
} catch (IOException e) {
Log.e("remotedroid", "Error in closing socket", e);
}
}
}
public class ConnectPhoneTask extends AsyncTask<String,Void,Boolean> {
@Override
protected Boolean doInBackground(String... params) {
boolean result = true;
try {
InetAddress serverAddr = InetAddress.getByName(params[0]);
socket = new Socket(serverAddr, Constants.SERVER_PORT);//Open socket on server IP and port
isConnected=true;
} catch (IOException e) {
Log.e("remotedroid", "Error while connecting", e);
result = false;
isConnected=false;
}
return result;
}
@Override
protected void onPostExecute(Boolean result)
{
isConnected = result;
Toast.makeText(context, isConnected ? "Connected to server!" : "Error while connecting", Toast.LENGTH_LONG).show();
try {
if(isConnected) {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true); //create output stream to send data to server
}
}catch (IOException e){
Log.e("remotedroid", "Error while creating OutWriter", e);
Toast.makeText(context,"Error while connecting",Toast.LENGTH_LONG).show();
}
}
}
}
常量类代码:
public class Constants {
public static final String SERVER_IP = "192.168.1.5";
public static final int SERVER_PORT = 8998;
public static final String NEXT="next";
public static final String PREVIOUS="previous";
public static final String ESCAPE="escape";
public static final String F5="f5";
public static final String HOME="home";
public static final String END="end";
public static final String SPACE="play";
public static final String VOLUP="volplus";
public static final String VOLDOWN="volminus";
public static final String FASTFORWARD="forward";
public static final String BACKWARD="backward";
public static final String ZOOM="fullscreen";
public static final String ASPECTRATIO="aspectratio";
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_powerpoint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.sahajsolns.socketprogrammingdemo.Powerpoint">
<Button
android:text="Start PPT"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="48dp"
android:id="@+id/btnStart"
android:layout_below="@+id/lblModuleTitle"
android:layout_centerHorizontal="true" />
<TextView
android:text="Powerpoint Module"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="45dp"
android:id="@+id/lblModuleTitle"
android:textSize="18sp"
android:textColor="@android:color/holo_orange_dark"
android:textStyle="normal|bold"
android:lineSpacingExtra="8sp" />
<Button
android:text="Next Slide"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/btnNext"
android:layout_below="@+id/btnStart"
android:layout_toRightOf="@+id/btnStart"
android:layout_toEndOf="@+id/btnStart" />
<Button
android:text="End PPT"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/btnEnd"
android:layout_below="@+id/btnNext"
android:layout_toRightOf="@+id/btnPrevious"
android:layout_toEndOf="@+id/btnPrevious" />
<Button
android:text="Previous Slide"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/btnPrevious"
android:layout_below="@+id/btnStart"
android:layout_toLeftOf="@+id/btnStart"
android:layout_toStartOf="@+id/btnStart" />
<Button
android:text="Connect To Server"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/btnConnect" />
<Button
android:text="Home"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_below="@+id/btnPrevious"
android:layout_toLeftOf="@+id/btnEnd"
android:layout_toStartOf="@+id/btnEnd"
android:id="@+id/btnHome" />
<Button
android:text="Last Slide"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/btnLastSlide"
android:layout_below="@+id/btnNext"
android:layout_toRightOf="@+id/btnEnd"
android:layout_toEndOf="@+id/btnEnd" />
</RelativeLayout>