Android - 如何使用 PHP 从 MySQL 数据库中获取响应?

Posted

技术标签:

【中文标题】Android - 如何使用 PHP 从 MySQL 数据库中获取响应?【英文标题】:Android - How to get response from a MySQL Database using PHP? 【发布时间】:2017-03-01 03:16:39 【问题描述】:

大家好,

我在从我创建的 php 文件中获取响应时遇到问题。我正在使用 AsyncTask 发送带有 SELECT 语句的请求,然后将其传递到本地 mysql 数据库。我想将响应作为 JSON 字符串返回给 android,但我在 Android 中得到的只是一个空字符串。如果我在浏览器中尝试 PHP 文件,我会得到正确的输出。

这是我的代码示例:

我的 AsyncTask 类:

public class DBHelperAsyncTask extends AsyncTask<String, Void, String> 
    private static final String SHARED_PREFERENCE = SharedPreferencesEnum.SHARED_PREFERENCE.getText();
    SharedPreferences prefs;
    final protected Activity currentActivity;
    final protected URL link;
    final protected String fileName;
    private ProgressDialog dialog;

    public DBHelperAsyncTask(Activity currentActivity, URL link, String fileName) throws MalformedURLException
    
        this.currentActivity = currentActivity;
        this.fileName = fileName;
        this.link = new URL(String.format("http://0/1", link, fileName));
    

    public DBHelperAsyncTask(Activity currentActivity, URL link) throws MalformedURLException
    
        this.currentActivity = currentActivity;
        this.fileName = "uebergabe.php";
        this.link = new URL(String.format("http://0/1", link, fileName));
    

    public DBHelperAsyncTask(Activity currentActivity) throws MalformedURLException
    
        prefs = PreferenceManager.getDefaultSharedPreferences(currentActivity);
        this.currentActivity = currentActivity;
        this.fileName = "uebergabe.php";
        this.link = new URL(String.format("http://%s/%s", prefs.getString(SharedPreferencesEnum.HOST.getText(), "127.0.0.1"), prefs.getString(SharedPreferencesEnum.PFAD.getText(), fileName)));
        AlertDialog.Builder builder = new AlertDialog.Builder(currentActivity);
        builder.setTitle(link.toString());
        Dialog dialog = builder.create();
        dialog.show();


    

    @Override
    protected void onPreExecute() 
        dialog = new ProgressDialog(currentActivity);
        dialog.setIndeterminate(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.show();
        super.onPreExecute();
    

    @Override
    protected String doInBackground(String... params) 
        try 
            HttpURLConnection connection = (HttpURLConnection) link.openConnection();
            connection.setDoOutput(true);

            OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());

            if (params.length > 1) return null;
            else
            
                String data = URLEncoder.encode("Url", "UTF-8") + "=" + URLEncoder.encode(params[0], "UTF-8");
                writer.write(data);
                writer.flush();
                writer.close();
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder builder = new StringBuilder();
                String line = null;
                while((line = reader.readLine()) != null)
                
                    builder.append(line);
                    break;
                
                reader.close();
                return builder.toString().trim();
            

            //Aufruf bei Verbindungsunterbrechung
         catch (Exception e) 
            AlertDialog.Builder builder = new AlertDialog.Builder(currentActivity);
            builder.setTitle("Verbindungsfehler");
            builder.setMessage("Die Verbindung mit dem Server hat fehlergeschlagen");
            builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() 
                public void onClick(DialogInterface dialog, int id) 
                    dialog.dismiss();
                
            );


            Dialog dialog = builder.create();
            dialog.show();
            return null;
        
    

    @Override
    protected void onPostExecute(String result) 
        if(dialog.isShowing()) 
            dialog.dismiss();
        
    

    //Konventiert ein json String zum ContentValues
    public ContentValues jsonToContentValues(String jsonString) 
        ContentValues output = new ContentValues();
        JSONObject parser = new JSONObject();
        try 
            if (jsonString == null) throw new JSONException(null);
            parser = new JSONObject(jsonString);
            Iterator<String> iterator = parser.keys();
            JSONArray array = parser.names();
            while (iterator.hasNext()) output.put(iterator.next(), array.getString(output.size()));
         catch (JSONException e) 
            AlertDialog.Builder builder = new AlertDialog.Builder(currentActivity);
            builder.setTitle("Daten-Konvertierungsfehler");
            builder.setMessage("Die Daten konnten nicht richtig gelesen werden\n" + jsonString);
            builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() 
                public void onClick(DialogInterface dialog, int id) 
                    dialog.dismiss();
                
            );


            Dialog dialog = builder.create();
            dialog.show();
            return null;
         finally 
            return output;
        
    


我的主要活动:

