Run Backgroung thread , when activity is created - java

I am new to Android Programming. I am making an App which requires "OnlineMode" as well as "OfflineMode". I researched a lot about the topic and first step is to check for internet connectivity continously. Just like big apps like "WhatsApp" "Hike" etc use. Now I tried to create a thread which will run in background , it got created but not being able to produce the output the results. I have tried various methods. Here's what i want
1. A thread should run continuously on the background throughout the app checking the network connectivity.
2. Thread should be created as soon as user opens up the app
Below is my MainActivity.java file
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity{
// flag for Internet connection status
Boolean isInternetPresent = false;
// Connection detector class
ConnectionDetector cd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runInBackground();
Button btnStatus = (Button) findViewById(R.id.btn_check);
btnStatus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Button Clicked.", Toast.LENGTH_LONG).show();
}
});
}
void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
ConnectivityManager cm =
(ConnectivityManager)getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
if (!isConnected) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Thread t1 = new Thread(this);
t1.start();
Toast.makeText(MainActivity.this, "You are online.", Toast.LENGTH_LONG).show();
runInBackground();
}
});
} else{
Toast.makeText(MainActivity.this, "You have gone offline.", Toast.LENGTH_LONG).show();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runInBackground();
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_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) {
return true;
}
return super.onOptionsItemSelected(item);
}
Edit:
Here is my final code and i am getting errors
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xyz.broadcastreciever" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
<!-- Internet Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Network State Permissions -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</application>
</manifest>
MainActivity.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
NetworkChangeReceiver network = new NetworkChangeReceiver();
network.onReceive(this,intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_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) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
NetworkChangeReceiver.java
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable()) {
Log.d("Netowk Available ", "Flag No 1");
}
}
}
And Here is my Logs showing errors:
02-19 12:10:21.321 30369-30369/com.aubergine.broadcastreciever E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aubergine.broadcastreciever/com.aubergine.broadcastreciever.MainActivity}: java.lang.SecurityException: ConnectivityService: Neither user 10208 nor current process has android.permission.ACCESS_NETWORK_STATE.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2299)
at android.app.ActivityThread.access$700(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1280)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5283)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.SecurityException: ConnectivityService: Neither user 10208 nor current process has android.permission.ACCESS_NETWORK_STATE.
at android.os.Parcel.readException(Parcel.java:1425)
at android.os.Parcel.readException(Parcel.java:1379)
at android.net.IConnectivityManager$Stub$Proxy.getNetworkInfo(IConnectivityManager.java:1123)
at android.net.ConnectivityManager.getNetworkInfo(ConnectivityManager.java:636)
at com.aubergine.broadcastreciever.NetworkChangeReceiver.onReceive(NetworkChangeReceiver.java:19)
at com.aubergine.broadcastreciever.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:5283)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1097)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2209)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2299)
            at android.app.ActivityThread.access$700(ActivityThread.java:150)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1280)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5283)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
            at dalvik.system.NativeStart.main(Native Method)

To check the internet connectivity you should not start a new thread instead of this follow these steps:
As soon as you enter the app check for internet connectivity.
Add a BroadCastREceiver that keeps on listening to network on/off i.e state change updates for that add a IntentFilter <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
Now whenever you are connected or disconnected to the internet you will receive a update in onReceive of your BroadcastReceiver.
This is the receiver in manifest
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
This is the java class of receiver:
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable()) {
// Do something
Log.d("Netowk Available ", "Flag No 1");
}
}
}
If you are stuck in any of above step please comment.

Related

Why do I get ClassCastException when I extend a class?

