通过Android应用程序向Apache服务器发送请求,摆脱无限循环

时间:2022-09-17 08:23:02

this is a schema of my project:

这是我的项目的架构:

1) Android app -> 2) Apache server on RPi -> 3) Python scripts that control -> 4) my device

1)Android应用程序 - > 2)RPi上的Apache服务器 - > 3)控制 - > 4)我的设备的Python脚本

1) Android app - 2 simple switches, each one sends different request to Apache on RPi:

1)Android应用程序 - 2个简单的开关,每个都在RPi上向Apache发送不同的请求:

public class MainActivity extends Activity{

private static final String TAG = "MainActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Switch switch_auto = findViewById(R.id.switch_auto);
    Switch switch_manual = findViewById(R.id.switch_manual);

    switch_auto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                new Background_get().execute("led1=1");
            } else {
                new Background_get().execute("led1=0");
            }
        }
    });

    switch_manual.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                Log.d(TAG, "onCheckedChanged: SET TO TRUE");
                new Background_get().execute("led2=1");
                Log.d(TAG, "onCheckedChanged: EXIT");
            } else {
                Log.d(TAG, "onCheckedChanged: SET TO FALSE");
                new Background_get().execute("led2=0");
                Log.d(TAG, "onCheckedChanged: EXIT");
            }
        }
    });

}

private class Background_get extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... params) {
        try {
            URL url = new URL("http://192.168.0.248/?" + params[0]);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuilder result = new StringBuilder();
            String inputLine;
            while ((inputLine = in.readLine()) != null)
                result.append(inputLine).append("\n");

            in.close();
            connection.disconnect();
            return result.toString();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
}

2) Apache server on RPi - very simple PHP code:

2)RPi上的Apache服务器 - 非常简单的PHP代码:

  • if it was "led1=1", launch Python script that makes device work for 10 seconds (time.sleep(10))
  • 如果是“led1 = 1”,则启动Python脚本,使设备工作10秒钟(time.sleep(10))

  • if it was "led1=0", just print something
  • 如果它是“led1 = 0”,只需打印一些东西

  • if it was "led2=1", launch another Python script that makes device work for an indefinite period of time (while True: time.sleep(1))
  • 如果它是“led2 = 1”,则启动另一个Python脚本,使设备无限期工作(而True:time.sleep(1))

  • if it was "led2=0", launch third Python script that stops the device
  • 如果它是“led2 = 0”,则启动第三个停止设备的Python脚本

My problem: I can correctly control my device with these scripts by web browser, for example:

我的问题:我可以通过网络浏览器使用这些脚本正确控制我的设备,例如:

For testing purposes, this is Apache2's access.log for led1 (=1 makes it work for 10 seconds, =0 does nothing more than print a line):

出于测试目的,这是针对led1的Apache2的access.log(= 1使其工作10秒,= 0只会打印一行):

192.168.0.10 - - [01/Mar/2018:10:42:01 +0100] "GET /?led1=1 HTTP/1.1" 200 411 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"

192.168.0.10 - - [01 / Mar / 2018:10:42:01 +0100]“GET /?led1 = 1 HTTP / 1.1”200 411“ - ”“Mozilla / 5.0(Windows NT 6.1; Win64; x64)AppleWebKit /537.36(KHTML,与Gecko一样)Chrome / 64.0.3282.186 Safari / 537.36“

(It starts working)

(它开始工作)

192.168.0.10 - - [01/Mar/2018:10:42:05 +0100] "GET /?led1=0 HTTP/1.1" 200 233 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"

192.168.0.10 - - [01 / Mar / 2018:10:42:05 +0100]“GET /?led1 = 0 HTTP / 1.1”200 233“ - ”“Mozilla / 5.0(Windows NT 6.1; Win64; x64)AppleWebKit /537.36(KHTML,与Gecko一样)Chrome / 64.0.3282.186 Safari / 537.36“