public class MainActivity extends ActionBarActivity 
    private static final String SHARED_PREFERENCE = SharedPreferencesEnum.SHARED_PREFERENCE.getText();
    ContentValues result = null;
    private EditText benutzerEditText;
    private EditText passwortEditText;
    private TextView anmeldenTextView;
    DBHelperAsyncTask asyncTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        SharedPreferences prefs = getSharedPreferences(SHARED_PREFERENCE, MODE_PRIVATE);

        String benutzer = prefs.getString(SharedPreferencesEnum.BENUTZER.getText(), null);
        if(benutzer == null) 
            setContentView(R.layout.login_maske);
            benutzerEditText = (EditText) findViewById(R.id.benutzerNameEditText);
            passwortEditText = (EditText) findViewById(R.id.benutzerPasswortEditText);
        
        else
            setContentView(R.layout.activity_main);
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        getMenuInflater().inflate(R.menu.activity_main_menu, menu);
        return true;
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        Intent intent = null;
        switch(item.getItemId()) 
            case R.id.settings_scan:
                intent = new Intent(Intent.ACTION_VIEW);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                intent.setClassName(this, PreferencesActivity.class.getName());
                break;
            case R.id.settings:
                intent = new Intent(Intent.ACTION_VIEW);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                intent.setClassName(this, SettingsActivity.class.getName());
                break;
        
        startActivity(intent);
        return super.onOptionsItemSelected(item);
    
    public void onAnmeldenClick(View view) throws MalformedURLException, InterruptedException, ExecutionException
    
        asyncTask = new DBHelperAsyncTask(this);
        String sql = String.format("SELECT IDBenutzer, Passwort FROM benutzer where Benutzername = '0'", benutzerEditText.getText().toString());
        result = asyncTask.jsonToContentValues(asyncTask.execute(sql).get());

        anmeldenTextView = (TextView) findViewById(R.id.anmeldenTextView);
        anmeldenTextView.setText(result.toString());
        /*
        String passwort = result.getAsString("Passwort");
        if(passwortEditText.getText().toString() == passwort)
        
            SharedPreferences prefs = getSharedPreferences(SHARED_PREFERENCE, MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            editor.putInt(SharedPreferencesEnum.BENUTZER_ID.getText(), result.getAsInteger("IDBenutzer"));
            editor.putString(SharedPreferencesEnum.BENUTZER.getText(), result.getAsString("Benutzer"));
        */
    


    public void onPruefenClick(View view) 
        Intent intent = new Intent("com.google.zxing.client.android.SCAN");
        startActivityForResult(intent, 0);
    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        if (requestCode == 0) 
            if (resultCode == RESULT_OK) 

                String contents = data.getStringExtra("SCAN_RESULT");
                AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).create();
                dialog.setTitle("Barcode");
                dialog.setMessage(contents);
                dialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                        new DialogInterface.OnClickListener()
                            public void onClick(DialogInterface dialog, int which) 
                                dialog.dismiss();
                            
                        );
                dialog.show();
                // Handle successful scan

            
        
    


    public void onAbmeldenClick(View view)
    
        SharedPreferences prefs = getSharedPreferences(SHARED_PREFERENCE, MODE_PRIVATE);
        SharedPreferences.Editor editor = prefs.edit();
        editor.remove(SharedPreferencesEnum.BENUTZER.getText());
        editor.remove(SharedPreferencesEnum.BENUTZER_ID.getText());
        editor.commit();
        restartActivity(this);
    

    private void restartActivity(Activity restartActivity)
    
        Intent intent = new Intent();
        intent.setClass(restartActivity, restartActivity.getClass());
        restartActivity.startActivity(intent);
        restartActivity.finish();
    

还有 PHP 文件:

    <?php

    $link = "localhost";
    $user = "root";
    $password = "";
    $dbname = "ProjektZ";

    $conn = mysqli_connect($link,$user,$password,$dbname);

    if ($conn->connect_error) 
                #Script verlassen
                die("Connection failed");
             
            $sql = $_POST['Url']; #sql-anfrage erstellen
            $myArray = array();
            if ($result = $conn->query($sql)) #sql-anfrage ausführen und in Variable speichern
            if(is_object($result))
            
                while($row = $result->fetch_array(MYSQL_ASSOC)) $myArray[] = $row;
                header('Content-type: application/json');
                echo json_encode($myArray);     
            
            mysqli_close($conn);
?>

我读到的所有地方都表明 echo json_encode($myArray) 应该是将响应传回应用程序的正确方法。

【问题讨论】:

IMO 你不应该在客户端(Android)端进行用户验证。您应该在服务器(PHP)端执行此操作。并请散列密码。好像您以纯文本形式存储它们。这里的整个登录过程对我来说似乎很容易受到攻击。 这是一种基本方法,只是为了测试它是否能正常工作。诸如 Encrypiton 之类的其他东西将随之而来。 【参考方案1】:

我认为您应该考虑使用REST 方法从数据库中获取数据。这对 Android 应用程序来说会更容易,也更安全(SQL 注入是代码中的风险)。 您可以使用 Symfony 之类的 CMS(或您喜欢的任何其他 CMS)来帮助您构建服务器端。

【讨论】:

这是否与例如冲突? XAMPP之类的?更重要的是,这与简单地使用 Apache 和 HTTP-Requests 有很大不同吗? 我看到您已经在使用 XAMP 环境,所以这是一个简单的步骤。不,没有什么不同,它比手动完成所有这些操作更简单、更安全、更快捷。 如果要更改为 REST,您有什么建议可以从哪里开始。使用 REST 需要在服务器上安装除 XAMPP 以外的任何其他设备吗? 您可以阅读本教程:symfony.com/doc/current/bundles/FOSRestBundle/index.html。 XAMP 正是您所需要的。 感谢您的帮助。我去看看。

以上是关于Android - 如何使用 PHP 从 MySQL 数据库中获取响应?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 asynctask 将图像从 android 上传到 php

如何将数据从填充的下拉 php 数据库发布到另一个脚本?

如何从 PHP 网站向 iOS 和 Android 发送推送通知?

如何从php检索变量到android?

如何从android的浏览器运行php脚本? [关闭]

如何将json从android发送到php?