I'm developing an app which can read data from a Bluetooth RFID Reader, but everytime i start the BluetoothActivity (it's a tabbed activity), it always shows a ClassCastException, below is my code..
BluetoothActivity class:
package com.siscaproject.sisca.Activity;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.siscaproject.sisca.Fragment.RegisterFragment;
import com.siscaproject.sisca.Fragment.SearchFragment;
import com.siscaproject.sisca.R;
import com.siscaproject.sisca.Utilities.FamsModel;
import com.siscaproject.sisca.Utilities.TSLBluetoothDeviceActivity;
import com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;
import com.uk.tsl.rfid.asciiprotocol.responders.LoggerResponder;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
public class BluetoothActivity extends TSLBluetoothDeviceActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
#BindView(R.id.viewpager_bluetooth) ViewPager mViewPager;
#BindView(R.id.toolbar_bluetooth) Toolbar mToolbar;
#BindView(R.id.tab_bluetooth) TabLayout mTabLayout;
private FamsModel mModel;
public AsciiCommander getCommander(){
return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
setupViewPager(mViewPager);
mTabLayout.setupWithViewPager(mViewPager);
AsciiCommander commander = getCommander();
// Add the LoggerResponder - this simply echoes all lines received from the reader to the log
// and passes the line onto the next responder
// This is added first so that no other responder can consume received lines before they are logged.
commander.addResponder(new LoggerResponder());
// Add a synchronous responder to handle synchronous commands
commander.addSynchronousResponder();
}
private void setupViewPager(ViewPager viewPager){
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new RegisterFragment(), "REGISTER");
adapter.addFragment(new SearchFragment(), "SEARCH");
viewPager.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_bluetooth, 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.menu_item_reconnect_reader) {
return true;
}
return super.onOptionsItemSelected(item);
}
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_bluetooth, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragmentList = new ArrayList<>();
private ArrayList<String> fragmentTitleList = new ArrayList<>();
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
// Show 3 total pages.
return fragmentList.size();
}
public void addFragment(Fragment fragment, String title ){
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
}
}
TSLBluetoothDeviceActivity class:
package com.siscaproject.sisca.Utilities;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;
import com.siscaproject.sisca.BuildConfig;
import com.uk.tsl.rfid.DeviceListActivity;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;
import java.util.Timer;
import java.util.TimerTask;
public class TSLBluetoothDeviceActivity extends AppCompatActivity {
// Debugging
private static final String TAG = "TSLBTDeviceActivity";
private static final boolean D = BuildConfig.DEBUG;
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;
// Local Bluetooth adapter
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothDevice mDevice = null;
protected AsciiCommander getCommander() {
return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// Create the AsciiCommander to talk to the reader (if it doesn't already exist)
if (getCommander() == null) {
try {
TSLBluetoothDeviceApplication app = (TSLBluetoothDeviceApplication) getApplication();
AsciiCommander commander = new AsciiCommander(getApplicationContext());
app.setCommander(commander);
} catch (Exception e) {
fatalError("Unable to create AsciiCommander!");
}
}
}
// Terminate the app with the given message
private void fatalError(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
finish();
}
}, 1800);
}
protected void bluetoothNotAvailableError(String message) {
fatalError(message);
}
#Override
public void onStart() {
super.onStart();
// If no other attempt to connect is ongoing try to connect to last used reader
// Note: When returning from the Device List activity
if (mBluetoothAdapter.isEnabled()) {
if (mDevice == null) {
// Attempt to reconnect to the last reader used
Toast.makeText(this, "Reconnecting to last used reader...", Toast.LENGTH_SHORT).show();
getCommander().connect(null);
}
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
#Override
public void onStop() {
super.onStop();
getCommander().disconnect();
mDevice = null;
}
protected void connectToDevice(Intent deviceData, boolean secure) {
Toast.makeText(this.getApplicationContext(), "Connecting...", Toast.LENGTH_LONG).show();
// Get the device MAC address
String address = deviceData.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
mDevice = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
if (mDevice != null) {
getCommander().connect(mDevice);
} else {
if (D) Log.e(TAG, "Unable to obtain BluetoothDevice!");
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (D)
Log.d(TAG, "selectDevice() onActivityResult: " + resultCode + " for request: " + requestCode);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectToDevice(data, true);
}
break;
case REQUEST_CONNECT_DEVICE_INSECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectToDevice(data, false);
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode != Activity.RESULT_OK) {
// User did not enable Bluetooth or an error occurred
Log.d(TAG, "BT not enabled");
bluetoothNotAvailableError("Bluetooth was not enabled\nApplication Quitting...");
}
}
}
public void selectDevice() {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
}
public void disconnectDevice() {
mDevice = null;
getCommander().disconnect();
}
public void reconnectDevice() {
getCommander().connect(null);
}
}
The error log:
11-21 14:47:54.836 18956-18956/com.siscaproject.sisca E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.siscaproject.sisca, PID: 18956
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.siscaproject.sisca/com.siscaproject.sisca.Activity.BluetoothActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2318)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396)
at android.app.ActivityThread.access$800(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1293)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication
at com.siscaproject.sisca.Activity.BluetoothActivity.getCommander(BluetoothActivity.java:51)
at com.siscaproject.sisca.Utilities.TSLBluetoothDeviceActivity.onCreate(TSLBluetoothDeviceActivity.java:45)
at com.siscaproject.sisca.Activity.BluetoothActivity.onCreate(BluetoothActivity.java:57)
at android.app.Activity.performCreate(Activity.java:5411)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396) 
at android.app.ActivityThread.access$800(ActivityThread.java:139) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1293) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:149) 
at android.app.ActivityThread.main(ActivityThread.java:5257) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:515) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609) 
at dalvik.system.NativeStart.main(Native Method) 
I've followed this code from an app that works fine, but when I implemented it in my project it always shows this error, I'm not sure what I'm doing wrong.
---EDIT---
TSLBluetoothDeviceApplication class:
package com.siscaproject.sisca.Utilities;
import android.app.Application;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;
public class TSLBluetoothDeviceApplication extends Application {
private static AsciiCommander commander = null;
/// Returns the current AsciiCommander
public AsciiCommander getCommander() {
return commander;
}
/// Sets the current AsciiCommander
public void setCommander(AsciiCommander _commander) {
commander = _commander;
}
}
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.siscaproject.sisca">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="android:icon">
<activity
android:name=".Activity.LoginActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Activity.BluetoothTestActivity"
android:theme="#style/StandardTheme" />
<activity
android:name=".Activity.HomeActivity"
android:label="#string/title_activity_home"
android:theme="#style/AppTheme" />
<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="barcode" />
<activity android:name=".Activity.QRActivity" />
<activity
android:name=".Activity.BluetoothActivity"
android:label="#string/title_activity_bluetooth"
android:theme="#style/AppTheme"></activity>
</application>
</manifest>
getApplication() inside an activity returns an object of type Application. In your case you are trying to cast this object into TSLBluetoothDeviceApplication which, as defined by you, is an Activity type class.
As I see, you are trying to call getCommander() which is defined already in your TSL activity class. I assume you want getCommander() method from another class.. Make sure which one is.
public AsciiCommander getCommander(){
return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
}
This method is already inside TSLBluetoothDeviceApplication class.. I don't know what are you trying to achieve by trying to call same method which is already in your current class.
EDIT:
After the edited post, we noticed that the class was properly implemented, just forgot to add
android:name="com.path.to.ApplicationClass" into the Manifestfile under <application/> tag.
I will let the above answer also, because it may help others
Happy coding <3
It's clear that your application class is not used. You need to add it to your xml Application tag like this:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication"
android:theme="#style/AppTheme"
tools:replace="android:icon">
and the only change is adding android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication" to the Application tag as your customized class.