(No problem to get led1=0 just after 4 seconds and led1=1's script still works for few more secs)

(没有问题,在4秒后获得led1 = 0并且led1 = 1的脚本仍然可以工作几秒钟)

Unfortunately, I cannot do the same with my Android app. Here's same Apache's logs:

不幸的是,我的Android应用程序无法做到这一点。这是Apache的日志:

192.168.0.66 - - [01/Mar/2018:10:36:53 +0100] "GET /?led1=1 HTTP/1.1" 200 411 "-" "Dalvik/2.1.0 (Linux; U; Android 8.1.0; Nexus 5X Build/OPM3.171019.014)"

192.168.0.66 - - [01 / Mar / 2018:10:3​​6:53 +0100]“GET /?led1 = 1 HTTP / 1.1”200 411“ - ”“Dalvik / 2.1.0(Linux; U; Android 8.1。 0; Nexus 5X Build / OPM3.171019.014)“

(I make a "switch off" after 5 secs but...)

(我在5秒后做出“关闭”但......)

192.168.0.66 - - [01/Mar/2018:10:37:07 +0100] "GET /?led1=0 HTTP/1.1" 200 232 "-" "Dalvik/2.1.0 (Linux; U; Android 8.1.0; Nexus 5X Build/OPM3.171019.014)"

192.168.0.66 - [01 / Mar / 2018:10:3​​7:07 +0100]“GET /?led1 = 0 HTTP / 1.1”200 232“ - ”“Dalvik / 2.1.0(Linux; U; Android 8.1。 0; Nexus 5X Build / OPM3.171019.014)“

(It didn't! Notice 14 secs of difference (it launches about 3 secs and then work for 10 secs). It receives GET after led1=1's script finished its work).

(它没有!注意差异14秒(它启动大约3秒,然后工作10秒)。它在led1 = 1的脚本完成其工作后收到GET)。

This is a concern when script is working for 10 secs (led1) but a big problem when the script is working in infinite while loop (led2) - I cannot break it until first script stops (but it's while True loop so...)

当脚本工作10秒(led1)时,这是一个问题,但是当脚本在无限循环(led2)中工作时是一个大问题 - 我不能在第一个脚本停止之前打破它(但它是True循环所以......)

I was thinking about Python's subprocess.check_call() in second script to kill the first one but it didn't seem to help.

我在第二个脚本中考虑Python的subprocess.check_call()以杀死第一个但它似乎没有帮助。

Any ideas how to solve this?

任何想法如何解决这个问题?

1 个解决方案

#1


0  

Finally, I managed to do it. The idea of killing infinite while loop was correct but firstly I was thinking about doing it on Python scripts which was wrong.

最后,我设法做到了。杀死无限循环的想法是正确的,但首先我考虑在Python脚本上做错,这是错误的。

I noticed that those GET responses didn't appear in logs while local .php site was loading (due to while loop) so there was a need to abort current GET. And it can be done with Apache's httpcomponents.

我注意到,当本地.php站点加载时(由于while循环),那些GET响应没有出现在日志中,因此需要中止当前的GET。它可以用Apache的httpcomponents完成。

So after some modifications my code looks like this:

所以经过一些修改我的代码看起来像这样:

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
boolean flagToggle = true;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Switch switch_auto = findViewById(R.id.switch_auto);
    Switch switch_manual = findViewById(R.id.switch_manual);


    switch_auto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        HttpGet requestOn = new HttpGet();
        HttpGet requestOff = new HttpGet();

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            if (!flagToggle) {
                requestOn = new HttpGet();
                requestOff = new HttpGet();
                flagToggle = true;
            }

            Background_get switchOn = new Background_get(requestOn);
            Background_get switchOff = new Background_get(requestOff);

            if (isChecked) {
                switchOn.execute("led1=1");
            }
            else {
                requestOn.abort();
                switchOff.execute("led1=0");
                flagToggle = false;
            }

        }
    });

    switch_manual.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        HttpGet requestOn = new HttpGet();
        HttpGet requestOff = new HttpGet();

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            if (!flagToggle) {
                requestOn = new HttpGet();
                requestOff = new HttpGet();
                flagToggle = true;
            }

            Background_get switchOn = new Background_get(requestOn);
            Background_get switchOff = new Background_get(requestOff);

            if (isChecked) {
                switchOn.execute("led2=1");
            }
            else {
                requestOn.abort();
                switchOff.execute("led2=0");
                flagToggle = false;
            }

        }
    });
}

public class Background_get extends AsyncTask<String, Void, String> {

    private HttpGet mRequest = new HttpGet();

    public Background_get(HttpGet newRequest) {
        mRequest = newRequest;
    }

    public HttpGet getRequest() {
        return mRequest;
    }

