I've been trying for a little bit now to just get my app launching again. I modified how I pulled bitcoin price data to allow for user preferences. However since doing this I get a NullPointerException from my TextView currentPriceDisplay elements method.currentPriceDisplay.setText(getmBitcoinPrice());
I have modified values throughout my code to prevent this variable from ever actually being null, I've also checked my nav_header_main.xml file to see if I was referencing the right TextView I am. So at this point pretty stumped and I have to go to the day job. If you can have a look at my code and see if you notice anything that would be great.
MainActivity:
package com.instacoind.www.coind;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Set;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private Double mBitcoinPrice = 0.0;
public Double getmBitcoinPrice(){
return mBitcoinPrice;
}
public void setmBitcoinPrice(Double price){
this.mBitcoinPrice = price;
}
private Double mBitcoinPriceOld = 0.0;
public Double getmBitcoinPriceOld(){
return mBitcoinPriceOld;
}
public void setmBitcoinPriceOld(Double price){
this.mBitcoinPriceOld = price;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mBitcoinPrice != 0.0) {
Snackbar.make(view, "Last Change: " + priceChange(), Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}else{
Snackbar.make(view, "SYNC FAILED ERROR::01", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, 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) {
Intent start_settings = new Intent(this, SettingsActivity.class);
startActivity(start_settings);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onStart(){
super.onStart();
updatePrice();
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void updatePrice(){
GetBitcoinPrice worker = new GetBitcoinPrice();
worker.execute(getPrefFiat(this), getPrefPriceIndex(this));
refreshPriceDisplays();
}
public static String getPrefFiat(Context context){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getString(context.getString(R.string.pref_currency_key),
context.getString(R.string.pref_currency_def));
}
public static String getPrefPriceIndex(Context context){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getString(context.getString(R.string.pref_source_key),
context.getString(R.string.pref_source_default));
}
public String priceChange(){
Double past = getmBitcoinPriceOld();
Double pres = getmBitcoinPrice();
Double change = 0.0;
String fin = "price_change";
if(past != null){
if(pres >= past){
change = pres - past;
fin = "+ " + Double.toString(change);
}else if(pres <= past){
change = past - pres;
fin = "- " + Double.toString(change);
}
}else{
setmBitcoinPriceOld(getmBitcoinPrice());
}
return fin;
}
public void refreshPriceDisplays(){
TextView PriceDisplay = (TextView) findViewById(R.id.current_price_display);
String error = "No Bitcoin Price";
try {
Log.v("RefreshPriceDisplays", "mBitcoinPrice: " + Double.toString(getmBitcoinPrice()));
PriceDisplay.setText(Double.toString(getmBitcoinPrice()));
}catch(NullPointerException e) {
Log.v("RefreshPriceDisplays", "mBitcoinPrice NULL");
PriceDisplay.setText("ERR");
}
}
private class GetBitcoinPrice extends AsyncTask<String, Void, Double> {
public String mPrefFiat;
public String mPrefIndex;
protected Double doInBackground(String... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String bitcoinJsonStr = null;
this.mPrefFiat = params[0];
this.mPrefIndex = params[1];
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
URL url = new URL(buildUrl(this.mPrefFiat,this.mPrefIndex));
// Create the request to Index Source, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
bitcoinJsonStr = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
bitcoinJsonStr = null;
}
bitcoinJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("GetBitcoinPrice", "Error ", e);
// If the code didn't successfully get the price index data, there's no point in attemping
// to parse it.
bitcoinJsonStr = null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("GetBitcoinPrice", "Error closing stream", e);
}
}
}
if(this.mPrefIndex == "https://api.coindesk.com/v1/bpi/currentprice.json")
return parseCoindesk(bitcoinJsonStr);
else if (this.mPrefIndex == "https://api.coinbase.com/v2/prices/spot?currency=")
return parseCoinbase(bitcoinJsonStr);
else if (this.mPrefIndex == "https://www.okcoin.com/api/v1/ticker.do?symbol=")
return parseOkcoin(bitcoinJsonStr);
else if (this.mPrefIndex == "https://cex.io/api/ticker/BTC/")
return parseCex(bitcoinJsonStr);
else
return 0.0;
}
private Double parseCex(String bitcoinJsonStr){
Double price = 0.0;
try {
JSONObject obj = new JSONObject(bitcoinJsonStr);
price = obj.getDouble("bid");
Log.v("ConvertPriceStr", "Current Price is " + Double.toString(price));
if (price == null){
Log.e("CEXParsing", "Parsed to Null");
}
}catch (JSONException x){
Log.e("ConvertPriceStr", "Error Parsing bitcoinJsonStr");
}
return price;
}
private Double parseCoindesk(String bitcoinJsonStr){
Double price = 0.0;
try {
JSONObject obj = new JSONObject(bitcoinJsonStr);
JSONObject bpi = obj.getJSONObject("bpi");
JSONObject usd = bpi.getJSONObject("USD");
price = usd.getDouble("rate_float");
Log.v("ConvertPriceStr", "Current Price is " + Double.toString(price));
}catch (JSONException x){
Log.e("ConvertPriceStr", "Error Parsing bitcoinJsonStr");
}
return price;
}
private Double parseCoinbase(String bitcoinJsonStr){
Double price = 0.0;
try{
JSONObject obj = new JSONObject(bitcoinJsonStr);
JSONObject bpi = obj.getJSONObject("data");
price = bpi.getDouble("amount");
Log.v("ParseCoinbase", "Current Price is " + Double.toString(price));
}catch(JSONException e){
Log.e("ParseCoinbase", "Error Parsing bitcoinJsonStr");
}
return price;
}
private Double parseOkcoin(String bitcoinJsonStr){
Double price = 0.0;
try{
JSONObject obj = new JSONObject(bitcoinJsonStr);
JSONObject bpi = obj.getJSONObject("ticker");
price = bpi.getDouble("buy");
Log.v("ParseOkCoin", "Current Price is " + Double.toString(price));
}catch(JSONException e){
Log.e("ParseOkCoin", "Error Parsing bitcoinJsonStr");
}
return price;
}
private String buildUrl(String prefFiat, String prefIndex){
String url = null;
try {
if (prefIndex == "https://api.coinbase.com/v2/prices/spot?currency=") {
url = prefIndex + prefFiat;
} else if (prefIndex == "https://api.coindesk.com/v1/bpi/currentprice.json") {
url = prefIndex + prefFiat;
} else if (prefIndex == "https://www.okcoin.com/api/v1/ticker.do?symbol=") {
String modFiat;
modFiat = "btc_" + prefFiat;
url = prefIndex + modFiat;
} else if (prefIndex == "https://cex.io/api/ticker/BTC/") {
String modFiat;
modFiat = prefIndex + prefFiat;
url = modFiat;
} else {
url = "https://api.coindesk.com/v1/bpi/currentprice.json";
}
}catch(NullPointerException e){
Log.e("URL Builder", "Error Constructing Proper URL", e);
}
return url;
}
protected void onPostExecute(Double result){
setmBitcoinPriceOld(getmBitcoinPrice());
setmBitcoinPrice(result);
}
}
}
XML Files:
activity_main.xml:
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
app_bar_main.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"
tools:context="com.instacoind.www.coind.MainActivity">
<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:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/refresh_60_60" />
</android.support.design.widget.CoordinatorLayout>
content_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.instacoind.www.coind.MainActivity"
tools:showIn="#layout/app_bar_main">
</RelativeLayout>
nav_header_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/nav_header_height"
android:background="#drawable/side_nav_bar"
android:gravity="bottom"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:theme="#style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="#+id/coin_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:paddingTop="#dimen/nav_header_vertical_spacing"
android:src="#drawable/bitcoin_80_80"
android:contentDescription="#string/coin_content_description"/>
<TextView
android:id="#+id/bpi_source_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="#dimen/nav_header_vertical_spacing"
android:text="BPI_Source"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:textAppearance="#style/TextAppearance.AppCompat.Body1" />
<TextView
android:id="#+id/def_currency_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:layout_toRightOf="#+id/bpi_source_display"
android:layout_toEndOf="#+id/bpi_source_display"
android:layout_alignParentBottom="true"
android:text="DEF_Currency" />
<TextView
android:id="#+id/current_price_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="40dp"
android:paddingStart="80dp"
android:paddingLeft="80dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="#+id/coin_display"
android:textAppearance="#style/TextAppearance.AppCompat.Headline"/>
</RelativeLayout>
I think the problem comes from these four method:
parseCoindesk,parseCoinbase,parseCex,parseOkcoin
In each of these(parseCex for example):
if (price == null){
Log.e("CEXParsing", "Parsed to Null");// You just print a Log!
}
}catch (JSONException x){
Log.e("ConvertPriceStr", "Error Parsing bitcoinJsonStr");
}
return price;//when price is null it can still return!
}
so, you should try to return like this:
return price == null ? 0.0 : price;
Ok, way longer than I thought it would take till I could actually sit down and work on this again. Apologies for dragging my heels, I have fixed the problem of the crash.
It occurred because I was calling my refreshPriceDisplays() method before the onCreate/AsyncTask was finished. Once I moved refreshPriceDisplays() into my onPostExecute everything went great.
And as far as the first answer to this question you raised some good points about my logic and they have been addressed as well thank you so much for your inputs!
Related
I'm writing an app and it has a part which, on button click, scans for Bluetooth devices and shows them in a ListView. It works fine, but i need it to show only devices starting with a word in the name, for example: "MyArduino/123", so I need it to look for the "MyArduino/" part in device names and only show those that have it.
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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.test.app.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/title"
android:textSize="20sp"
android:textAlignment="center"
android:text="#string/title"
android:gravity="center_horizontal" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/title"
android:text="#string/bt_menu"
android:background="#color/button"
android:onClick="showBt"
android:id="#+id/to_bt_menu"
android:layout_margin="10sp"
tools:ignore="UsingOnClickInXml" />
<Button
android:id="#+id/to_vars_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/title"
android:layout_marginLeft="10sp"
android:layout_marginStart="10sp"
android:layout_toEndOf="#id/to_bt_menu"
android:layout_toRightOf="#id/to_bt_menu"
android:onClick="showVars"
android:text="#string/vars_menu"
android:background="#color/button"
android:layout_margin="10sp"
tools:ignore="UsingOnClickInXml" />
<TextView
android:id="#+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/to_bt_menu"
android:visibility="gone"
android:ellipsize="end"
android:maxLines="1"
android:text="#string/status"
android:textStyle="bold" />
<TextView
android:id="#+id/bluetooth_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/to_bt_menu"
android:visibility="gone"
android:layout_toEndOf="#id/status"
android:layout_toRightOf="#id/status"
android:layout_marginLeft="20sp"
android:layout_marginStart="20sp"
android:ellipsize="end"
android:maxLines="1"
android:text="#string/bluetooth_status" />
<Button
android:id="#+id/scan"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="#id/bluetooth_status"
android:layout_margin="10sp"
android:visibility="gone"
android:text="#string/bluetooth_on"
android:background="#color/button" />
<Button
android:id="#+id/off"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="#id/bluetooth_status"
android:layout_margin="10sp"
android:visibility="gone"
android:layout_toRightOf="#id/scan"
android:layout_toEndOf="#id/scan"
android:background="#color/button"
android:text="#string/bluetooth_off" />
<Button
android:id="#+id/paired_btn"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="#id/off"
android:layout_margin="10sp"
android:visibility="gone"
android:text="#string/show_paired_devices"
android:background="#color/button" />
<Button
android:id="#+id/discover"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="#id/off"
android:layout_margin="10sp"
android:visibility="gone"
android:layout_toEndOf="#+id/paired_btn"
android:layout_toRightOf="#id/paired_btn"
android:text="#string/discover_new_devices"
android:background="#color/button" />
<ListView
android:id="#+id/devices_list_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/discover"
android:visibility="gone"
android:choiceMode="singleChoice" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20sp"
android:onClick="reqVars"
android:text="#string/req_btn"
android:layout_below="#id/user_edit"
android:visibility="gone"
android:id="#+id/req_btn"
android:layout_margin="10sp"
android:background="#color/button" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/to_vars_menu"
android:layout_margin="10sp"
android:visibility="gone"
android:id="#+id/user_edit"
android:hint="#string/hint_edit"
tools:ignore="TextFields"/>
<Button
android:id="#+id/send_edit_btn"
android:layout_margin="10sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/user_edit"
android:visibility="gone"
android:layout_marginStart="20sp"
android:layout_marginLeft="20sp"
android:layout_marginTop="20sp"
android:layout_toEndOf="#+id/req_btn"
android:layout_toRightOf="#+id/req_btn"
android:onClick="editVar"
android:text="#string/send_edit_btn"
android:background="#color/button" />
<ListView
android:layout_below="#id/req_btn"
android:visibility="gone"
android:id="#+id/vars"
android:choiceMode="singleChoice"
android:listSelector="#color/list"
android:layout_width="300sp"
android:layout_height="wrap_content" />
</RelativeLayout>
MainActivity:
package com.test.app;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private final String TAG = MainActivity.class.getSimpleName();
private static final UUID BT_MODULE_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // "random" unique identifier
// #defines for identifying shared types between calling functions
private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names
public final static int MESSAGE_READ = 2; // used in bluetooth handler to identify message update
private final static int CONNECTING_STATUS = 3; // used in bluetooth handler to identify message status
// GUI Components
private TextView mBluetoothStatus;
private Button mScanBtn;
private Button mOffBtn;
private Button mListPairedDevicesBtn;
private Button mDiscoverBtn;
private ListView mDevicesListView;
private TextView mStatus;
private EditText mUserEdit;
private Button mReqBtn;
private Button mSendEdit;
private ListView mVars;
private String mSelecVar;
private String mMessage;
private BluetoothAdapter mBTAdapter;
private Set<BluetoothDevice> mPairedDevices;
private ArrayList<BluetoothDevice> mBTDevices;
private ArrayAdapter<String> mBTArrayAdapter;
private Handler mHandler; // Our main handler that will receive callback notifications
private ConnectedThread mConnectedThread; // bluetooth background worker thread to send and receive data
private BluetoothSocket mBTSocket = null; // bi-directional client-to-client data path
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Objects.requireNonNull(getSupportActionBar()).hide();
} else {
getSupportActionBar().hide();
}
setContentView(R.layout.activity_main);
mBluetoothStatus = (TextView)findViewById(R.id.bluetooth_status);
mScanBtn = (Button)findViewById(R.id.scan);
mOffBtn = (Button)findViewById(R.id.off);
mDiscoverBtn = (Button)findViewById(R.id.discover);
mListPairedDevicesBtn = (Button)findViewById(R.id.paired_btn);
mStatus = (TextView)findViewById(R.id.status);
mUserEdit = (EditText)findViewById(R.id.user_edit);
mReqBtn = (Button)findViewById(R.id.req_btn);
mSendEdit = (Button)findViewById(R.id.send_edit_btn);
mVars = (ListView)findViewById(R.id.vars);
mBTArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
mBTDevices = new ArrayList<>();
mBTAdapter = BluetoothAdapter.getDefaultAdapter(); // get a handle on the bluetooth radio
mDevicesListView = (ListView)findViewById(R.id.devices_list_view);
assert mDevicesListView != null;
mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view
mDevicesListView.setOnItemClickListener(mDeviceClickListener);
mVars.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mSelecVar = mVars.getItemAtPosition(position).toString().split(",")[0];
}
});
// Ask for location permission if not already allowed
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
mHandler = new Handler(Looper.getMainLooper()){
#Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_READ){
String readMessage = null;
try {
readMessage = new String((byte[]) msg.obj, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
mMessage = readMessage;
if (mMessage != null) {
for (int i = 0; i < mMessage.length(); i++) {
if (mMessage.toCharArray()[i] == ';') {
getVars(mMessage);
break;
}
}
}
}
if(msg.what == CONNECTING_STATUS){
if(msg.arg1 == 1) {
mBluetoothStatus.setText("Connected to Device: " + msg.obj);
mConnectedThread.write("list");
} else
mBluetoothStatus.setText("Connection Failed");
}
}
};
if (mBTArrayAdapter == null) {
// Device does not support Bluetooth
mBluetoothStatus.setText("Status: Bluetooth not found");
Toast.makeText(getApplicationContext(),"Bluetooth device not found!",Toast.LENGTH_SHORT).show();
}
else {
mScanBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bluetoothOn();
}
});
mOffBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
bluetoothOff();
}
});
mListPairedDevicesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
listPairedDevices();
}
});
mDiscoverBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
discover();
}
});
}
}
private void bluetoothOn(){
if (!mBTAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
mBluetoothStatus.setText("Bluetooth enabled");
Toast.makeText(getApplicationContext(),"Bluetooth turned on",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(),"Bluetooth is already on", Toast.LENGTH_SHORT).show();
}
}
// Enter here after user selects "yes" or "no" to enabling radio
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent Data){
// Check which request we're responding to
if (requestCode == REQUEST_ENABLE_BT) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
// The Intent's data Uri identifies which contact was selected.
mBluetoothStatus.setText("Enabled");
}
else
mBluetoothStatus.setText("Disabled");
}
}
private void bluetoothOff(){
mBTAdapter.disable(); // turn off
mBluetoothStatus.setText("Bluetooth disabled");
Toast.makeText(getApplicationContext(),"Bluetooth turned Off", Toast.LENGTH_SHORT).show();
}
private void discover(){
// Check if the device is already discovering
if(mBTAdapter.isDiscovering()){
mBTAdapter.cancelDiscovery();
Toast.makeText(getApplicationContext(),"Discovery stopped",Toast.LENGTH_SHORT).show();
}
else{
if(mBTAdapter.isEnabled()) {
mBTArrayAdapter.clear(); // clear items
mBTAdapter.startDiscovery();
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
registerReceiver(blReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
else{
Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
}
}
}
final BroadcastReceiver blReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name to the list
mBTDevices.add(device);
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
BluetoothDevice mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED){
Log.d(TAG, "BroadcastReceiver: BOND_BONDED");
}
if (mDevice.getBondState() == BluetoothDevice.BOND_BONDING){
Log.d(TAG, "BroadcastReceiver: BOND_BONDING");
}
if (mDevice.getBondState() == BluetoothDevice.BOND_NONE){
Log.d(TAG, "BroadcastReceiver: BOND_NONE");
}
}
}
};
private void listPairedDevices(){
mBTArrayAdapter.clear();
mPairedDevices = mBTAdapter.getBondedDevices();
if(mBTAdapter.isEnabled()) {
// put it's one to the adapter
for (BluetoothDevice device : mPairedDevices)
if (device.getName().equals("MyArduino/")){
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
Toast.makeText(getApplicationContext(), "Show Paired Devices", Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
}
private AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(!mBTAdapter.isEnabled()) {
Toast.makeText(getBaseContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
return;
}
mBluetoothStatus.setText("Connecting...");
// Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) view).getText().toString();
final String address = info.substring(info.length() - 17);
final String name = info.substring(0,info.length() - 17);
// Spawn a new thread to avoid blocking the GUI one
new Thread()
{
#Override
public void run() {
boolean fail = false;
BluetoothDevice device = mBTAdapter.getRemoteDevice(address);
try {
mBTSocket = createBluetoothSocket(device);
} catch (IOException e) {
fail = true;
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
}
// Establish the Bluetooth socket connection.
try {
mBTSocket.connect();
} catch (IOException e) {
try {
fail = true;
mBTSocket.close();
mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)
.sendToTarget();
} catch (IOException e2) {
//insert code to deal with this
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
}
}
if(!fail) {
mConnectedThread = new ConnectedThread(mBTSocket, mHandler);
mConnectedThread.start();
mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)
.sendToTarget();
}
}
}.start();
}
};
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", UUID.class);
return (BluetoothSocket) m.invoke(device, BT_MODULE_UUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
return device.createRfcommSocketToServiceRecord(BT_MODULE_UUID);
}
public void showBt(View view) {
mBluetoothStatus.setVisibility(View.VISIBLE);
mScanBtn.setVisibility(View.VISIBLE);
mOffBtn.setVisibility(View.VISIBLE);
mDiscoverBtn.setVisibility(View.VISIBLE);
mListPairedDevicesBtn.setVisibility(View.VISIBLE);
mDevicesListView.setVisibility(View.VISIBLE);
mStatus.setVisibility(View.VISIBLE);
mVars.setVisibility(View.GONE);
mUserEdit.setVisibility(View.GONE);
mSendEdit.setVisibility(View.GONE);
mReqBtn.setVisibility(View.GONE);
}
public void showVars(View view) {
mBluetoothStatus.setVisibility(View.GONE);
mScanBtn.setVisibility(View.GONE);
mOffBtn.setVisibility(View.GONE);
mDiscoverBtn.setVisibility(View.GONE);
mListPairedDevicesBtn.setVisibility(View.GONE);
mDevicesListView.setVisibility(View.GONE);
mStatus.setVisibility(View.GONE);
mVars.setVisibility(View.VISIBLE);
mUserEdit.setVisibility(View.VISIBLE);
mSendEdit.setVisibility(View.VISIBLE);
mReqBtn.setVisibility(View.VISIBLE);
}
public void reqVars(View view) {
if (mConnectedThread != null){
mConnectedThread.write("list");
}
}
public void getVars(String string) {
String[] str = string.split(";");
List<String> al;
al = Arrays.asList(str);
ArrayAdapter<String> mVarsArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, al);
mVars.setAdapter(mVarsArrayAdapter);
}
public void editVar(View view) {
if (mConnectedThread != null) {
mConnectedThread.write("edit " + mSelecVar + " " + mUserEdit.getText());
mUserEdit.setText("");
SystemClock.sleep(2000);
mConnectedThread.write("list");
}
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
mBTAdapter.cancelDiscovery();
Log.d(TAG, "onItemClick: You clicked on a device.");
String deviceName = mBTDevices.get(i).getName();
String deviceAddress = mBTDevices.get(i).getAddress();
Log.d(TAG, "onItemClick: deviceName = " + deviceName);
Log.d(TAG, "onItemClick: deviceAddress = " + deviceAddress);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2){
Log.d(TAG, "Trying to pair with " + deviceName);
mBTDevices.get(i).createBond();
}
}
}
ConnectedThread:
package com.test.app;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.SystemClock;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final Handler mHandler;
public ConnectedThread(BluetoothSocket socket, Handler handler) {
mmSocket = socket;
mHandler = handler;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
#Override
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.available();
if(bytes != 0) {
buffer = new byte[1024];
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String input) {
byte[] bytes = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
Right now, the ListView shows all the devices that the Bluetooth founds, and sometimes, even shows them 2 or 3 times in the same list. As you can see in the MainActivity, i tried to make some sort of a filter in line 272 but it just does not work. Thanks
You trying to get device name equals to "MyArduino/" but what you need is actually device name how start with "MyArduino/":
just replace this line in listPairedDevices() on MainActivity:
from : (equals)
if (device.getName().equals("MyArduino/")){
to : (startsWith)
if (device.getName().startsWith("MyArduino/")){
editting the answer
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//before adding the device:
if(device.getName().startsWith("MyArduino/")){
// add the name to the list
mBTDevices.add(device);
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
}
So, after hours of trial and error, the problem was solved.
I've noticed this line in the errors on crash:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.startsWith(java.lang.String)' on a null object reference
It means that the function was looking for "MyArduino/" in a null object.
So i modified this:
if(device.getName().startsWith("MyArduino/")){
mBTDevices.add(device);
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
To this:
if (device.getName() != null) {
if (device.getName().contains("MyAdruino/")) {
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
}
And the problem was solved. It just showed the devices with "MyAdruino/" names and only once. Hope this will help anyone that gets the same problem
I intended to fetch data from ConnectionClass in background and then populate it into recyclerView.
Now, I have successfully fetched the data from url in json format, but my app is crashing when I am trying to display data using recyclerView.
Adapter Class for recyclerview
package com.example.mainapp;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import Model.PersonDetails;
public class PersonDetailsAdapter extends RecyclerView.Adapter<PersonDetailsAdapter.ViewHolder> {
private List<PersonDetails> personDetails;
PersonDetailsAdapter(List<PersonDetails>details)
{
personDetails = details;
}
#NonNull
#Override
public PersonDetailsAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Log.d("create view " , personDetails.toString());
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context) ;
View personView = inflater.inflate(R.layout.person_details_view , parent , true) ;
ViewHolder view = new ViewHolder(personView) ;
return view;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
PersonDetails details = personDetails.get(position);
holder.nameTextView.setText(details.getName());
holder.aliasTextView.setText(details.getAlias());
}
#Override
public int getItemCount() {
return personDetails.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView nameTextView;
public TextView aliasTextView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.nameHolder);
aliasTextView = (TextView) itemView.findViewById(R.id.aliasHolder);
}
}
}
MainActivity.java
package com.example.mainapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.mainapp.Utility.ConnectionClass;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Text;
import java.net.MalformedURLException;
import java.util.List;
import Model.PersonDetails;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button getButton = findViewById(R.id.get);
Button postButton = findViewById(R.id.post);
Context context = this.getBaseContext();
getButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ConnectionClass conn = null;
try {
conn = new ConnectionClass("URL", context);
conn.execute();
} catch (MalformedURLException e) {
System.out.println("connection not set ");
e.printStackTrace();
}
}
});
postButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
postRequest();
}
}
);
}
public void updateView( List<PersonDetails> personDetails ) {
Log.d("1" , "******************************************called fro");
RecyclerView rView = (RecyclerView)findViewById(R.id.recyclerViewPerson);
Log.d("2" , "******************************************iosdjdsa");
PersonDetailsAdapter adapter = new PersonDetailsAdapter(personDetails);
rView.setLayoutManager(new GridLayoutManager(this, 5));
rView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
private void postRequest() {
}
}
ConnectionClass.java
package com.example.mainapp.Utility;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import com.example.mainapp.MainActivity;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import Model.PersonDetails;
public class ConnectionClass extends AsyncTask<Void, Void, Void> {
private URL url ;
private HttpURLConnection conn;
private String response ;
private Context context ;
public ConnectionClass() {
super();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Log.d("onPost", "*****************************************postexe");
Toast.makeText(context, "Records fetched",Toast.LENGTH_SHORT);
List<PersonDetails> details = new ArrayList<>();
try {
JSONArray arr = new JSONArray(response);
for( int i = 0; i < arr.length() ; ++i )
{
JSONObject jObject = arr.getJSONObject(i);
PersonDetails record = new PersonDetails(jObject.getString("name"),jObject.getString("alias") );
details.add(record);
}
} catch (JSONException e) {
Log.d("t","json exception");
e.printStackTrace();
}
Log.d( "detalis", "**************************************"+details.toString());
MainActivity activity = new MainActivity();
activity.updateView(details);
}
public ConnectionClass(String url, Context context) throws MalformedURLException {
this.url = new URL (url);
conn = null ;
this.context = context;
}
// public void sendRequest(){
// try {
// System.out.println("\n\n***************************************hello**********************\n\n");
// conn = (HttpURLConnection) url.openConnection();
// conn.setDoOutput(false);
// conn.setDoInput(true);
// conn.setUseCaches(false);
// conn.setRequestMethod("GET");
// conn.setRequestProperty("Content-Type", "application/json");
// conn.connect();
// // handle the response
// System.out.println("\n\n***************************************here**********************\n\n");
//
// int status = conn.getResponseCode();
// System.out.println(status);
//
// if (status != 200)
// throw new IOException("Request not completed");
// else
// {
// BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// String inputLine ;
// StringBuilder builder = new StringBuilder() ;
// while((inputLine = in.readLine()) != null )
// builder.append(inputLine);
// in.close();
// response = builder.toString();
// }
//
// }
// catch (IOException e) {
// e.printStackTrace();
// }
// finally{
// if( conn != null )
// conn.disconnect();
// }
// }
public void setUrl(String url) throws MalformedURLException {
this.url = new URL(url);
}
public String getResponse() {
return response;
}
#Override
protected Void doInBackground(Void... voids) {
try {
conn = (HttpURLConnection) url.openConnection();
Log.d("conn", "***************************************************************************connectioon set " ) ;
} catch (IOException e) {
e.printStackTrace();
}
try {
conn.setRequestMethod("GET");
} catch (ProtocolException e) {
e.printStackTrace();
}
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setDoOutput(true);
try {
conn.connect();
Log.d("conn " , "**********************************************************************connected ");
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
try{
br =new BufferedReader(new InputStreamReader(url.openStream()));
char[] buffer = new char[1024];
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
Log.d("sb" , String.valueOf(sb));
}
catch (IOException e)
{
e.printStackTrace();
}
finally{
Log.d("finally ", "*****************************************************************************************finally");
response = sb.toString();
System.out.println("JSON: " + response);
conn.disconnect();
}
return null ;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_alignParentTop="true"
android:layout_marginTop="-3dp">
<TextView
android:id="#+id/nameText"
android:layout_width="141dp"
android:layout_height="45dp"/>
<TextView
android:id="#+id/aliasText"
android:layout_width="141dp"
android:layout_height="45dp"
android:layout_marginLeft="119dp"
android:layout_toRightOf="#+id/nameText" />
<Button
android:id="#+id/post"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginLeft="-11dp"
android:layout_marginBottom="2dp"
android:text="POST" />
<Button
android:id="#+id/get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="1dp"
android:layout_marginBottom="3dp"
android:text="GET" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewPerson"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#972A2A" />
</RelativeLayout>
xml for RecyclerView content
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="50dp"
android:padding="10dp">
<TextView
android:id="#+id/nameHolder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="TextView" />
<TextView
android:id="#+id/aliasHolder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="TextView" />
</LinearLayout>
Application is crashing when control reaches updateView()?
Add your AsyncTask code at the bottom of your MainActivity and then update the recyclerview like this:
updateView(details);
Let me clarify #sdex answer:
When you create an instance of Activity - in your case MainActivity - it doesn't have a view, it is not visible to the user and it's not added to the Activity stack. You could say - this activity is "Dead"
In order to display the result to your currently running MainActivity, so it's displayed to the user, you need to pass the instance of it to the ConnectionClass class. For example - pass it to the constructor of the ConnectionClass.
By the way - please consider moving away from AsyncTask, it's been deprecated and could be a reason for the Context leaks, meaning - you'll have massive objects, that are no more visible to the user are retaining in the memory.
In order to avoid leaking the Activity reference, please store it as the "WeakReference"
MainActivity activity = new MainActivity();
activity.updateView(details);
You can't instantiate activity like this; if you want to call a method in the activity within the AsynkTask class ConnectionClass; you can pass a listener to it and implement this listener in the activity, and then invoke the callback of that listener when you want to call some functionality in the activity.
interface ConnectionClassListener {
void onPostExecuteFinished(List<PersonDetails> personDetails);
}
Pass the class to the AsyncTask constructor
public class ConnectionClass extends AsyncTask<Void, Void, Void> {
ConnectionClassListener mConnectionClassListener;
public ConnectionClass(String url, Context context, ConnectionClassListener listener) throws MalformedURLException {
this.url = new URL (url);
conn = null ;
this.context = context;
mConnectionClassListener = listener;
}
Implement the listener by the activity
public class MainActivity extends AppCompatActivity implements ConnectionClassListener {
#Override
void onPostExecuteFinished(List<PersonDetails> personDetails) {
// Do here what you want when the ConnectionClass calls `onPostExecuteFinished()`
updateView(personDetails);
}
}
add this when creating the AsynkTask class
conn = new ConnectionClass("URL", context, this);
And finally call onPostExecuteFinished() in your ConnectionClass
public class ConnectionClass extends AsyncTask<Void, Void, Void> {
// ...
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// ...
mConnectionClassListener.onPostExecuteFinished(details);
MainActivity activity = new MainActivity();
You cannot just create the instance using the constructor. You should pass a reference of MainActivity to make it work. You need just to change a few lines of the code:
In ConnectionClass replace field private Context context; by private MainActivity activity; and change the constructor accordingly:
public ConnectionClass(String url, MainActivity activity) throws MalformedURLException {
this.url = new URL (url);
conn = null ;
this.activity = activity;
}
After that, you will be able to call activity.updateView(details);.
And don't forget to remove MainActivity activity = new MainActivity();
Further reading:
Proper use of AsyncTask
AsyncTask deprecation and alternatives
i am building a bluetooth chat application in android platform. everything is going fine but i have slight bug in my application . when i am trying to connect with a remote device which is present in my paired devices list and not available currently as a nearby device, then it throws "service discovery failed" exception and my application gets terminated automatically .
To prevent this automatic termination i have also put the condition like if such a exception occurs then start the "accept thread" again but it is not working.
mainActivity.java source code
package simpleweather.bluetooth_test1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import java.lang.InterruptedException;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TabHost;
import android.widget.TextView;
import java.util.Set;
import android.widget.Toast;
import java.util.ArrayList;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.view.View;
import android.widget.ArrayAdapter;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_ENABLE_BT = 1;
BluetoothAdapter bluetoothAdapter;
private UUID myUUID;
private String myName;
Button Refresh;
ListView NewDevices;
ArrayList<String> ScanNewList;
ArrayAdapter<String> ScanNewAdapter;
server serverconnection=null;
ArrayList<String> conversation;
ArrayAdapter<String> sessionchat;
ListView MsgList;
ArrayList<String> pairedDeviceArrayList;
ListView listViewPairedDevice;
ArrayAdapter<String> pairedDeviceAdapter;
client clientconnection=null;
communication datatransfer=null;
EditText input;
FloatingActionButton sent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NewDevices=(ListView)findViewById(R.id.newDevices);
ScanNewList=new ArrayList<String>();
Refresh=(Button)findViewById(R.id.refresh);
ScanNewAdapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,ScanNewList);
NewDevices.setAdapter(ScanNewAdapter);
sent=(FloatingActionButton)findViewById(R.id.send);
input=(EditText)findViewById(R.id.input);
MsgList=(ListView)findViewById(R.id.msglist);
conversation=new ArrayList<String>();
sessionchat = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, conversation);
MsgList.setAdapter(sessionchat);
TabHost tabHost=(TabHost)findViewById(R.id.tabHost);
tabHost.setup();
TabHost.TabSpec tabSpec=tabHost.newTabSpec("paireddevices");
tabSpec.setContent(R.id.pairedDevices);
tabSpec.setIndicator("Paired Devices");
tabHost.addTab(tabSpec);
tabSpec=tabHost.newTabSpec("msgArea");
tabSpec.setContent(R.id.chatArea);
tabSpec.setIndicator("Start Chat");
tabHost.addTab(tabSpec);
tabSpec=tabHost.newTabSpec("newdiscovered_devices");
tabSpec.setContent(R.id.newdevices);
tabSpec.setIndicator("Scan Devices");
tabHost.addTab(tabSpec);
listViewPairedDevice=(ListView)findViewById(R.id.listView);
sent.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
if(datatransfer!=null){
byte[] bytesToSend = input.getText().toString().getBytes();
datatransfer.write(bytesToSend,input.getText().toString());
input.setText("");
}
}});
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)){
Toast.makeText(getBaseContext(),"FEATURE_BLUETOOTH NOT support",Toast.LENGTH_SHORT).show();
finish();
return;
}
myUUID = UUID.fromString("ec79da00-853f-11e4-b4a9-0800200c9a66");
myName = myUUID.toString();
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(getBaseContext(),"Bluetooth is not supported on this hardware platform",Toast.LENGTH_SHORT).show();
finish();
return;
}
if (!bluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}else{
server_start();
client_start();
}
Refresh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
bluetoothAdapter.startDiscovery();
}
});
// start discovery for new devices
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); // registering broadcast reciever for retrieving information of new devices
registerReceiver(mReceiver, filter);
NewDevices.setOnItemClickListener(new OnItemClickListener() { // list of newly scaned devices
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
bluetoothAdapter.cancelDiscovery();
String info = ((TextView) view).getText().toString();
String address = info.substring(info.length() - 17);
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
Toast.makeText(MainActivity.this,"Name: " + device.getName() + "\n" + "Address: " + device.getAddress(), Toast.LENGTH_SHORT).show();
clientconnection = new client(device);
clientconnection.start();
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed here it is 1
if(requestCode==1) {
Log.d("Shashank","Bluetooth turned on ");
server_start();
client_start();
}
}
private synchronized void server_start() {
if(clientconnection!=null)
{
clientconnection.cancel();
clientconnection=null;
}
if(datatransfer!=null){
datatransfer.cancel();
datatransfer=null;
}
if(serverconnection!=null) {
serverconnection.cancel();
serverconnection = null;
}
serverconnection = new server();
serverconnection.start();
}
#Override
protected void onDestroy() {
super.onDestroy();
if(bluetoothAdapter!=null){
bluetoothAdapter.cancelDiscovery();
}
unregisterReceiver(mReceiver);
if(serverconnection!=null){
serverconnection.cancel();
serverconnection=null;
}
if(clientconnection!=null){
clientconnection.cancel();
clientconnection=null;
}
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(!ScanNewList.contains(device.getName()+"\n"+device.getAddress())) {
ScanNewList.add(device.getName() + "\n" + device.getAddress());
ScanNewAdapter.notifyDataSetChanged();
}
}
}
};
private class server extends Thread {
private BluetoothServerSocket bluetoothServerSocket = null;
public server() {
try {
bluetoothServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(myName, myUUID);
Toast.makeText(getBaseContext(),"Waiting\n" + "bluetoothServerSocket :\n" + bluetoothServerSocket,Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
server_start();
}
}
#Override
public void run() {
BluetoothSocket bluetoothSocket = null;
if(bluetoothServerSocket!=null){
try {
bluetoothSocket = bluetoothServerSocket.accept();
BluetoothDevice remoteDevice = bluetoothSocket.getRemoteDevice();
final String strConnected = "Connected:\n" + remoteDevice.getName() + "\n" +remoteDevice.getAddress();
//connected
runOnUiThread(new Runnable(){
#Override
public void run() {
Toast.makeText(getBaseContext(),strConnected,Toast.LENGTH_SHORT).show();
}});
start_communication(bluetoothSocket,remoteDevice.getName());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
final String eMessage = e.getMessage();
runOnUiThread(new Runnable(){
#Override
public void run() {
Toast.makeText(getBaseContext(),"something wrong: \n" + eMessage,Toast.LENGTH_SHORT).show();
}});
server_start();
}
}else{
runOnUiThread(new Runnable(){
#Override
public void run() {
Toast.makeText(getBaseContext(),"bluetoothServerSocket == null",Toast.LENGTH_SHORT).show();
}});
}
}
public void cancel() {
Toast.makeText(getBaseContext(),"close bluetoothServerSocket", Toast.LENGTH_SHORT).show();
try {
bluetoothServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void client_start() {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
findViewById(R.id.listView).setVisibility(View.VISIBLE);
pairedDeviceArrayList = new ArrayList<String>();
pairedDeviceAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, pairedDeviceArrayList);
for (BluetoothDevice device : pairedDevices) {
pairedDeviceArrayList.add(device.getName()+"\n"+device.getAddress());
}
pairedDeviceAdapter.notifyDataSetChanged();
listViewPairedDevice.setAdapter(pairedDeviceAdapter);
listViewPairedDevice.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
bluetoothAdapter.cancelDiscovery();
String info = ((TextView) view).getText().toString();
String address = info.substring(info.length() - 17);
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
Toast.makeText(MainActivity.this,"Name: " + device.getName() + "\n"+ "Address: " + device.getAddress(),Toast.LENGTH_SHORT).show();
clientconnection = new client(device);
clientconnection.start();
}});
}
}
private class client extends Thread {
private BluetoothSocket bluetoothSocket = null;
private final BluetoothDevice bluetoothDevice;
public client(BluetoothDevice device) {
bluetoothDevice = device;
try {
bluetoothSocket = device.createRfcommSocketToServiceRecord(myUUID);
Toast.makeText(getBaseContext(),"bluetoothSocket: \n" + bluetoothSocket,Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
server_start();
}
}
#Override
public void run() {
boolean success = false;
try {
bluetoothSocket.connect();
success = true;
} catch (IOException e) {
e.printStackTrace();
final String eMessage = e.getMessage();
runOnUiThread(new Runnable(){
#Override
public void run() {
Toast.makeText(getBaseContext(),"something wrong bluetoothSocket.connect(): \n" + eMessage,Toast.LENGTH_SHORT).show();
}});
try {
bluetoothSocket.close();
}
catch (IOException e2){
e2.printStackTrace();
server_start();
}
}
if(success){
//connect successful
runOnUiThread(new Runnable(){
#Override
public void run() {
Toast.makeText(getBaseContext(),"connection successfull",Toast.LENGTH_SHORT).show();
}});
start_communication(bluetoothSocket,bluetoothDevice.getName());
}else{
//fail
Toast.makeText(getBaseContext(),"Could not connected with the device!",Toast.LENGTH_SHORT).show();
server_start();
}
}
public void cancel() {
Toast.makeText(getBaseContext(), "Closed bluetoothSocket", Toast.LENGTH_SHORT).show();
try {
bluetoothSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void start_communication(BluetoothSocket socket,String chater){
datatransfer = new communication(socket,chater);
datatransfer.start();
}
private class communication extends Thread {
private final BluetoothSocket connectedBluetoothSocket;
private final InputStream connectedInputStream;
private final OutputStream connectedOutputStream;
String deviceName;
public communication(BluetoothSocket socket,String chater) {
connectedBluetoothSocket = socket;
deviceName=chater;
InputStream in = null;
OutputStream out = null;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
connectedInputStream = in;
connectedOutputStream = out;
}
#Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
bytes = connectedInputStream.read(buffer);
String strReceived = new String(buffer, 0, bytes);
final String msgReceived =strReceived;
runOnUiThread(new Runnable(){
#Override
public void run() {
conversation.add(deviceName+" : "+msgReceived);
sessionchat.notifyDataSetChanged();
}});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
final String msgConnectionLost = "Connection lost:\n" + e.getMessage();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), msgConnectionLost, Toast.LENGTH_SHORT).show();
server_start();
}
});
break;
}
}
}
public void write(byte[] buffer,String sendmsg) {
try {
connectedOutputStream.write(buffer);
conversation.add("Me : "+sendmsg);
sessionchat.notifyDataSetChanged();
} catch (IOException e) {
// TODO Auto-generated catch block
server_start();
}
}
public void cancel() {
try {
connectedBluetoothSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
and this is activity layout file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="simpleweather.bluetooth_test1.MainActivity"
tools:showIn="#layout/activity_main">
<TabHost
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/tabHost"
android:layout_alignParentTop="true"
android:layout_alignRight="#+id/textView2"
android:layout_alignEnd="#+id/textView2">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:id="#android:id/tabs"
android:layout_width="340dp"
android:layout_height="wrap_content"></TabWidget>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="392dp"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/chatArea"
android:layout_width="361dp"
android:layout_height="541dp"
android:weightSum="1">
<ListView
android:layout_width="match_parent"
android:layout_height="380dp"
android:id="#+id/msglist"
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"
android:layout_weight="0.87"
android:layout_above="#+id/send" />
<EditText
android:layout_width="230dp"
android:layout_height="wrap_content"
android:id="#+id/input"
android:hint="Type Message"
android:layout_marginBottom="41dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toStartOf="#+id/send"
android:layout_toLeftOf="#+id/send"
android:layout_marginRight="0dp" />
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/ic_dialog_email"
android:id="#+id/send"
android:layout_gravity="center_horizontal"
android:layout_alignBottom="#+id/input"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="20dp" />
</RelativeLayout>
<LinearLayout
android:id="#+id/newdevices"
android:layout_width="355dp"
android:layout_height="516dp"
android:orientation="vertical"
android:weightSum="1">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Refresh Scan"
android:id="#+id/refresh"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp" />
<ListView
android:layout_width="match_parent"
android:layout_height="379dp"
android:id="#+id/newDevices"
android:layout_marginTop="30dp"
android:layout_weight="0.47" />
</LinearLayout>
<LinearLayout
android:id="#+id/pairedDevices"
android:layout_width="374dp"
android:layout_height="500dp"
android:orientation="vertical"
android:weightSum="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Tap over the Listed Devices to start Connection"
android:id="#+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Paired Devices"
android:id="#+id/textView2"
android:layout_below="#+id/textView"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal" />
<ListView
android:layout_width="350dp"
android:layout_height="450dp"
android:id="#+id/listView"
android:layout_below="#+id/textView2"
android:layout_alignRight="#+id/textView"
android:layout_alignEnd="#+id/textView" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</RelativeLayout>
</ScrollView>
i have screenshot showing the bug .
screenshot showing the bug
I am confused why all this happening . I searched for the similar questions but i didn't found the situation like my bug . Please help me .
I meant that if your connection failed with an exception, then the error path is executed.
The code to show the "Toast" in the error path is different from all the other Toast calls. (ie. its probably not called on the UI thread), so that might be the issue.
Or there might be an issue somewhere within the server.start() call.
I want to display a Google Map on half screen of my profile view. In my onCreate method I created a new instance of an AsyncTask to retrieve latitude and longitude from Google servers via JSON. After receiving the result, I call:
GoogMapHandler gmh = new GoogMapHandler(fragmentManager, applicationContext);
gmh.initilizeMap(coord, "Username", "addressInfo");
Here is my GoogMapHandler class:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.content.Context;
import android.widget.Toast;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import com.google.android.gms.internal.fm;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class GoogMapHandler {
// Google Map
private GoogleMap googleMap;
private android.support.v4.app.FragmentManager fragmentManager;
private Context applicationContext;
public GoogMapHandler(FragmentManager fmanager, Context applicationContext) {
this.fragmentManager = fmanager;
this.applicationContext = applicationContext;
}
public void initilizeMap(LatLng coord, String username, String addrInfo) {
if (googleMap == null) {
Fragment fragment = this.fragmentManager.findFragmentById(R.id.map);
FragmentTransaction fragTransaction = this.fragmentManager
.beginTransaction();
fragTransaction.detach(fragment);
SupportMapFragment supportmapfragment = (SupportMapFragment) fragment;
googleMap = supportmapfragment.getMap();
if (googleMap == null) {
Toast.makeText(applicationContext,
"Sorry! Unable to create map.", Toast.LENGTH_SHORT)
.show();
} else {
Marker loc = googleMap.addMarker(new MarkerOptions()
.position(coord).title("User: " + username)
.snippet(addrInfo));
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(coord,
15));
fragTransaction.attach(fragment);
fragTransaction.commit();
}
}
}
}
Now the problem is, that I can't see the map, although I get no errors. As the View is already created, I tried to to "redraw" the fragment to display the map, but it's not working.
How can I achieve this?
Any help would be greatly appreciated.
EDIT:
Here is my ProfileActivity. As suggested, I used onResume to create the AsyncTask.
public class ProfileActivity extends BaseActivity {
private String username, address, postalCode, country;
#Override
protected void onResume() {
Log.i("URL",
"http://maps.googleapis.com/maps/api/geocode/json?address="
+ address.replaceAll("\\s+", "+") + ",+" + postalCode
+ ",+" + country + "&sensor=false");
new LocationTask(getSupportFragmentManager(),
getApplicationContext())
.execute("http://maps.googleapis.com/maps/api/geocode/json?address="
+ address.replaceAll("\\s+", "+")
+ ",+"
+ postalCode
+ ",+" + country + "&sensor=false");
super.onResume();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
Intent intent = getIntent();
username = intent.getStringExtra(SearchResultsActivity.USERNAME);
if (username != null) {
setTitle("User: " + username);
}
address = intent.getStringExtra(SearchResultsActivity.ADDRESS);
postalCode = intent
.getStringExtra(SearchResultsActivity.POSTALCODE);
country = intent.getStringExtra(SearchResultsActivity.COUNTRY);
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(username);
setContentView(textView);
}
}
Profile Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/map_frame"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.2" >
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="fill_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
</FrameLayout>
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="TextView" />
</LinearLayout>
Location Task:
public class LocationTask extends
AsyncTask<String, String, StringBuilder> {
private EditText address = null;
private EditText postalCode = null;
private EditText country = null;
private Context applicationContext;
private FragmentManager fragmentManager;
private LatLng coord;
public LocationTask(FragmentManager fmanager,
Context applicationContext) {
this.fragmentManager = fmanager;
this.applicationContext = applicationContext;
}
#Override
protected StringBuilder doInBackground(String... params) {
HttpGet httpGet = new HttpGet(params[0]);
HttpClient client = new DefaultHttpClient();
HttpResponse response;
try {
response = client.execute(httpGet);
StringBuilder stringBuilder = new StringBuilder();
try {
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder;
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(StringBuilder result) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject = new JSONObject(result.toString());
} catch (JSONException e) {
e.printStackTrace();
}
String postal_code = null;
String street_address = null;
String country = null;
try {
String status = jsonObject.getString("status").toString();
if (status.equalsIgnoreCase("OK")) {
JSONArray results = jsonObject.getJSONArray("results");
JSONObject r = results.getJSONObject(0);
JSONArray addressComponentsArray = r
.getJSONArray("address_components");
JSONObject geometry = r.getJSONObject("geometry");
JSONObject locationObj = geometry.getJSONObject("location");
coord = new LatLng(locationObj.getDouble("lat"), locationObj.getDouble("lng"));
}
} catch (JSONException e) {
e.printStackTrace();
}
GoogMapHandler gmh = new GoogMapHandler(fragmentManager, applicationContext);
gmh.initilizeMap(coord, "Username", "addressInfo");
}
}
I forgot to remove this in my ProfileActivity:
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(username);
setContentView(textView);
Removing it, solved my problem.
I cannot comment
Are you sure your code is going inside the IF block:
public void initilizeMap(LatLng coord, String username, String addrInfo) {
if (googleMap == null) {
//are you getting upto here?
....
}
}
If SupportMapFragment is declared in your layout, I don't think detach will do anything meaningful here. The following should work:
public void initilizeMap(LatLng coord, String username, String addrInfo) {
if (googleMap == null) {
Fragment fragment = this.fragmentManager.findFragmentById(R.id.map);
SupportMapFragment supportmapfragment = (SupportMapFragment) fragment;
googleMap = supportmapfragment.getMap();
if (googleMap == null) {
Toast.makeText(applicationContext,
"Sorry! Unable to create map.", Toast.LENGTH_SHORT)
.show();
} else {
Marker loc = googleMap.addMarker(new MarkerOptions()
.position(coord).title("User: " + username)
.snippet(addrInfo));
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(coord, 15));
}
} else {
Marker loc = googleMap.addMarker(new MarkerOptions()
.position(coord).title("User: " + username)
.snippet(addrInfo));
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(coord, 15));
}
If the above is not working, the problem is unlikely to be in the block of code, rather, it's probably getting called before map is ready.
Please give us more info; tell us whether the AsyncTask may be returning the results before onResume() is being called.
I use the org.apache.commons.io.FileUtils.readFileToByteArray method in myAndroid application. I imported the jar file and I see this method is in my project. (I use Eclipse.) Actually, compilation is ok. Here's the message from LogCat:
01-26 18:43:08.177: I/dalvikvm(897): Could not find method org.apache.commons.io.FileUtils.readFileToByteArray, referenced from method com.example.anagrams.MainActivity.readFile
So this is not an error, but then I get a NullPointerException due, apparently, to the statement:
private Button button_read_file = (Button) findViewById(R.id.button_readfile);
I have no idea how to correct the NullPointerException. Also I am puzzled by the message about the method not found. The application is supposed to read a text file containing English words and then for each word to find all the anagrams that exist. For the moment I just use System.out.println to write the anagrams.
Any help is welcome. Following is my whole MainActivity (the only one so far):
public class MainActivity extends Activity {
private String[] words;
private Button button_read_file = (Button) findViewById(R.id.button_readfile);
private EditText input_file_name = (EditText) findViewById(R.id.editText1) ;
private Button button_write_file = (Button) findViewById(R.id.button_writefile);
private EditText output_file_name = (EditText) findViewById(R.id.editText2) ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_read_file.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String inputFileName = input_file_name.getText().toString();
try {
words = readFile(inputFileName, Charset.defaultCharset());
} catch (FileNotFoundException e) {
e.getStackTrace();
} catch (IOException ioe) {
ioe.getStackTrace();
}
}});
button_write_file.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for (int i = 0; i < words.length; ++i) {
String s = words[i];
System.out.println(" words[" + i + "] = " + s);
HashSet<String> a = new HashSet<String>();
permutations(s,a);
Iterator<String> iterator = a.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}});
}
public String[] readFile(String path, Charset encoding) throws IOException {
File file = new File(path);
byte[] encoded = FileUtils.readFileToByteArray(file);
String s = encoding.decode(ByteBuffer.wrap(encoded)).toString();
s = s.replace(" ","");
return s.split("[,.\\n\\s]");
}
public ArrayList<String> getDictionary(String filename) throws IOException, FileNotFoundException {
ArrayList<String> dictionary = new ArrayList<String>();
FileReader fileReader = new FileReader(filename);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
dictionary.add(line);
}
bufferedReader.close();
return dictionary;
}
public boolean isInDictionary(String s) {
String dictionaryname = "enable1.txt";
ArrayList<String> dictionary = new ArrayList<String>();
try {
dictionary = getDictionary(dictionaryname);
} catch (FileNotFoundException e) {
e.getStackTrace();
} catch (IOException e) {
e.getStackTrace();
}
if (dictionary.contains(s))
return true;
else
return false;
}
public void permutations(String word, HashSet<String> anagrams) {
generatePermutations("",word,anagrams);
}
public void generatePermutations(String prefix, String word, HashSet<String> anagrams) {
int n = word.length();
if (n == 0) {
if (prefix != word && isInDictionary(prefix))
anagrams.add(prefix);
}
else {
for (int i = 0; i < n; ++i) {
generatePermutations(prefix + word.charAt(i),word.substring(0,i) + word.substring(i+1),anagrams);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
And here's the layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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=".MainActivity" >
<Button
android:id="#+id/button_readfile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="17dp"
android:text="#string/read_file" />
<Button
android:id="#+id/button_writefile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/button_readfile"
android:layout_below="#+id/button_readfile"
android:layout_marginTop="24dp"
android:text="#string/write_file" />
<EditText
android:id="#+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/button_readfile"
android:layout_toRightOf="#+id/button_writefile"
android:ems="10" >
<requestFocus />
</EditText>
<EditText
android:id="#+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button_writefile"
android:layout_alignBottom="#+id/button_writefile"
android:layout_alignLeft="#+id/editText1"
android:ems="10" >
</EditText>
You are initializing these before the layout is even set:
private Button button_read_file = (Button) findViewById(R.id.button_readfile);
private EditText input_file_name = (EditText) findViewById(R.id.editText1) ;
private Button button_write_file = (Button) findViewById(R.id.button_writefile);
private EditText output_file_name = (EditText) findViewById(R.id.editText2) ;
Change them to:
private Button button_read_file;
private EditText input_file_name;
private Button button_write_file;
private EditText output_file_name;
Then declare them after setContentView(...) in your onCreate like:
button_read_file = (Button) findViewById(R.id.button_readfile);
input_file_name = (EditText) findViewById(R.id.editText1) ;
button_write_file = (Button) findViewById(R.id.button_writefile);
output_file_name = (EditText) findViewById(R.id.editText2) ;
If you see NoClassDefFoundError, try this in Eclipse:
Go to Project Properties → Java Build Path → Order and Export tab.
Check the Android Private Libraries option.