Turn your WordPress site into a native android app. Certainly not talking about creating a webview and loading an URL with it. In conclusion almost all android apps for website’s are URL loaded inside a webview. Although the webview is present here but it’s different.Let me explain.Don’t have to,let me show it.
In fact this video is sufficient explanation. However for this project we are using an actual website, yes this website. Hence turning this site into an android app. So let’s begin, Mainly this project is divided in to three.
- WordPress part.
- Web-service Part.
- Android part.
WordPress Part
In the first place start by installing a plugin for Accelerated Mobile Pages (AMP), i am using this one. Then after installing the plugin you can check your amp url. As a result normal url for a post is “www.yourwebsite.com/post/” and it’s amp url is “www.yourwebsite.com/post/amp/”. Keep it in mind we will be using it later.
Web-service Part
In addition to WordPress part this gets posts details from your database to android. Since it’s the sole purpose of this part. While only focus of this projects are posts. You can modify it as you like, either posts or pages even both. On with the code, Like my all other posts this web-service is also written in php. While WordPress is written using php as the scripting language. Therefore making it much more practical to use php. Create a folder in your public_html so we can access it like this “www.yourwebsite.com/yourfolder/webservice.php”.
However some of the things are gathered using WordPress functions. Especially relevant things like database name password thumbnail etc. So sensitive information’s are therefore hidden. Another interesting thing is that this code is universal just copy and use. Also it work’s with any WordPress websites.
webservice.php
<?php /* * Post Template Used to call webservices Plugin Name: Android App logicchip Plugin URI: https://logicchip.com Description: A plugin for creating an android app of your site with realtime notifiaction and much more. For more information please visit out site the link is below. #happy coding ! Version: 1.0 Author: Mr. Akhil Ashok Author URI: https://logicchip.com License: GPL2 Email :akhilashok123@gmail.com,info@logicchip.com */ ini_set("memory_limit","128M"); // To load wordpress functions ,include file wp-load.php which is in root. $base_dir = dirname(dirname(__FILE__)); require_once($base_dir."/wp-load.php"); mysql_connect(DB_HOST, DB_USER, DB_PASSWORD); $conn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD,DB_NAME); if ($conn->connect_error) { //die("Connection failed: " . $conn->connect_error); } else{ //echo "Connected successfully "."<br />\r\n"; } $jsonDataBack = array(); $sql="SELECT wp_posts.ID,wp_posts.post_author,wp_posts.post_modified,wp_posts.guid,wp_users.display_name FROM wp_posts INNER JOIN wp_users WHERE wp_posts.post_status = 'publish' AND wp_posts.post_type = 'post' AND wp_users.ID = wp_posts.post_author ORDER BY wp_posts.post_date DESC "; $result = $conn->query($sql); if ($result->num_rows > 0) { for ($x=0; $row = $result->fetch_assoc(); $x++) { $jTempData = array(); $jTempData['id']=$row["ID"]; $jTempData['author']=$row["display_name"]; $jTempData['name']=get_the_title($row["ID"]); $jTempData['time']=$row["post_modified"]; //$jTempData['link']=$row["guid"]; $jTempData['link']=get_permalink($row["ID"]); if ( has_post_thumbnail($row["ID"])) { $jTempData['image']=$post_thumbnail_id = wp_get_attachment_url(get_post_thumbnail_id( $row["ID"] )); }else{ $jTempData['image']="none"; } setup_postdata($row["ID"]); $categories = get_the_category($row["ID"]); if ( ! empty( $categories ) ) { $jTempData['category']=esc_html( $categories[0]->name ); }else{ $jTempData['category']="none"; } $jTempData['content']=strip_tags(get_the_excerpt( $row["ID"])); $jsonDataBack[$x]=$jTempData; } }else{ $jTempData = array(); $jTempData['id']="0"; $jTempData['name']="none"; $jTempData['link']="none"; $jTempData['time']="none"; $jTempData['content']="none"; $jTempData['author']="none"; $jTempData['image']="none"; $jTempData['category']="none"; $jsonDataBack[0]=$jTempData; } $conn->close(); $outputArray['for_post'] = $jsonDataBack; print_r( json_encode($outputArray)); ?>
Android Part
Finally, Android part include fetching the information provided by the web-service. However the received information has a pattern and it’s repeating. Therefore we need to create a type for pattern and an adapter for repeating part. Also a list for displaying the adapter. Finally activity for reading the post.
Type
All the information received are of string type so it’s easy to work with. Class file for setting and getting information in this case string value’s. Another way is you can just sent it directly to the adapter, by using type complexity of the code is reduced.
WordPressType.java
public class WordPressType { String response_id,response_name,response_link,response_time,response_content,response_author,response_image,response_category; public WordPressType(){} public WordPressType(String response_id, String response_name, String response_link, String response_time, String response_content, String response_author, String response_image, String response_category){ this.response_id=response_id; this.response_name=response_name; this.response_link=response_link; this.response_time=response_time; this.response_content=response_content; this.response_author=response_author; this.response_image=response_image; this.response_category=response_category; } // in order to get string value public String getResponse_id(){return this.response_id;} public String getResponse_name(){return this.response_name;} public String getResponse_link(){return this.response_link;} public String getResponse_time(){return this.response_time;} public String getResponse_content(){return this.response_content;} public String getResponse_author(){return this.response_author;} public String getResponse_image(){return this.response_image;} public String getResponse_category(){return this.response_category;} // in order to set string value public void setResponse_id(String response_id){this.response_id=response_id;} public void setResponse_name(String response_name){this.response_name=response_name;} public void setResponse_link(String response_link){this.response_link=response_link;} public void setResponse_time(String response_time){this.response_time=response_time;} public void setResponse_content(String response_content){this.response_content=response_content;} public void setResponse_author(String response_author){this.response_author=response_author;} public void setResponse_image(String response_image){this.response_image=response_image;} public void setResponse_category(String response_category){this.response_category=response_category;} }
Before creating the adapter, See the images in the below image. Another class is created for caching those images to avoid using up the resources.
BitmapCache.java
public class BitmapCache extends LruCache<String, Bitmap> implements ImageCache { public static int getDefaultLruCacheSize() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 8; return cacheSize; } public BitmapCache(){ this(getDefaultLruCacheSize()); } public BitmapCache(int sizeInKiloBytes) { super(sizeInKiloBytes); } @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight() / 1024; } @Override public Bitmap getBitmap(String url) { return get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { put(url, bitmap); } }
Adapter
So the adapter extents RecyclerView.Adapter and it’s placed inside the RecyclerView that’s the list. Like any adapter both xml and java part is required. CardView looks cool so it’s created with card view.
wordpress_layout.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto" android:elevation="5dp" app:cardElevation="5dp"> // in order for getting the image <com.android.volley.toolbox.NetworkImageView android:id="@+id/idForImage" android:layout_gravity="top" android:scaleType="centerCrop" android:layout_width="match_parent" android:layout_height="160dp" android:src="@mipmap/ic_launcher"/> <View android:layout_marginTop="82dp" android:layout_width="match_parent" android:layout_height="80dp" android:alpha=".7" android:background="@color/colorPrimaryText"> </View> <LinearLayout android:layout_marginTop="80dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:maxLines="1" android:id="@+id/idForName" android:layout_marginTop="10dp" android:layout_marginLeft="16dp" android:textColor="@color/colorIcons" android:gravity="left" android:textSize="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Event Management Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs This is my web site, so do not override; let my WebView load the page"/> <TextView android:id="@+id/idForContent" android:layout_marginLeft="16dp" android:textColor="@color/colorDivider" android:maxLines="3" android:textAlignment="inherit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Event Management Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs This is my web site, so do not override; let my WebView load the page"/> <LinearLayout android:layout_marginLeft="16dp" android:layout_marginBottom="5dp" android:layout_marginTop="5dp" android:layout_marginRight="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <LinearLayout android:layout_weight="1" android:layout_gravity="left" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_weight="1" android:maxLines="1" android:id="@+id/idForTime" android:gravity="left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Event Management Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs This is my web site, so do not override; let my WebView load the page"/> <TextView android:layout_weight="1" android:maxLines="1" android:id="@+id/idForAuthor" android:gravity="left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Event Management Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs This is my web site, so do not override; let my WebView load the page"/> </LinearLayout> <LinearLayout android:layout_weight="1" android:layout_gravity="right" android:gravity="right" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/idForCategory" android:textStyle="bold" style="@style/Widget.AppCompat.Button.Borderless" android:textColor="@color/colorAccent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Event Management Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs This is my web site, so do not override; let my WebView load the page"/> </LinearLayout> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView>
Errors are common while coding, if “com.android.volley.toolbox.NetworkImageView” showing an error include volley in your dependencies .
dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.1.0' testCompile 'junit:junit:4.12' compile 'com.android.volley:volley:1.0.0' compile 'com.android.support:design:25.1.0' compile 'com.android.support:cardview-v7:25.1.0' compile 'com.android.support:palette-v7:25.1.0' compile 'com.android.support:recyclerview-v7:25.1.0' }
AdapterForWordPress.java
So the adapter contain ((WordPress)context).LoadPostView ();
, because adapter can’t directly call parent activity methods. However LoadPostView() is the method and WordPress is the parent activity.
public class AdapterForWordPress extends RecyclerView.Adapter<AdapterForWordPress.ViewHolder>{ private Activity context; private ArrayList<WordPressType> typeForPosts; private RequestQueue mRequestQueue; private ImageLoader mImageLoader; public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ // each data item is just a string in this case TextView idForName,idForContent,idForTime,idForAuthor; Button idForCategory; NetworkImageView idForImage; public ViewHolder(View v) { super(v); idForName=(TextView)v.findViewById(R.id.idForName); idForContent=(TextView)v.findViewById(R.id.idForContent); idForTime=(TextView)v.findViewById(R.id.idForTime); idForAuthor=(TextView)v.findViewById(R.id.idForAuthor); idForCategory=(Button) v.findViewById(R.id.idForCategory); idForImage=(NetworkImageView) v.findViewById(R.id.idForImage); v.setOnClickListener(this); } @Override public void onClick(View v) { ((WordPress)context).LoadPostView(typeForPosts.get(getAdapterPosition()).getResponse_link().toString()); } } public AdapterForWordPress(Activity context,ArrayList<WordPressType> typeForPosts){ this.context=context; this.typeForPosts = typeForPosts; } @Override public AdapterForWordPress.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.wordpress_layout, parent, false); // set the view's size, margins, paddings and layout parameters ViewHolder vh = new ViewHolder(view); return vh; } @Override public void onBindViewHolder(ViewHolder holder, int position) { //each data is inserted holder.idForName.setText(typeForPosts.get(position).getResponse_name().toString()); holder.idForContent.setText(typeForPosts.get(position).getResponse_content().toString()); holder.idForAuthor.setText(typeForPosts.get(position).getResponse_author().toString()); holder.idForCategory.setText(typeForPosts.get(position).getResponse_category().toString()); holder.idForImage.setImageUrl(typeForPosts.get(position).getResponse_image(), getImageLoader()); try { DateFormat inputFirstTime = new SimpleDateFormat(Constants.TEMPLATE_FOR_TIME); DateFormat inputSecondTime = new SimpleDateFormat(Constants.TEMPLATE_FOR_TIME); Date dateOne = new Date(); Date dateTwo = inputFirstTime.parse(inputSecondTime.format(dateOne)+" 00:00:00"); Date dateThree = inputFirstTime.parse(typeForPosts.get(position).getResponse_time().toString()); Calendar calenderOne = Calendar.getInstance(); calenderOne.setTime(dateThree); int monthOne = calenderOne.get(Calendar.MONTH); String month = getMonthForInt(monthOne); int hour =calenderOne.get(Calendar.HOUR); int day = calenderOne.get(Calendar.DAY_OF_MONTH); int year = calenderOne.get(Calendar.YEAR); if(dateTwo.compareTo(dateThree)>0){ holder.idForTime.setText(year+" "+month+" "+day); }else if(dateTwo.compareTo(dateThree)<0){ holder.idForTime.setText("Tomorrow "+year+" "+month+" "+day+" "+hour); }else if(dateTwo.compareTo(dateThree)==0) { //It's today not possible holder.idForTime.setText("Today "+year+" "+month+" "+day+" "+hour); }else { //How to get here ? holder.idForTime.setText("Error "+year+" "+month+" "+day+" "+hour); } }catch (Exception e){ ((WordPress)context).SnackBarMessage("Exception with date"); } } @Override public int getItemCount() { return typeForPosts.size(); } //month in string from number public String getMonthForInt(int num) { String month = "wrong"; DateFormatSymbols dfs = new DateFormatSymbols(); String[] months = dfs.getMonths(); if (num >= 0 && num <= 11 ) { month = months[num]; } return month; } //for requesting image file for network imageview public RequestQueue getRequestQueue() { if (mRequestQueue == null) { mRequestQueue = Volley.newRequestQueue(context); } return mRequestQueue; } public ImageLoader getImageLoader() { getRequestQueue(); if (mImageLoader == null) { mImageLoader = new ImageLoader(this.mRequestQueue,new BitmapCache()); } return this.mImageLoader; } }
Parent activity
So the Parent activity contains SwipeRefreshLayout + NestedScrollView + RecyclerView. As a result of combining this, user interface is more material design. However this includes swipe refresh option auto hiding of action bar, and CallingPage is the web-service method. Retrieved web-service information is changed to type and that is place inside an array-list is passed to adapter. Another method LoadPostView is for the launching activity to read the post along with the link of selected post.
public class WordPress extends AppCompatActivity { private RecyclerView recycleViewWordPress; private RecyclerView.Adapter mAdapter; private RequestQueue queue; private ArrayList<WordPressType> typeForPosts; private SwipeRefreshLayout swipeRefreshLayout; private CoordinatorLayout coordinatorLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wordpress); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); coordinatorLayout=(CoordinatorLayout)findViewById(R.id.coordinatorLayout); swipeRefreshLayout=(SwipeRefreshLayout)findViewById(R.id.swipeRefreshLayout); recycleViewWordPress=(RecyclerView)findViewById(R.id.recycleViewWordPress); recycleViewWordPress.setHasFixedSize(true); recycleViewWordPress.setLayoutManager(new LinearLayoutManager(this)); // specify an adapter (see also next example) recycleViewWordPress.setNestedScrollingEnabled(false); queue = Volley.newRequestQueue(this); swipeRefreshLayout.setRefreshing(true); CallingPage(); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { swipeRefreshLayout.setRefreshing(true); CallingPage(); } }); } public void SnackBarMessage(String message) { Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_LONG).setAction("Action", null).show(); } public void CallingPage(){ // Request a string response from the provided URL. StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.HOST_URL, new Response.Listener<String>() { @Override public void onResponse(String response) { // Display the first 500 characters of the response string. typeForPosts =new ArrayList<WordPressType>(); mAdapter = new AdapterForWordPress(WordPress.this,typeForPosts); recycleViewWordPress.setAdapter(mAdapter); try { JSONArray jsonResponse = new JSONObject(response).getJSONArray(Constants.RESPONSE); int i = jsonResponse.length(); for (int j = 0; j < i; j++) { WordPressType typeHints =new WordPressType(); JSONObject jsonChildNode = jsonResponse.getJSONObject(j); typeHints.setResponse_id(jsonChildNode.optString(Constants.RESPONSE_1.trim()).toString()); typeHints.setResponse_name(jsonChildNode.optString(Constants.RESPONSE_2.trim()).toString()); typeHints.setResponse_link(jsonChildNode.optString(Constants.RESPONSE_3.trim()).toString()); typeHints.setResponse_time(jsonChildNode.optString(Constants.RESPONSE_4.trim()).toString()); typeHints.setResponse_content(jsonChildNode.optString(Constants.RESPONSE_5.trim()).toString()); typeHints.setResponse_author(jsonChildNode.optString(Constants.RESPONSE_6.trim()).toString()); typeHints.setResponse_image(jsonChildNode.optString(Constants.RESPONSE_7.trim()).toString()); typeHints.setResponse_category(jsonChildNode.optString(Constants.RESPONSE_8.trim()).toString()); typeForPosts.add(typeHints); mAdapter.notifyDataSetChanged(); } swipeRefreshLayout.setRefreshing(false); } catch (JSONException e) { e.printStackTrace(); //Toast.makeText(WordPress.this,"frag a"+ e.getMessage(), Toast.LENGTH_LONG).show(); SnackBarMessage("JSON Exception"); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { //Toast.makeText(WordPress.this, "error 2", Toast.LENGTH_LONG).show(); SnackBarMessage("Volley Response Error"); } }); // Add the request to the RequestQueue. queue.add(stringRequest); } // next activity with specific link public void LoadPostView(String linkToOpen){ Intent intent =new Intent(WordPress.this,PostView.class); intent.putExtra("link",linkToOpen); startActivity(intent); } }
Also user interface for parent activity.
activity_wordpress.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:id="@+id/coordinatorLayout" tools:context="com.logicchip.wordpresstoandroid.WordPress"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="fill_vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="fill_vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.RecyclerView android:id="@+id/recycleViewWordPress" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.RecyclerView> </android.support.v4.widget.NestedScrollView> </android.support.v4.widget.SwipeRefreshLayout> </android.support.design.widget.CoordinatorLayout>
Reading post
So Remember the AMP mentioned above seems like we are using it now. First of all see the xml yes it contain’s a webview, then the class file PostView. In fact parameter passed from parent activity is changed like this, from “www.yourwebsite.com/post/” to “www.yourwebsite.com/post/amp/” . As a result of this operation webview loads the AMP version of your page. Because of class MyWebChromeClient inside PostView we can play videos in webview. Similarly MyBrowser class is for handling the clicks inside the webview along with some other functions like 404, 403 error’s etc.
activity_post_view.xml
<?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_post_view" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.logicchip.wordpresstoandroid.PostView"> <WebView android:id="@+id/idForLink" android:layout_width="match_parent" android:layout_height="match_parent"> </WebView> </RelativeLayout>
PostView.java
public class PostView extends AppCompatActivity { private WebView idForLink; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_post_view); idForLink = (WebView) findViewById(R.id.idForLink); idForLink.setWebViewClient(new MyBrowser()); idForLink.setWebChromeClient(new MyWebChromeClient()); idForLink.getSettings().setLoadsImagesAutomatically(true); idForLink.getSettings().setJavaScriptEnabled(true); idForLink.getSettings().setAppCacheEnabled(true); idForLink.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); String linkToOpen=getIntent().getStringExtra("link"); idForLink.loadUrl(linkToOpen+"amp/"); } public class MyWebChromeClient extends WebChromeClient { @Override public void onShowCustomView(View view, CustomViewCallback callback) { // TODO Auto-generated method stub super.onShowCustomView(view, callback); if (view instanceof FrameLayout) { FrameLayout frame = (FrameLayout) view; if (frame.getFocusedChild() instanceof VideoView) { VideoView video = (VideoView) frame.getFocusedChild(); frame.removeView(video); video.start(); } } } } private class MyBrowser extends WebViewClient { } }
Constants.java
In order to keep constant values for easy access.
public class Constants { public static String HOST_URL="http://yourwebsite.com/yourfolder/webservice.php"; public static String AMP="amp/"; public static String TEMPLATE_FOR_TIME = "yyyy-MM-dd"; public static String RESPONSE = "for_post"; public static String RESPONSE_1 = "id"; public static String RESPONSE_2 = "name"; public static String RESPONSE_3 = "link"; public static String RESPONSE_4 = "time"; public static String RESPONSE_5 = "content"; public static String RESPONSE_6 = "author"; public static String RESPONSE_7 = "image"; public static String RESPONSE_8 = "category"; }
Can get the Source Code of this Project?
yes you can. http://destyy.com/wEWIjO
Thank You!
I got error like this: The site is experiencing technical difficulties. And android app can’t load the data. What’s wrong?
Please include more information.
Your tutorial is very helpful, but unfortunately I’m facing a problem. Here is the code in webserver when i tried to access it.
{“for_post”:[{“id”:”0″,”name”:”none”,”link”:”none”,”time”:”none”,”content”:”none”,”author”:”none”,”image”:”none”,”category”:”none”}]}
There is an easier way now using wordpress api. Just try it out https://developer.wordpress.org/rest-api/