    public void setRequest(HttpGet newRequest) {
        mRequest = newRequest;
    }

    @Override
    protected String doInBackground(String... params) {
        try {
            URI url = new URI("http://192.168.0.248/?" + params[0]);
            // HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            HttpClient httpclient = new DefaultHttpClient();
            getRequest().setURI(url);
            HttpResponse response = httpclient.execute(getRequest());

            BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuilder result = new StringBuilder();
            String inputLine;
            while ((inputLine = in.readLine()) != null)
                result.append(inputLine).append("\n");

            in.close();
            // response.close();
            // httpclient.close();

            return result.toString();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        return null;
    }
}
}

Things worth noting:

值得注意的事情:

  • for each toggle-switching it needs separate request (new HttpGet())
  • 对于每个切换切换,它需要单独的请求(新的HttpGet())

  • same with BackgroundGet (because it's AsyncTask)
  • 与BackgroundGet相同(因为它是AsyncTask)

  • flagToggle helps with multiple toggle-switching
  • flagToggle有助于多次切换切换

#1


0  

Finally, I managed to do it. The idea of killing infinite while loop was correct but firstly I was thinking about doing it on Python scripts which was wrong.

最后,我设法做到了。杀死无限循环的想法是正确的,但首先我考虑在Python脚本上做错,这是错误的。

I noticed that those GET responses didn't appear in logs while local .php site was loading (due to while loop) so there was a need to abort current GET. And it can be done with Apache's httpcomponents.

我注意到,当本地.php站点加载时(由于while循环),那些GET响应没有出现在日志中,因此需要中止当前的GET。它可以用Apache的httpcomponents完成。

So after some modifications my code looks like this:

所以经过一些修改我的代码看起来像这样:

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
boolean flagToggle = true;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Switch switch_auto = findViewById(R.id.switch_auto);
    Switch switch_manual = findViewById(R.id.switch_manual);


    switch_auto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        HttpGet requestOn = new HttpGet();
        HttpGet requestOff = new HttpGet();

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            if (!flagToggle) {
                requestOn = new HttpGet();
                requestOff = new HttpGet();
                flagToggle = true;
            }

            Background_get switchOn = new Background_get(requestOn);
            Background_get switchOff = new Background_get(requestOff);

            if (isChecked) {
                switchOn.execute("led1=1");
            }
            else {
                requestOn.abort();
                switchOff.execute("led1=0");
                flagToggle = false;
            }

        }
    });

    switch_manual.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        HttpGet requestOn = new HttpGet();
        HttpGet requestOff = new HttpGet();

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            if (!flagToggle) {
                requestOn = new HttpGet();
                requestOff = new HttpGet();
                flagToggle = true;
            }

            Background_get switchOn = new Background_get(requestOn);
            Background_get switchOff = new Background_get(requestOff);

            if (isChecked) {
                switchOn.execute("led2=1");
            }
            else {
                requestOn.abort();
                switchOff.execute("led2=0");
                flagToggle = false;
            }

        }
    });
}

public class Background_get extends AsyncTask<String, Void, String> {

    private HttpGet mRequest = new HttpGet();

    public Background_get(HttpGet newRequest) {
        mRequest = newRequest;
    }

    public HttpGet getRequest() {
        return mRequest;
    }

    public void setRequest(HttpGet newRequest) {
        mRequest = newRequest;
    }

    @Override
    protected String doInBackground(String... params) {
        try {
            URI url = new URI("http://192.168.0.248/?" + params[0]);
            // HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            HttpClient httpclient = new DefaultHttpClient();
            getRequest().setURI(url);
            HttpResponse response = httpclient.execute(getRequest());

            BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuilder result = new StringBuilder();
            String inputLine;
            while ((inputLine = in.readLine()) != null)
                result.append(inputLine).append("\n");

            in.close();
            // response.close();
            // httpclient.close();

            return result.toString();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        return null;
    }
}
}

Things worth noting:

值得注意的事情:

  • for each toggle-switching it needs separate request (new HttpGet())
  • 对于每个切换切换,它需要单独的请求(新的HttpGet())

  • same with BackgroundGet (because it's AsyncTask)
  • 与BackgroundGet相同(因为它是AsyncTask)

  • flagToggle helps with multiple toggle-switching
  • flagToggle有助于多次切换切换