Android app unable to launch an activity after splash activity

My app is unable to move to the 2nd activity that's StartingPoint after successfully launching the splash activity. App closes saying "unfortunately theNewBoston has stopped working."
I am attaching the relevant files. hope someone can help me with this.
StartingPoint.java
package com.example.thenewboston;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class StartingPoint extends Activity {
int counter;
Button add,sub;
TextView display;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_starting_point);
counter=0;
add=(Button)findViewById(R.id.addButton);
sub=(Button)findViewById(R.id.subButton);
display=(TextView) findViewById(R.id.display);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
counter++;
display.setText("Your total is = " + counter);
}
});
sub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
counter--;
display.setText("Your total is = " + counter);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.starting_point, 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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Splash.java
package com.example.thenewboston;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class Splash extends Activity{
#Override
public void onCreate(Bundle TV) {
// TODO Auto-generated method stub
super.onCreate(TV);
setContentView(R.layout.splash);
Thread timer = new Thread(){
public void run(){
try{
sleep(5000);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
Intent openStatingPoint= new Intent("com.thenewboston.StartingPoint");
startActivity(openStatingPoint);
}
}
};
timer.start();
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.thenewboston"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="23"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".StartingPoint"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.example.thenewboston.StartingPoint" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".Splash"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Try to change your code as below:
Intent openStatingPoint= new Intent(Splash.this,StartingPoint.class);
startActivity(openStatingPoint);
Explanation:
The constructor used here takes two parameters:
A Context as its first parameter (Splash.this is used because the Activity class is a subclass of Context)
The Class of the app component to which the system should deliver the Intent (in this case, the activity that should be started, here is StartingPoint.class)
See more Build an Intent
Thread class doesn't work on UI Thread so that instead of using Thread class use Handler class as follows -
Splash.java
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent openStatingPoint= new Intent(Splash.this,StartingPoint.class); // Use Explicit Intents
startActivity(openStatingPoint);
finish();
}
}, 5000); //time in milliseconds
check your logcat for the exception stack trace, it could be many reasons.
and

