2015-08-27 33 views
0

我開發一個Android應用程序使用改裝訪問REST API在PHP和MySQL開發的Android使用REST API。使用改造

的API是在PHP和MySQL。

的PHP文件如下:

的index.php

<?php 
$servername = "localhost"; 
$username = "root"; 
$password = ""; 
$dbname = "bookdb"; 
// Create connection 
$conn = new mysqli($servername, $username, $password, $dbname); 

// Check connection 
if ($conn->connect_error) { 
    die("Connection failed: " . $conn->connect_error); 
} 
$sql = "SELECT * FROM books"; 
$result = $conn->query($sql); 

if ($result->num_rows > 0) { 
    echo '{"books":['; 

     $first = true; 
     while($row=$result->fetch_assoc()){ 
     // cast results to specific data types 

      if($first) { 
       $first = false; 
      } else { 
       echo ','; 
      } 
      echo json_encode($row); 
     } 
     echo ']}'; 
} else { 
    echo "0 results"; 
} 
$conn->close(); 
?> 

,當我訪問它在瀏覽器中我得到以下結果使用http://localhost/books

{"books":[{"author":"Ash Maurya","categories":"process","lastcheckedout":null,"lastcheckedoutby":null,"publisher":"O'REILLY","title":"Running Lean","url":"\/books\/1","book_id":"1"}]} 

是哪個預期產出。

現在,我嘗試在Android中使用改型來使用它:

BookListActivity.java

package com.example.android.taskapp; 

import android.content.Context; 
import android.database.Cursor; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.CursorAdapter; 
import android.widget.ListView; 
import android.widget.SimpleAdapter; 
import android.widget.SimpleCursorAdapter; 

import com.example.android.taskapp.api.ApiInterface; 
import com.example.android.taskapp.model.Book; 
import com.google.gson.Gson; 
import com.google.gson.reflect.TypeToken; 

import java.lang.reflect.Field; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Objects; 

import retrofit.Callback; 
import retrofit.RestAdapter; 
import retrofit.RetrofitError; 
import retrofit.client.Response; 

public class BookListActivity extends AppCompatActivity { 

static final String API_URL = "http://192.168.0.104:8080/books"; 
ListView books_listview; 
RestAdapter restAdapter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_book_list); 
    books_listview = (ListView) findViewById(R.id.books_listview); 

    restAdapter = new RestAdapter.Builder().setEndpoint(API_URL).build(); 
    ApiInterface methods = restAdapter.create(ApiInterface.class); 

    Callback cb = new Callback() { 
     @Override 
     public void success(Object o, Response response) { 
      List<Book> books = (List<Book>) o; 
      //Log.v("BookListActivity", booksString); 
      //TypeToken<List<Book>> token = new TypeToken<List<Book>>() {}; 
      //List<Book> books = new Gson().fromJson(booksString, token.getType()); 

      List<HashMap<String,Object>> bookMapList = new ArrayList<>(); 
      for(Book b: books){ 
       HashMap<String, Object> bookmap = new HashMap<>(); 

       try { 
        bookmap.put(b.getClass().getField("author").getName(),b.getAuthor()); 
        bookmap.put(b.getClass().getField("categories").getName(),b.getCategories()); 
        bookmap.put(b.getClass().getField("lastCheckedOut").getName(),b.getLastCheckedOut()); 
        bookmap.put(b.getClass().getField("lastCheckedOutBy").getName(),b.getLastCheckedOutBy()); 
        bookmap.put(b.getClass().getField("publisher").getName(),b.getPublisher()); 
        bookmap.put(b.getClass().getField("title").getName(),b.getTitle()); 
        bookmap.put(b.getClass().getField("url").getName(),b.getUrl()); 
        bookMapList.add(bookmap); 
       } catch (NoSuchFieldException e) { 
        e.printStackTrace(); 
       } 
      } 
      SimpleAdapter adapter = new SimpleAdapter(getApplication(), bookMapList, R.layout.list_item_book, 
        new String [] {"title", "author"},new int [] {R.id.book_title, R.id.book_author}); 

      books_listview.setAdapter(adapter); 
     } 

     @Override 
     public void failure(RetrofitError error) { 
      Log.e("BookListActivity", error.getMessage() +"\n"+ error.getStackTrace()); 
      error.printStackTrace(); 
     } 
    }; 
    methods.getBooks(cb); 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_book_list, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 
} 

這裏是我ApiInterface類:

ApiInterface.java

package com.example.android.taskapp.api; 

import com.example.android.taskapp.model.Book; 

import java.util.List; 

import retrofit.Callback; 
import retrofit.client.Response; 
import retrofit.http.GET; 
import retrofit.http.Path; 

/** 
* Created by aagam shah on 8/25/2015. 
*/ 
public interface ApiInterface { 

    @GET("/index.php") 
    void getBooks(Callback<List<Book>> cb); 
} 

我執行後出現以下錯誤:

com.example.android.taskapp E/BookListActivity﹕ socket failed: EACCES (Permission denied) 
retrofit.RetrofitError: socket failed: EACCES (Permission denied) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:395) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at retrofit.CallbackRunnable.run(CallbackRunnable.java:42) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at retrofit.Platform$Android$2$1.run(Platform.java:142) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ at java.lang.Thread.run(Thread.java:841) 
08-27 12:59:02.855 10942-10942/com.example.android.taskapp W/System.err﹕ Caused by: java.net.SocketException: socket failed: EACCES (Permission denied) 
08-27 12:59:02.865  822-856/? I/ActivityManager﹕ Displayed com.example.android.taskapp/.BookListActivity: +541ms 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at libcore.io.IoBridge.socket(IoBridge.java:587) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at java.net.PlainSocketImpl.create(PlainSocketImpl.java:202) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at java.net.Socket.checkOpenAndCreate(Socket.java:668) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at java.net.Socket.setSoTimeout(Socket.java:523) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.internal.http.SocketConnector.connectRawSocket(SocketConnector.java:159) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.internal.http.SocketConnector.connectCleartext(SocketConnector.java:67) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.Connection.connect(Connection.java:152) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:185) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.Call.getResponse(Call.java:273) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:230) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:201) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at com.squareup.okhttp.Call.execute(Call.java:81) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at retrofit.client.OkClient.execute(OkClient.java:53) 
08-27 12:59:02.865 10942-10942/com.example.android.taskapp W/System.err﹕ at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326) 

methods.getBooks(cb);這條線。

誰能請告訴我,我缺少什麼呢?

我已經嘗試尋找類似的答案,但他們都沒有幫助。

我還包括在應用節點上述清單所有必要的權限。

非常感謝您的幫助。

回答

0

挖這麼多在這裏和那裏後,我終於找到了解決我的問題:

,我錯過了最重要的事情是這樣的:

<uses-permission android:name="ANDROID.PERMISSION.INTERNET" /> 

應該

<uses-permission android:name="android.permission.INTERNET" /> 

其他文件有一些小的變化:

BookListActivi ty.java

public class BookListActivity extends AppCompatActivity { 

static final String API_URL = "http://192.168.0.104/books"; 
ListView books_listview; 
RestAdapter restAdapter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_book_list); 
    books_listview = (ListView) findViewById(R.id.books_listview); 

    OkHttpClient mOkHttpClient = new OkHttpClient(); 
    mOkHttpClient.setConnectTimeout(15000,TimeUnit.MILLISECONDS); 
    mOkHttpClient.setReadTimeout(15000,TimeUnit.MILLISECONDS); 

    restAdapter = new RestAdapter.Builder() 
      .setEndpoint(API_URL) 
      .setClient(new OkClient(mOkHttpClient)) 
      .setLogLevel(RestAdapter.LogLevel.FULL) 
      .build(); 
    ApiInterface methods = restAdapter.create(ApiInterface.class); 

    Callback<List<Book>> cb = new Callback<List<Book>>() { 
     @Override 
     public void success(List<Book> books, Response response) { 
      //Log.v("BookListActivity", booksString); 
      //TypeToken<List<Book>> token = new TypeToken<List<Book>>() {}; 
      //List<Book> books = new Gson().fromJson(booksString, token.getType()); 

      List<HashMap<String,Object>> bookMapList = new ArrayList<>(); 
      for(Book b: books){ 
       HashMap<String, Object> bookmap = new HashMap<>(); 

       try { 

        bookmap.put(b.getClass().getField("book_id").getName(),b.getBook_id()); 
        bookmap.put(b.getClass().getField("author").getName(),b.getAuthor()); 
        bookmap.put(b.getClass().getField("categories").getName(),b.getCategories()); 
        bookmap.put(b.getClass().getField("lastCheckedOut").getName(),b.getLastCheckedOut()); 
        bookmap.put(b.getClass().getField("lastCheckedOutBy").getName(),b.getLastCheckedOutBy()); 
        bookmap.put(b.getClass().getField("publisher").getName(),b.getPublisher()); 
        bookmap.put(b.getClass().getField("title").getName(),b.getTitle()); 
        bookmap.put(b.getClass().getField("url").getName(),b.getUrl()); 
        bookMapList.add(bookmap); 
       } catch (NoSuchFieldException e) { 
        e.printStackTrace(); 
       } 
      } 
      SimpleAdapter adapter = new SimpleAdapter(getApplication(), bookMapList, R.layout.list_item_book, 
        new String [] {"title", "author"},new int [] {R.id.book_title, R.id.book_author}); 

      books_listview.setAdapter(adapter); 
     } 

     @Override 
     public void failure(RetrofitError error) { 
      Log.e("BookListActivity", error.getMessage() +"\n"+ error.getStackTrace()); 
      error.printStackTrace(); 
     } 
    }; 
    methods.getBooks(cb); 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_book_list, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 
} 

和index.php文件

<?php 
$servername = "localhost"; 
$username = "root"; 
$password = ""; 
$dbname = "bookdb"; 
// Create connection 
$conn = new mysqli($servername, $username, $password, $dbname); 

// Check connection 
if ($conn->connect_error) { 
    die("Connection failed: " . $conn->connect_error); 
} 
$sql = "SELECT * FROM books"; 
$result = $conn->query($sql); 

if ($result->num_rows > 0) { 
    echo '['; 

     $first = true; 
     while($row=$result->fetch_assoc()){ 
     // cast results to specific data types 

      if($first) { 
       $first = false; 
      } else { 
       echo ','; 
      } 
      echo json_encode($row); 
     } 
     echo ']'; 
} else { 
    echo "0 results"; 
} 
$conn->close(); 
?> 

而且也把你的防火牆關閉。 Fellas!祝你有美好的一天! :)