Auto Launch on Eddystone-UID within 1 meter

I want to auto-launch my activity when a beacon comes within 1 meter. This question has been posed before, but I am unable to get mine to work using/modifying his code.
Just like that post, I followed the same steps with the android beacon library through the altbeacon github but still have been unsuccessful.
I also have "compile 'org.altbeacon:android-beacon-library:2.7+'" in build.gradle file.
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.communionchapelefca.ccsatx" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
"android.hardware.bluetooth_le" android:required="false"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name="org.communionchapelefca.ccsatx.SplashScreen" android:label="#string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="org.communionchapelefca.ccsatx.MainActivity" android:label="#string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="org.communionchapelefca.ccsatx.MAINACTIVITY"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import org.altbeacon.beacon.startup.RegionBootstrap;
import java.util.Collection;
public class MainActivity extends Activity implements BootstrapNotifier, RangeNotifier {
public static final String TAG = "MainActivityCCSATX";
private WebView mWebView;
ProgressBar progressBar;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("http://communionchapelefca.org/edy-home");
mWebView.setWebViewClient(new HelloWebViewClient());
// begin code for bluetooth permission for android 6
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android M Permission check

if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access to find Communion Chapel beacons");
builder.setMessage("Please grant location access so this app can detect Communion Chapel beacons.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
mAllBeaconsRegion = new Region("all beacons", null, null, null);
mBeaconManager = BeaconManager.getInstanceForApplication(this);
mBackgroundPowerSaver = new BackgroundPowerSaver(this);
mRegionBootstrap = new RegionBootstrap(this, mAllBeaconsRegion);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb
//
Log.d(TAG, " region. starting ranging");
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
mBeaconManager.setBackgroundScanPeriod(11000l);
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
// end code for bluetooth permission for android 6
private class HelloWebViewClient extends WebViewClient{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
webView.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(view.GONE);
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{ //if back key is pressed
if((keyCode == KeyEvent.KEYCODE_BACK)&& mWebView.canGoBack())
{
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_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) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onBackPressed() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
MainActivity.this);
// set title
alertDialogBuilder.setTitle("Exit");
// set dialog message
alertDialogBuilder
.setMessage("Do you really want to exit?")
.setCancelable(false)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, close
// current activity
MainActivity.this.finish();
}
})
.setNegativeButton("No",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
private RegionBootstrap regionBootstrap;
private BeaconManager mBeaconManager;
private Region region;
private Region mAllBeaconsRegion;
private BackgroundPowerSaver mBackgroundPowerSaver;
private RegionBootstrap mRegionBootstrap;
#Override
public void didDetermineStateForRegion(int arg0, Region arg1) {
// Don't care
}
#Override
public void didEnterRegion(Region arg0) {
mRegionBootstrap.disable();
// This call to disable will make it so the activity below only gets launched the first time a beacon is seen (until the next time the app is launched)
// if you want the Activity to launch every single time beacons come into view, remove this call.
try {
mBeaconManager.startRangingBeaconsInRegion(new Region("all beacons", null, null, null));
mBeaconManager.setRangeNotifier(this);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d(TAG, "Got a didEnterRegion call");
}
#Override
public void didExitRegion(Region arg0) {
// Don't care
}
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
// TODO Auto-generated method stub
if (beacons.size() > 0) {
for (Beacon beacon: beacons) {
Log.d(TAG, "Found a beacon, getting distance");
if(beacon.getDistance()<1)
{
Log.d(TAG, "within 1 minute call");
Intent intent = new Intent(this, MainActivity.class);
// IMPORTANT: in the AndroidManifest.xml definition of this activity, you must set android:launchMode="singleInstance" or you will get two instances
// created when a user launches the activity manually and it gets launched from here.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
}
}
}
}
LogCat from fatal error:
01-28 17:23:38.819 6549 6724 D MainActivityCCSATX: Got a didEnterRegion call
01-28 17:23:38.824 6549 6549 D BluetoothAdapter: STATE_ON
01-28 17:23:38.824 6549 6549 D BluetoothLeScanner: could not find callback wrapper
01-28 17:23:38.824 6549 6549 D BluetoothAdapter: STATE_ON
01-28 17:23:38.824 6549 6549 D BluetoothLeScanner: could not find callback wrapper
01-28 17:23:39.444 6549 6549 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6549
01-28 17:23:40.023 6549 6549 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6549
A few tips:
Try adding a debug line Log.d("Distance:"+beacon.get Distance()); before you check for Distance < 1. Then run the app while watching LogCat output looking for that log line.
Understand that if you have Android 4.x, it may take up to five minutes to detect in the background.
It is always easier to get apps working in the foreground first, and then add background capability. Make sure you can write code to detect your beacon in the foreground.
With help from davidgyoung's code posted on github, I was able to solve the problem.

Unable to start activity ComponentInfo Parse

I'm developing an app that uses Parse to store and retrieve some data. I followed the setup guide on the website but it´s crashing!
These are the files:
MainActivity.java:
package apps.XXXXXX.test;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import com.parse.Parse;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new Frag())
.commit();
}
// Enable Local Datastore.
Parse.enableLocalDatastore(this);
Parse.initialize(this, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Frag.java
package apps.XXXXXX.test;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Frag extends Fragment {
private String mParam1;
private String mParam2;
String[] values = new String[5];
FragmentActivity activity;
private OnFragmentInteractionListener mListener;
public static Frag newInstance(String param1, String param2) {
Frag fragment = new Frag();
return fragment;
}
public Frag() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this.getActivity();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
values[0] = "laps";
values[1] = "activeEvent";
values[2] = "eventName";
values[3] = "highlights";
values[4] = "image";
ParseHelper parseHelper = new ParseHelper("Event", "objectId", "XXXXXXX", values, activity);
parseHelper.executeString();
return inflater.inflate(R.layout.fragment_, container, false);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
The app is able to retrieve data form Parse. But when I press the Back Button and go back to the app (icon or trough the recent apps) it's giving me this:
02-25 09:22:32.146 3295-3295/apps.xxxx.test E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: apps.xxxx.test, PID: 3295
java.lang.RuntimeException: Unable to start activity ComponentInfo{apps.xxxx.test/apps.xxxx.test.MainActivity}: java.lang.IllegalStateException: `Parse#enableLocalDatastore(Context)` must be invoked before `Parse#initialize(Context, String, String)`
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.IllegalStateException: `Parse#enableLocalDatastore(Context)` must be invoked before `Parse#initialize(Context, String, String)`
at com.parse.Parse.enableLocalDatastore(Parse.java:102)
at apps.xxxx.test.MainActivity.onCreate(MainActivity.java:23)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
I found the solution!
Just create a class named Application.java
package your.package.name;
import com.parse.Parse;
import com.parse.ParseUser;
public class Application extends android.app.Application {
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, "YOUR_APP_ID", "YOUR_CLIENT_KEY");
}
}
Edit the application section on your AndroidManifest.xml
<application
android:name="your.package.name.Application"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
That's it. That will maintain the Global Application State.

NullPointerException when trying to use text to speech to speak text message out loud

I'm getting an Exception when trying to get text to speech to speak sms text upon arrival and it's giving me a NullPointerException and I can seem to figure out was it's wanting me to do or where exactly the error lies. What could possibly be my problem?
Error Log
java.lang.RuntimeException: Unable to start receiver com.fegeley.handsfreetexting.TTS: java.lang.NullPointerException
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2677)
at android.app.ActivityThread.access$1800(ActivityThread.java:170)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1380)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5635)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.fegeley.handsfreetexting.TTS.speakText(TTS.java:52)
at com.fegeley.handsfreetexting.TTS.onReceive(TTS.java:74)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2669)
at android.app.ActivityThread.access$1800(ActivityThread.java:170)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1380)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5635)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
MainActivity.java
package com.fegeley.handsfreetexting;
import android.media.AudioManager;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.view.View;
import android.widget.Toast;
import java.util.HashMap;
import java.util.Locale;
public class MainActivity extends ActionBarActivity {
TTS tts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tts = new TTS();
tts.giveContext(this);
}
#Override
public void onPause(){
tts.onPause();
super.onPause();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_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) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
TTS.java
package com.fegeley.handsfreetexting;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.telephony.SmsMessage;
import java.util.HashMap;
import java.util.Locale;
/**
* Created by Kayne on 1/14/2015.
*/
public class TTS extends BroadcastReceiver {
private static Context context;
TextToSpeech tts;
public TTS(){
}
public static void giveContext(Context con){
context = con;
}
protected void onCreate(Bundle savedInstanceState){
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
tts.setLanguage(Locale.US);
}
}
});
}
public void onPause(){
if(tts !=null){
tts.stop();
tts.shutdown();
}
}
public void speakText(String toSpeak){
HashMap<String, String> hash = new HashMap<String,String>();
hash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
String.valueOf(AudioManager.STREAM_NOTIFICATION));
tts.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, hash);
}
#Override
public void onReceive(Context context, Intent intent) {
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
//if (bundle != null)
//{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
//}
//---display the new SMS message---
speakText(str);
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fegeley.handsfreetexting" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.fegeley.handsfreetexting.TTS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
</manifest>
Your "tts" object on Line 52 in NULL.
You seems to be initializing it in "onCreate()" of BroadcastReceiver.
protected void onCreate(Bundle savedInstanceState){
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener()
Note that BroadcastReceiver class do not have any onCreate() Activity-styled call back method.
I guess you assumed that system will invoke onCreate() of BroadcastReceiver class. That is not true for BroadcastReceiver.
You can initialize "tts" object in onReceive() as below:
public void onReceive(Context context1, Intent intent) {
//---get the SMS message passed in---
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
tts.setLanguage(Locale.US);
}
}
});
Also, change following line in your MainActivity.java
Remove : tts.giveContext(this); Add:TTS.giveContext(getApplicationContext());
This change is to prevent ReceiverCallNotAllowedException
You cannot instantiate a TextToSpeech object in a broadcast receiver. Your code
speakText(str);
at the end of onReceive is called before the Text To Speech call onInit thus you get speak failed not bound to TTS engine.
When an SMS arrives the system instantiate a TTS object as defined in your manifest. It has nothing to do with the tts you instantiates in your MainActivity.
You did not get NPE when your app is opened because the static declaration of context in your TTS class and you instantiate an object in your MainActivity, thus context is not null and therefore the tts object you declare in onCreate or in onReceive as AADTechnical suggested is not null.
When your app is close the tts object declared in MainActivity is destroyed thus the context member in any TTS object initiates without having one calls giveContext woud be null. And giveContext would not be called by the system when it instantiates a TTS object thus context is null and the tts object instantiates in the class is null and you get NPE.
What you need to do is to create a service class where a TTS object is instantiated and start your service in onReceive
public class SMSService extends Service
{
// instantiate a TTS object in this class
}
and
public class TTS extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// get your SMS message
// and then start the SMSService passing the message in the intent bundle
}
}
I don't know the library but the stack trace tells that the NullPointerException occured in TTS.java on line 52:
str += "SMS from " + msgs[i].getOriginatingAddress();
That means msgs[i] is null although it was assigned one line before that:
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
Thus createFromPdu returned null.
Since createFromPdu seems to be a framework method it is very likely that pdus[i] which you retrieved from the bundle is null.
Please make sure that you have written "pdus" into the bundle before you read them.
regards,
Max

Categories