I run through the following life-cycle when starting my app through the launcher:
onCreate..., onPostCreate..., onResume..., onNewIntent..., act:android.intent.action.MAIN, mNfcAdapter.disableForegroundDispatch OK.
When I then tap a tag, a new instance of application seems to be launched as I run through the following life-cycle then:
onPause..., onCreate..., onPostCreate..., onResume..., onNewIntent..., act:android.nfc.action.TAG_DISCOVERED, myTag.mId:048a1382bd2384)
Since I try to use the foreground dispatch system to disable recieving NFC events, I expected my app to ignore the NFC tag. So why is my activity recreated instead? Is it because AndroidManifest.xml allows it?
package com.example.pdf.nfcaccess;
import android.annotation.SuppressLint;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
// PDf import
import android.telephony.TelephonyManager;
import android.content.Intent;
import android.content.Context;
import android.content.IntentFilter;
import android.app.PendingIntent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.widget.TextView;
import android.widget.Toast;
import android.util.Log;
import android.nfc.tech.NfcF;
import android.nfc.Tag;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
public class FullscreenActivity extends AppCompatActivity {
/**
* Whether or not the system UI should be auto-hidden after
* {#link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = true;
/**
* If {#link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private static final int UI_ANIMATION_DELAY = 300;
private final Handler mHideHandler = new Handler();
private View mContentView;
private final Runnable mHidePart2Runnable = new Runnable() {
#SuppressLint("InlinedApi")
#Override
public void run() {
// Delayed removal of status and navigation bar
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
};
private View mControlsView;
// application
static FullscreenActivity mInstance;
NfcAdapter mNfcAdapter;
Intent mNfcIntent;
PendingIntent mNfcPendingIntent;
IntentFilter mTagIntentFilter;
IntentFilter[] mIntentFiltersArray;
String[][] mTechLists;
TextView mTagContentText;
// log
//java.util.ArrayList<String> mLogItems = new java.util.ArrayList<String>();
java.util.ArrayList<String> mLogItems = new java.util.ArrayList<String>();
android.widget.ArrayAdapter<String> mLogAdapter;
android.widget.ListView mLogList;
/**/
private final Runnable mShowPart2Runnable = new Runnable() {
#Override
public void run() {
// Delayed display of UI elements
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.show();
}
mControlsView.setVisibility(View.VISIBLE);
}
};
private boolean mVisible;
private final Runnable mHideRunnable = new Runnable() {
#Override
public void run() {
hide();
}
};
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
/* Enable NFC
*/
private final View.OnTouchListener mFuncNfcEnable = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
traceTry("mFuncNfcEnable");
if (mNfcAdapter != null) {
try {
traceTry("mNfcAdapter.enableForegroundDispatch");
mNfcAdapter.enableForegroundDispatch(FullscreenActivity.mInstance, mNfcPendingIntent, mIntentFiltersArray, mTechLists);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
}
return false;
}
};
/* read Intent
*/
private final View.OnTouchListener mFuncNfcRead = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (mNfcAdapter != null) {
try {
traceTry("onNewIntent");
onNewIntent(getIntent());
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
return false;
}
};
/* Disable NFC
*/
private final View.OnTouchListener mFuncNfcDisable = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
traceTry("mFuncNfcDisable");
if (mNfcAdapter != null) {
try {
traceTry("mNfcAdapter.disableForegroundDispatch");
mNfcAdapter.disableForegroundDispatch(FullscreenActivity.mInstance);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
}
return false;
}
};
/* Quit
*/
private final View.OnTouchListener mFuncBtnQuit = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
finish();
return false;
}
};
/**/
private void trace(String m) {
Log.d("NFCTags",m);
/*TextView tv = (TextView)findViewById(R.id.logContent_value);
String previous = tv.getText().toString();
tv.setText(previous + "\n" + m);*/
if (mLogAdapter != null) {
mLogItems.add(m);
mLogAdapter.notifyDataSetChanged();
mLogList.setSelection(mLogList.getCount()-1);
}
}
String mMessage = "";
private void traceTry(String m) {
trace(m + "...");
mMessage = m;
}
private void traceOk() {
trace(mMessage + " OK");
mMessage = "";
}
private void traceFails(Throwable t) {
String msg = mMessage + " fails";
if (t != null) {
msg += " exception:" + t.getMessage();
}
trace(msg);
//Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
mMessage = "";
}
/*
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
trace("onCreate...");
// set global unique instance
FullscreenActivity.mInstance = this;
setContentView(R.layout.activity_fullscreen);
// log
mLogItems.add("starts");
mLogAdapter = new android.widget.ArrayAdapter<String>(this, R.layout.support_simple_spinner_dropdown_item, mLogItems);
mLogList = (android.widget.ListView) findViewById(R.id.logList_value);
mLogList.setAdapter(mLogAdapter);
mVisible = true;
mControlsView = findViewById(R.id.fullscreen_content_controls);
mContentView = findViewById(R.id.fullscreen_content);
mTagContentText = (TextView) findViewById(R.id.tagContent_value);
// Set up the user interaction to manually show or hide the system UI.
mContentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
toggle();
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.nfcRead_btn).setOnTouchListener(mFuncNfcRead);
//findViewById(R.id.nfcDisable_btn).setOnTouchListener(mFuncNfcDisable);
findViewById(R.id.quit_btn).setOnTouchListener(mFuncBtnQuit);
trace("onCreate > before initializing nfc");
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
trace("ID:" + tm.getDeviceId());
trace("Network Operator Name:" + tm.getNetworkOperatorName());
trace("Sim Operator Name:" + tm.getSimOperatorName());
trace("Sim Serial Number:" + tm.getSimSerialNumber());
trace("Phone Type:" + tm.getPhoneType());
trace("Initial Phone Number:" + tm.getLine1Number());
boolean tryNfc = true;
if (tryNfc) {
try {
mMessage = "NfcAdapter.getDefaultAdapter";
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null) {
mMessage = "NFC is not available";
traceFails(null);
return;
} else {
traceOk();
}
} catch (Throwable t) {
traceFails(t);
return;
}
// Check if NFC is enabled
try {
mMessage = "test NfcAdapter.isEnabled";
if (!mNfcAdapter.isEnabled()) {
mMessage = "NFC is not enabled. do it manually";
traceFails(null);
return;
} else {
trace("NFC is enabled.");
}
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "create new Intent";
mNfcIntent = new Intent(this, getClass());
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "mNfcIntent.addFlags, PendingIntent.getActivity";
mNfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
mNfcPendingIntent = PendingIntent.getActivity(this, 0, mNfcIntent, 0);
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "new IntentFilter";
mTagIntentFilter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
mTagIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "addDataType, new IntentFilter[]";
mTagIntentFilter.addDataType("*/*");
//mTagIntentFilter.addDataType("text/plain");
mIntentFiltersArray = new IntentFilter[]{mTagIntentFilter};
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
// Setup a tech list for all NfcF tags
try {
mMessage = "new tech list";
//mTechLists = new String[][]{new String[]{NfcF.class.getName()}};
mTechLists = new String[][]{};
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
/*
if (mNfcAdapter != null) {
try {
mMessage = "mNfcAdapter.enableForegroundDispatch";
mNfcAdapter.enableForegroundDispatch(FullscreenActivity.mInstance, mNfcPendingIntent, mIntentFiltersArray, mTechLists);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
*/
}
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
trace("onPostCreate...");
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
//delayedHide(100);
}
private void toggle() {
trace("toggle...");
if (mVisible) {
hide();
} else {
show();
}
}
private void hide() {
trace("hide...");
// Hide UI first
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
mControlsView.setVisibility(View.GONE);
mVisible = false;
// Schedule a runnable to remove the status and navigation bar after a delay
mHideHandler.removeCallbacks(mShowPart2Runnable);
mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
}
#SuppressLint("InlinedApi")
private void show() {
// Show the system bar
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mVisible = true;
// Schedule a runnable to display UI elements after a delay
mHideHandler.removeCallbacks(mHidePart2Runnable);
mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
}
/**
* Schedules a call to hide() in [delay] milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
/**/
public String intentToText(Intent intent){
String report = "?";
try {
Bundle bundle = intent.getExtras();
if (bundle != null) {
java.util.Set<String> keys = bundle.keySet();
java.util.Iterator<String> it = keys.iterator();
report = "Intent:{";
while (it.hasNext()) {
String key = it.next();
report += "\n[" + key + ":" + bundle.get(key) + "],";
}
report += "}\n";
}
}
catch(Throwable t){
trace("intentToText > " + t.getMessage());
}
return report;
}
/**/
public static String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b & 0xff));
return sb.toString();
}
/**/
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
trace("onNewIntent...");
handleIntent(intent);
}
/**/
void handleIntent(Intent intent) {
if (intent == null) return;
String sAction = intent.getAction();
trace("act:" + sAction);
if( (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
|| (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()))
|| (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()))) {
String payload = intent.getDataString();
mTagContentText.setText("act:" + sAction + "\n" + "pload:" + payload + "\n" + intentToText(intent));
Tag myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (myTag != null) {
trace("myTag.mId:" + byteArrayToHex(myTag.getId()));
mTagContentText.setText(mTagContentText.getText() + "\n" + "myTag.mId:" + byteArrayToHex(myTag.getId()));
android.os.Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
for (android.os.Parcelable p : rawMsgs) {
NdefMessage msg = (NdefMessage) p;
NdefRecord[] records = msg.getRecords();
for (NdefRecord record : records) {
short tnf = record.getTnf();
byte[] id = record.getId();
byte[] payLoad = record.getPayload();
}
}
}
}
}
}
/**/
#Override
protected void onResume() {
super.onResume();
trace("onResume...");
if (mNfcAdapter != null) {
try {
// See if the Activity is being started/resumed due to an NFC event and handle it
onNewIntent( getIntent());
}
catch (Throwable t) {
traceFails(t);
}
try {
mMessage = "mNfcAdapter.disableForegroundDispatch";
mNfcAdapter.disableForegroundDispatch(FullscreenActivity.mInstance);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
}
/**/
#Override
protected void onPause() {
super.onPause();
trace("onPause...");
}
}
AndroidManifest.xml is :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.pdf.nfcaccess">
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_pdflauncher"
android:label="#string/app_name"
android:supportsRtl="true"
android:debuggable="true"
android:theme="#style/AppTheme">
<activity
android:name=".FullscreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name"
android:theme="#style/FullscreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
<!--intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter-->
</manifest>
You receive the NFC intent (action TAG_DISCOVERED) because you registered for it in the manifest:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
This is also the reason why your activity is recreated upon receiving the intent.
The intent filter that you register for the foreground dispatch (action NDEF_DISCOVERED with any MIME type) does not seem to match your tag (or you did not yet invoke the piece of code that would enable the foreground dispatch).
Note that calling disableForegroundDispatch() will ony disable a foreground dispatch previously registered through enableForegroundDispatch(). It will not influence the intent filters in your manifest. See Android: Can I enable/disable an activity's intent filter programmatically? on how you could selectively disable intent filters registered in the manifest. However, with regard to NFC intents, you would probably want to register to receive events for all tags through the foreground dispatch system and then, upon receiving the event in onNewIntent() selectively ignore tags that you don't want.
A few more things about your code (actually only about the NFC parts)
For the NDEF_DISCOVERED intent filter in your manifest you would typically also want to specify a <data ... /> element that matches the data type of your tags.
Do not use a TAG_DISCOVERED intent filter in your manifest (unless you really understand and want the impact of this). The TAG_DISCOVERED intent filter (when used in the manifest) is merely a compatibility mode for API level 9 (before Android 2.3.3) where NFC support was very, very limited and a fall-back mode that can be used to create apps that handle NFC tags that are not supported by any other app.
The TECH_DISCOVERED intent filter requires a tech-list XML file in order to match any tag. Thus, your current version of this filter in your manifest will never match anything.
Calling disableForegroundDispatch() in onResume() does not make any sense. By design, the foreground dispatch could never be enabled at this point of the activity life-cycle. The reason for this is that you must not call enableForegroundDispatch() before onResume() and you are required to call disableForegroundDispatch() at latest in onPause().
In fact it does not make sense to use enableForegroundDispatch() / disableForegroundDispatch() anywhere other than in onResume() / onPause(). If you want to stop listening for tags upon other events (e.g. a pressing a button), you would simply remember your current state (process/don't process NFC events) in some flag and, when you receive a new NFC intent in onNewIntent(), you would either process or silently ignore the tag based n that flag.
Your code should not manually call activity life-cycle methods (as you currently do with onNewIntent(getIntent());).
Related
Hi I m getting this error again and again.
Process: pandaboo.run.carromking, PID: 30965
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{pandaboo.run.carromking/pandaboo.run.carromking.MainActivity}: java.lang.InstantiationException: java.lang.Class<pandaboo.run.carromking.MainActivity> has no zero argument constructor
the android manifest is as follow:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:fullBackupContent="#xml/backup_descriptor"
tools:ignore="AllowBackup">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
there is no error in build but there is a red underline in the manifest under the .MainActivity with error:
This class should provide a default constructor (a public constructor with no arguments) (`pandaboo.run.carromking.MainActivity`)
pls help.
sure the MainActivity is as follow:
public class MainActivity extends Activity {
#SuppressLint("StaticFieldLeak")
static Context context;
public final ThreadLocal<Discovery> disc;
{
disc = new ThreadLocal<Discovery>() {
#Override
protected Discovery initialValue() {
return new Discovery(Discovery.DiscoveryType.MDNS);
}
};
}
public static Publisher gamePublisher;
Subscriber gameSubscriber;
Thread testPublishing;
RenderThread renderThread;
private final Node node;
public MainActivity(Node node) {
this.node = node;
}
public class TestPublishing extends Application implements Runnable {
#Override
public void run() {
while (gamePublisher != null) {
Log.v("CarromGame: umundo", "run");
//gamePublisher.send(message.getBytes());
try {
Thread.sleep(1000);
Log.v("CarromGame:", "sleep");
} catch (InterruptedException e) {
Log.v("CarromGame: exception", "in run");
e.printStackTrace();
}
pandaboo.run.carromking.MainActivity.this.runOnUiThread(() -> {
//tv.setText(tv.getText() + "o");
Log.v("CarromGame: umundo", "context view o");
//contentView = true;
renderThread = new RenderThread(new pandaboo.run.carromking.MainActivity.displayComponents().getHolder(), new MainGamePanel(pandaboo.run.carromking.MainActivity.this));
renderThread.start();
});
}
}
}
public class TestReceiver extends Receiver {
byte[] msgb;
String type = null;
public void receive(Message msg) {
msgb = msg.getData();
type = msg.getMeta("CLASS");
Log.v("CarromGame:umundo value", "TYPE = " + type);
for (String key : msg.getMeta().keySet()) {
Log.v("CarromGame: umundo", key + ": " + msg.getMeta(key) + " value for class" + msg.getMeta("CLASS"));
}
pandaboo.run.carromking.MainActivity.this.runOnUiThread(() -> {
//tv.setText(tv.getText() + "i");
Log.v("CarromGame: umundo", "context view i before");
ObjectInputStream is = null;
if ((type != null) && (!type.equals(""))) {
try {
type = null;
ByteArrayInputStream in = new ByteArrayInputStream(msgb);
is = new ObjectInputStream(in);
is.readObject();
Log.v("CarromGame: umundo", "inside try block " + is.toString());
} catch (Exception e) {
e.printStackTrace();
}
assert is != null;
Log.v("CarromGame: umundo", "context view i after" + is.toString());
renderThread = new RenderThread(new pandaboo.run.carromking.MainActivity.displayComponents().getHolder(), new MainGamePanel(pandaboo.run.carromking.MainActivity.this));
renderThread.start();
}
});
}
}
public class displayComponents extends SurfaceView implements SurfaceHolder.Callback {
public displayComponents() {
super(getApplicationContext());
this.getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
renderThread.running = true;
renderThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
while (true) {
try {
renderThread.join();
break;
} catch (InterruptedException ignored) {
}
}
}
}
//Called when activity is created for the first time
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
WifiManager wifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
// To check if there is any active Wifi connection
if (!wifi.isWifiEnabled()) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
//Allow the application to receive Wifi Multicast packets.
WifiManager.MulticastLock mcLock = wifi.createMulticastLock("gameLock");
mcLock.acquire();
System.loadLibrary("umundoNativeJava");
Objects.requireNonNull(disc.get()).add(node);
Log.v("CarromGame:", "on create");
gamePublisher = new Publisher("Carrom"); //Carrom: channel Name
node.addPublisher(gamePublisher);
//gamePublisher.send();
gameSubscriber = new Subscriber("Carrom", new pandaboo.run.carromking.MainActivity.TestReceiver());
node.addSubscriber(gameSubscriber);
testPublishing = new Thread(new pandaboo.run.carromking.MainActivity.TestPublishing());
//contentView();
testPublishing.start();
Log.v("CarromGame: umundo", "inside context view");
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//setTitle(title);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
MainGamePanel.PANEL_HEIGHT = this.getWindowManager().getDefaultDisplay().getHeight();
MainGamePanel.PANEL_WIDTH = this.getWindowManager().getDefaultDisplay().getWidth();
setContentView(new MainGamePanel(this));
}
#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_carrom_game_umundo, 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.
return super.onOptionsItemSelected(item);
}
}
You cannot do this:
public MainActivity(Node node) {
this.node = node;
}
Do not declare any constructors for an Activity. Only the Android framework can instantiate an Activity and you cannot define any additional constructors.
I'm new in Android world (as user but also as developer) and my Android App crash when execute myWebView.loadUrl("https://www.google.com"), but I don't understand why...
The goal is monitoring internet connection while the app is running:
If the connection is lost -> loads the error html in the web view
If the connection returns active -> reload the web view
Here's my app code:
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dedalos.amb">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MyApplication"
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">
<activity android:name=".SplashScreen" android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity
public class MainActivity extends AppCompatActivity {
// WEB VIEW
WebView myWebView = null;
// NETWORK MONITORING
Boolean isInternetConnected = false;
ConnectivityManager.NetworkCallback networkCallback = null;
ConnectivityManager connectivityManager = null;
//////////////////// OVERRIDE ////////////////////
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hideSystemUI();
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
if (getToken().equals("")) {
String uniqueID = UUID.randomUUID().toString();
SharedPreferences.Editor editor = prefs.edit();
editor.putString("token", uniqueID);
editor.commit();
}
creaWebView();
configuraWebView();
initNetworkCallback();
}
#Override
public void onResume() {
super.onResume();
if (myWebView == null) {
creaWebView();
configuraWebView();
}
if (networkCallback == null || connectivityManager == null)
initNetworkCallback();
isInternetConnected = (new ConnectionDetector(this).isConnectingToInternet());
startNetworkMonitoring();
if (isInternetConnected) {
caricaWebView();
}
else {
MyWebViewClient.loadError(myWebView);
}
}
#Override
public void onPause() {
super.onPause();
stopNetworkMonitoring();
}
private void creaWebView() {
if (myWebView == null) {
myWebView = (WebView) findViewById(R.id.ambWebViewLayout);
}
}
private void configuraWebView() {
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.setWebViewClient(new MyWebViewClient());
}
private void caricaWebView() {
if (myWebView == null) {
creaWebView();
configuraWebView();
}
myWebView.loadUrl("https://www.google.com");
}
private void initNetworkCallback() {
networkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
if (!isInternetConnected) {
isInternetConnected = true;
caricaWebView();
}
}
#Override
public void onLost(Network network) {
if (isInternetConnected) {
isInternetConnected = false;
MyWebViewClient.loadError(myWebView);
}
}
};
connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
}
private void startNetworkMonitoring() {
if (networkCallback == null)
initNetworkCallback();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectivityManager.registerDefaultNetworkCallback(networkCallback);
}
else {
NetworkRequest request = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
connectivityManager.registerNetworkCallback(request, networkCallback);
}
}
private void stopNetworkMonitoring() {
connectivityManager.unregisterNetworkCallback(networkCallback);
}
private String getToken() {
return getPreferences(MODE_PRIVATE).getString("token", "");
}
private void hideSystemUI() {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE
// Set the content to appear under the system bars so that the
// content doesn't resize when the system bars hide and show.
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
// Hide the nav bar and status bar
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
MyWebViewClient
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("https://www.google.com")) {
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
else {
return false;
}
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
if (error.getErrorCode() == -2) {
loadError(view);
}
else {
// TODO
}
}
public static void loadError(WebView view) {
String html = "<!DOCTYPE HTML>\n" +
"<html>\n" +
"<head>\n" +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" +
"<title>APP</title>\n" +
"</head>\n" +
"<body style=\"background:#e11020;font-family:Arial,Helvetica;\">\n" +
"<h1 style=\"color:rgba(255,255,255,0.9);text-align:center;padding:120px 20px 20px 20px;font-size:30px;\">No Internet connection</h1>\n" +
"</body>\n" +
"</html>";
view.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null);
}
}
ConnectionDetector
public class ConnectionDetector {
private Context mContext;
public ConnectionDetector(Context context) {
this.mContext = context;
}
/**
* Checking for all possible internet providers
* **/
public boolean isConnectingToInternet() {
ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Network[] networks = connectivityManager.getAllNetworks();
NetworkInfo networkInfo;
for (Network mNetwork : networks) {
networkInfo = connectivityManager.getNetworkInfo(mNetwork);
if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
return true;
}
}
}
else {
if (connectivityManager != null) {
//noinspection deprecation
NetworkInfo[] info = connectivityManager.getAllNetworkInfo();
if (info != null) {
for (NetworkInfo anInfo : info) {
if (anInfo.getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
}
return false;
}
}
Thanks in advance
According to this you need to call all view related methods on UI thread. Just load the url on UI thread like this:
myWebView.post(new Runnable() {
#Override
public void run() {
myWebView.loadUrl("https://www.google.com");
}
});
You also need to load your error html in the same way, like:
view.post(new Runnable() {
#Override
public void run() {
String html = "<!DOCTYPE HTML>\n" +
"<html>\n" +
"<head>\n" +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" +
"<title>APP</title>\n" +
"</head>\n" +
"<body style=\"background:#e11020;font-family:Arial,Helvetica;\">\n" +
"<h1 style=\"color:rgba(255,255,255,0.9);text-align:center;padding:120px 20px 20px 20px;font-size:30px;\">No Internet connection</h1>\n" +
"</body>\n" +
"</html>";
view.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null);
}
});
If you get Only the original thread that created a view hierarchy can touch its views error in your Logcat, use this.
what I want to do is developing an app that reads health data that collected by Samsung watch so I tried to use Samsung android health SDK . Moreover reading steps was very easy as there was a sample app doing the same thing . the issue appear when I was trying to read the heart rate value :
here is my code please help me address the issue :
Mainfest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smaunghealth">
<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">
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.step_count;com.samsung.health.heart_rate"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivity
package com.example.smaunghealth;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.samsung.android.sdk.healthdata.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
public static final String APP_TAG = "SimpleHealth";
private static MainActivity mInstance = null;
private HealthDataStore mStore;
private HealthConnectionErrorResult mConnError;
private Set<HealthPermissionManager.PermissionKey> mKeySet;
private StepCountReporter mReporter;
private HeartRateReporter mHeartReporter;
TextView stepCount ;
TextView heartRate ;
private final HealthResultHolder.ResultListener<HealthPermissionManager.PermissionResult> mPermissionListener =
new HealthResultHolder.ResultListener<HealthPermissionManager.PermissionResult>() {
#Override
public void onResult(HealthPermissionManager.PermissionResult result) {
Log.d(APP_TAG, "Permission callback is received.");
Map<HealthPermissionManager.PermissionKey, Boolean> resultMap = result.getResultMap();
if (resultMap.containsValue(Boolean.FALSE)) {
// Requesting permission fails
} else {
// Get the current step count and display it
}
}
};
private final HealthDataStore.ConnectionListener mConnectionListener = new HealthDataStore.ConnectionListener() {
#Override
public void onConnected() {
Log.d(APP_TAG, "Health data service is connected.");
HealthPermissionManager pmsManager = new HealthPermissionManager(mStore);
try {
// Check whether the permissions that this application needs are acquired
Map<HealthPermissionManager.PermissionKey, Boolean> resultMap = pmsManager.isPermissionAcquired(mKeySet);
if (resultMap.containsValue(Boolean.FALSE)) {
// Request the permission for reading step counts if it is not acquired
pmsManager.requestPermissions(mKeySet, MainActivity.this).setResultListener(mPermissionListener);
} else {
// Get the current step count and display it
// ...
mReporter = new StepCountReporter(mStore);
mReporter.start(mStepCountObserver);
mHeartReporter = new HeartRateReporter(mStore);
mHeartReporter.start(heartRateObserver);
}
} catch (Exception e) {
Log.e(APP_TAG, e.getClass().getName() + " - " + e.getMessage());
Log.e(APP_TAG, "Permission setting fails.");
}
}
#Override
public void onConnectionFailed(HealthConnectionErrorResult error) {
Log.d(APP_TAG, "Health data service is not available.");
showConnectionFailureDialog(error);
}
#Override
public void onDisconnected() {
Log.d(APP_TAG, "Health data service is disconnected.");
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInstance = this;
stepCount= (TextView) findViewById(R.id.step_count);
heartRate= (TextView) findViewById(R.id.heart_rate);
mKeySet = new HashSet<HealthPermissionManager.PermissionKey>();
// mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEART_RATE, HealthPermissionManager.PermissionType.READ));
HealthDataService healthDataService = new HealthDataService();
try {
healthDataService.initialize(this);
} catch (Exception e) {
e.printStackTrace();}
mStore = new HealthDataStore(this, mConnectionListener);
// Request the connection to the health data store
mStore.connectService();
}
#Override
public void onDestroy() {
mStore.disconnectService();
super.onDestroy();
}
private StepCountReporter.StepCountObserver mStepCountObserver = count -> {
Log.d(APP_TAG, "Step reported : " + count);
updateStepCountView(String.valueOf(count));
};
private HeartRateReporter.HeartRateObserver heartRateObserver = count -> {
Log.d(APP_TAG, "Step reported : " + count);
updateHeartRateView(String.valueOf(count));
};
private void updateHeartRateView(String valueOf) {
Log.d(APP_TAG, "heart rate reported : " + valueOf);
updateHeartRateView(String.valueOf(valueOf));
}
private void updateStepCountView(String count) {
stepCount.setText(count);
}
private void showConnectionFailureDialog(HealthConnectionErrorResult error) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
mConnError = error;
String message = "Connection with Samsung Health is not available";
if (mConnError.hasResolution()) {
switch(error.getErrorCode()) {
case HealthConnectionErrorResult.PLATFORM_NOT_INSTALLED:
message = "Please install Samsung Health";
break;
case HealthConnectionErrorResult.OLD_VERSION_PLATFORM:
message = "Please upgrade Samsung Health";
break;
case HealthConnectionErrorResult.PLATFORM_DISABLED:
message = "Please enable Samsung Health";
break;
case HealthConnectionErrorResult.USER_AGREEMENT_NEEDED:
message = "Please agree with Samsung Health policy";
break;
default:
message = "Please make Samsung Health available";
break;
}
}
alert.setMessage(message);
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
if (mConnError.hasResolution()) {
mConnError.resolve(mInstance);
}
}
});
if (error.hasResolution()) {
alert.setNegativeButton("Cancel", null);
}
alert.show();
}
}
HeartRateReporter
package com.example.smaunghealth;
import android.util.Log;
import com.samsung.android.sdk.healthdata.*;
import java.util.Calendar;
import java.util.TimeZone;
public class HeartRateReporter {
private final HealthDataStore mStore;
private HeartRateObserver mHeartRateObserver;
private static final long ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000L;
public HeartRateReporter(HealthDataStore store) {
mStore = store;
}
public void start(HeartRateObserver listener) {
mHeartRateObserver = listener;
HealthDataObserver.addObserver(mStore, HealthConstants.HeartRate.HEART_RATE, mObserver);
readHeartRate();
}
private void readHeartRate() {
HealthDataResolver resolver = new HealthDataResolver(mStore, null);
// Set time range from start time of today to the current time
long startTime = getStartTimeOfToday();
long endTime = startTime + ONE_DAY_IN_MILLIS;
HealthDataResolver.ReadRequest request = new HealthDataResolver.ReadRequest.Builder()
.setDataType(HealthConstants.HeartRate.HEART_RATE)
.setProperties(new String[] {HealthConstants.HeartRate.HEART_RATE})
.setLocalTimeRange(HealthConstants.HeartRate.START_TIME, HealthConstants.HeartRate.TIME_OFFSET,
startTime, endTime)
.build();
try {
resolver.read(request).setResultListener(mListener);
} catch (Exception e) {
Log.e("*&*&*&", "Getting Heart fails.", e);
}
}
private long getStartTimeOfToday() {
Calendar today = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
return today.getTimeInMillis();
}
private final HealthResultHolder.ResultListener<HealthDataResolver.ReadResult> mListener = result -> {
int count = 0;
try {
for (HealthData data : result) {
count += data.getInt(HealthConstants.HeartRate.HEART_RATE);
}
} finally {
result.close();
}
if (mHeartRateObserver != null) {
mHeartRateObserver.onChanged(count);
}
};
private final HealthDataObserver mObserver = new HealthDataObserver(null) {
#Override
public void onChange(String dataTypeName) {
Log.d("*&*&*&", "Observer receives a data changed event");
readHeartRate();
}
};
public interface HeartRateObserver {
void onChanged(int count);
}
}
StepCountReporter
/**
* Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
*
* Mobile Communication Division,
* Digital Media & Communications Business, Samsung Electronics Co., Ltd.
*
* This software and its documentation are confidential and proprietary
* information of Samsung Electronics Co., Ltd. No part of the software and
* documents may be copied, reproduced, transmitted, translated, or reduced to
* any electronic medium or machine-readable form without the prior written
* consent of Samsung Electronics.
*
* Samsung Electronics makes no representations with respect to the contents,
* and assumes no responsibility for any errors that might appear in the
* software and documents. This publication and the contents hereof are subject
* to change without notice.
*/
package com.example.smaunghealth;
import android.util.Log;
import com.samsung.android.sdk.healthdata.*;
import com.samsung.android.sdk.healthdata.HealthDataResolver.ReadRequest;
import com.samsung.android.sdk.healthdata.HealthDataResolver.ReadResult;
import java.util.Calendar;
import java.util.TimeZone;
public class StepCountReporter {
private final HealthDataStore mStore;
private StepCountObserver mStepCountObserver;
private static final long ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000L;
public StepCountReporter(HealthDataStore store) {
mStore = store;
}
public void start(StepCountObserver listener) {
mStepCountObserver = listener;
// Register an observer to listen changes of step count and get today step count
HealthDataObserver.addObserver(mStore, HealthConstants.StepCount.HEALTH_DATA_TYPE, mObserver);
readTodayStepCount();
}
// Read the today's step count on demand
private void readTodayStepCount() {
HealthDataResolver resolver = new HealthDataResolver(mStore, null);
// Set time range from start time of today to the current time
long startTime = getStartTimeOfToday();
long endTime = startTime + ONE_DAY_IN_MILLIS;
HealthDataResolver.ReadRequest request = new ReadRequest.Builder()
.setDataType(HealthConstants.StepCount.HEALTH_DATA_TYPE)
.setProperties(new String[] {HealthConstants.StepCount.COUNT})
.setLocalTimeRange(HealthConstants.StepCount.START_TIME, HealthConstants.StepCount.TIME_OFFSET,
startTime, endTime)
.build();
try {
resolver.read(request).setResultListener(mListener);
} catch (Exception e) {
Log.e(MainActivity.APP_TAG, "Getting step count fails.", e);
}
}
private long getStartTimeOfToday() {
Calendar today = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
return today.getTimeInMillis();
}
private final HealthResultHolder.ResultListener<ReadResult> mListener = result -> {
int count = 0;
try {
for (HealthData data : result) {
count += data.getInt(HealthConstants.StepCount.COUNT);
}
} finally {
result.close();
}
if (mStepCountObserver != null) {
mStepCountObserver.onChanged(count);
}
};
private final HealthDataObserver mObserver = new HealthDataObserver(null) {
// Update the step count when a change event is received
#Override
public void onChange(String dataTypeName) {
Log.d(MainActivity.APP_TAG, "Observer receives a data changed event");
readTodayStepCount();
}
};
public interface StepCountObserver {
void onChanged(int count);
}
}
Here is the exception log :
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.step_count;com.samsung.health.heart_rate"/>
I think you should separate this permission into two, not only one。
like:
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.step_count"/>
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.heart_rate"/>
After long time finally I was able to address the issue :
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEART_RATE, HealthPermissionManager.PermissionType.READ));
this is the write permissionKey :
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));
Hellow everyone ...
I'm new to Android Application development ..
Currently I'm working with BITalino Android API to develop my own Biosignal App.
The issue I'm facing now when I press the start button ... which intended to move to the next Activity it take me back to the launcher Activity(Main Activity).No error or warning is given out .. its just not working the way it supposed to work
Below are the codes
Thank you very much in advance .....
manifest.xml
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.Holo.Light">
<activity
android:name=".ScanActivity"
android:label="Anhalt BITadroid">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".DeviceActivity" />
<activity android:name=".BiosignalDisplay"></activity>
</application>
Snippet of onClick() for Device_Activity(MainActivity)
public class DeviceActivity extends Activity implements OnBITalinoDataAvailable, View.OnClickListener {
private final String TAG = this.getClass().getSimpleName();
public final static String EXTRA_DEVICE = "info.plux.pluxapi.sampleapp.DeviceActivity.EXTRA_DEVICE";
public final static String FRAME = "info.plux.pluxapi.sampleapp.DeviceActivity.Frame";
private BluetoothDevice bluetoothDevice;
private BITalinoCommunication bitalino;
private boolean isBITalino2 = false;
private Handler handler;
private States currentState = States.DISCONNECTED;
private boolean isUpdateReceiverRegistered = false;
/*
* UI elements
*/
private TextView nameTextView;
private TextView addressTextView;
private TextView elapsedTextView;
private TextView stateTextView;
private Button connectButton;
private Button disconnectButton;
private Button startButton;
private Button stopButton;
private LinearLayout bitalinoLinearLayout;
private Button stateButton;
private RadioButton digital1RadioButton;
private RadioButton digital2RadioButton;
private RadioButton digital3RadioButton;
private RadioButton digital4RadioButton;
private Button triggerButton;
private SeekBar batteryThresholdSeekBar;
private Button batteryThresholdButton;
private SeekBar pwmSeekBar;
private Button pwmButton;
private TextView resultsTextView;
private boolean isDigital1RadioButtonChecked = false;
private boolean isDigital2RadioButtonChecked = false;
private float alpha = 0.25f;
/*
* Test with 2 device
*/
// private BITalinoCommunication bitalino2;
// private String identifierBITalino2 = "20:16:07:18:15:94";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(getIntent().hasExtra(EXTRA_DEVICE)){
bluetoothDevice = getIntent().getParcelableExtra(EXTRA_DEVICE);
}
initView();
setUIElements();
handler = new Handler(getMainLooper()){
#Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
BITalinoFrame frame = bundle.getParcelable(FRAME);
Log.d(TAG, frame.toString());
if(frame != null){ //BITalino
resultsTextView.setText(frame.toString());
}
}
};
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(updateReceiver, makeUpdateIntentFilter());
isUpdateReceiverRegistered = true;
}
#Override
protected void onDestroy() {
super.onDestroy();
if(isUpdateReceiverRegistered) {
unregisterReceiver(updateReceiver);
isUpdateReceiverRegistered = false;
}
if(bitalino != null){
bitalino.closeReceivers();
try {
bitalino.disconnect();
} catch (BITalinoException e) {
e.printStackTrace();
}
}
// if(bitalino2 != null){
// bitalino2.closeReceivers();
// try {
// bitalino2.disconnect();
// } catch (BITalinoException e) {
// e.printStackTrace();
// }
// }
}
/*
* UI elements
*/
private void initView(){
nameTextView = (TextView) findViewById(R.id.device_name_text_view);
addressTextView = (TextView) findViewById(R.id.mac_address_text_view);
elapsedTextView = (TextView) findViewById(R.id.elapsed_time_Text_view);
stateTextView = (TextView) findViewById(R.id.state_text_view);
connectButton = (Button) findViewById(R.id.connect_button);
disconnectButton = (Button) findViewById(R.id.disconnect_button);
startButton = (Button) findViewById(R.id.start_button);
stopButton = (Button) findViewById(R.id.stop_button);
//bitalino ui elements
bitalinoLinearLayout = (LinearLayout) findViewById(R.id.bitalino_linear_layout);
stateButton = (Button) findViewById(R.id.state_button);
digital1RadioButton = (RadioButton) findViewById(R.id.digital_1_radio_button);
digital2RadioButton = (RadioButton) findViewById(R.id.digital_2_radio_button);
digital3RadioButton = (RadioButton) findViewById(R.id.digital_3_radio_button);
digital4RadioButton = (RadioButton) findViewById(R.id.digital_4_radio_button);
triggerButton = (Button) findViewById(R.id.trigger_button);
batteryThresholdSeekBar = (SeekBar) findViewById(R.id.battery_threshold_seek_bar);
batteryThresholdButton = (Button) findViewById(R.id.battery_threshold_button);
pwmSeekBar = (SeekBar) findViewById(R.id.pwm_seek_bar);
pwmButton = (Button) findViewById(R.id.pwm_button);
resultsTextView = (TextView) findViewById(R.id.results_text_view);
}
private void setUIElements(){
if(bluetoothDevice.getName() == null){
nameTextView.setText("BITalino");
}
else {
nameTextView.setText(bluetoothDevice.getName());
}
addressTextView.setText(bluetoothDevice.getAddress());
stateTextView.setText(currentState.name());
Communication communication = Communication.getById(bluetoothDevice.getType());
Log.d(TAG, "Communication: " + communication.name());
if(communication.equals(Communication.DUAL)){
communication = Communication.BLE;
}
bitalino = new BITalinoCommunicationFactory().getCommunication(communication,this, this);
// bitalino2 = new BITalinoCommunicationFactory().getCommunication(communication,this, this);
connectButton.setOnClickListener(this);
disconnectButton.setOnClickListener(this);
startButton.setOnClickListener(this);
stopButton.setOnClickListener(this);
stateButton.setOnClickListener(this);
digital1RadioButton.setOnClickListener(this);
digital2RadioButton.setOnClickListener(this);
digital3RadioButton.setOnClickListener(this);
digital4RadioButton.setOnClickListener(this);
triggerButton.setOnClickListener(this);
batteryThresholdButton.setOnClickListener(this);
pwmButton.setOnClickListener(this);
}
/*
* Local Broadcast
*/
private final BroadcastReceiver updateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if(ACTION_STATE_CHANGED.equals(action)){
String identifier = intent.getStringExtra(IDENTIFIER);
States state = States.getStates(intent.getIntExtra(EXTRA_STATE_CHANGED, 0));
Log.i(TAG, identifier + " -> " + state.name());
stateTextView.setText(state.name());
switch (state){
case NO_CONNECTION:
break;
case LISTEN:
break;
case CONNECTING:
break;
case CONNECTED:
break;
case ACQUISITION_TRYING:
break;
case ACQUISITION_OK:
break;
case ACQUISITION_STOPPING:
break;
case DISCONNECTED:
break;
case ENDED:
break;
}
}
else if(ACTION_DATA_AVAILABLE.equals(action)){
if(intent.hasExtra(EXTRA_DATA)){
Parcelable parcelable = intent.getParcelableExtra(EXTRA_DATA);
if(parcelable.getClass().equals(BITalinoFrame.class)){ //BITalino
BITalinoFrame frame = (BITalinoFrame) parcelable;
resultsTextView.setText(frame.toString());
}
}
}
else if(ACTION_COMMAND_REPLY.equals(action)){
String identifier = intent.getStringExtra(IDENTIFIER);
if(intent.hasExtra(EXTRA_COMMAND_REPLY) && (intent.getParcelableExtra(EXTRA_COMMAND_REPLY) != null)){
Parcelable parcelable = intent.getParcelableExtra(EXTRA_COMMAND_REPLY);
if(parcelable.getClass().equals(BITalinoState.class)){ //BITalino
Log.d(TAG, ((BITalinoState)parcelable).toString());
resultsTextView.setText(parcelable.toString());
}
else if(parcelable.getClass().equals(BITalinoDescription.class)){ //BITalino
isBITalino2 = ((BITalinoDescription)parcelable).isBITalino2();
resultsTextView.setText("isBITalino2: " + isBITalino2 + "; FwVersion: " + String.valueOf(((BITalinoDescription)parcelable).getFwVersion()));
// if(identifier.equals(identifierBITalino2) && bitalino2 != null){
// try {
// bitalino2.start(new int[]{0,1,2,3,4,5}, 1);
// } catch (BITalinoException e) {
// e.printStackTrace();
// }
// }
}
}
}
}
};
private IntentFilter makeUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_STATE_CHANGED);
intentFilter.addAction(ACTION_DATA_AVAILABLE);
intentFilter.addAction(ACTION_EVENT_AVAILABLE);
intentFilter.addAction(ACTION_DEVICE_READY);
intentFilter.addAction(ACTION_COMMAND_REPLY);
return intentFilter;
}
/*
* Callbacks
*/
#Override
public void onBITalinoDataAvailable(BITalinoFrame bitalinoFrame) {
Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putParcelable(FRAME, bitalinoFrame);
message.setData(bundle);
handler.sendMessage(message);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.connect_button:
try {
bitalino.connect(bluetoothDevice.getAddress());
} catch (BITalinoException e) {
e.printStackTrace();
}
break;
case R.id.disconnect_button:
try {
bitalino.disconnect();
} catch (BITalinoException e) {
e.printStackTrace();
}
break;
case R.id.start_button:{
Intent Recordingintent = new Intent(getApplicationContext(), BiosignalDisplay.class);
startActivity(Recordingintent);}
break;
case R.id.stop_button:
Intent exit = new Intent(this, ScanActivity.class);
startActivity(exit);
break;
}
}
}
main.xmlenter code here
This questions really can't be answered with what information was provided, so I'll instead give some general guidance on how to find these types of problems and the actual solution as per the context provided in the comments.
If your app closes when you don't expect it, the usual cause of this is an uncaught RuntimeException. These, in contrast to "checked exceptions", don't have to be surrounded by a try-catch for the compiler to be happy. If they are not caught, they will terminate the program/App.
The first step to fixing these exceptions is to check the Android Log (Log Cat) for the exception and a stack-trace. In Android Studio, the Log output is available at the bottom left corner.
If the Log is very busy with a lot of stuff going on, you can filter it by type and application. For the purpose of finding out error, we filter by our App and the "Error" log-level.
The actual exception from the question (from the comments) is:
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
This (very likely) means that the BiosignalDisplay-activity extends AppCompactActivity from the Android Support Library, but the entry in the AndroidManifest.xml doesn't set a support-library theme for the activity.
This can be fixed by setting the theme-attribute on either the specific <activity>-tag or on the <application>-tag to any theme under Theme.AppCompat, for example Theme.AppCompat.Light.NoActionBar.
For more information on this, see: You need to use a Theme.AppCompat theme (or descendant) with this activity
So I'm writing an app that reads reads in data from the serial port. This data is coming in from an arduino which is connected to a force transducer - essentially, the app is meant to measure the weight of something. I found serial port code here: https://www.allaboutcircuits.com/projects/communicate-with-your-arduino-through-android/, and I'm using it in multiple different activities (since I need an activity for calibration, an activity for the actual measuring, etc.). My problem is that the same exact serial port code is working in one activity and is not working in another. It works in this activity, for example:
public class EnterDataActivity extends AppCompatActivity {
private static final long TIMER_DELAY = 5000;
private static final long TIMER_LENGTH = 15000;
EditText enterMax, enterMin;
Button submitMax, submitMin, continueButton;
Chronometer emptyBagTimer;
boolean firstMeasure, getEmptyBagData, canEnterMax, canEnterMin;
ArrayList<String> emptyBagData;
float maxLoad, minLoad;
// serial port variables:
public final String ACTION_USB_PERMISSION = "com.example.jake.USB_PERMISSION";
UsbManager usbManager;
UsbDevice device;
UsbSerialDevice serialPort;
UsbDeviceConnection connection;
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
#Override
public void onReceivedData(byte[] arg0) {
String data;
try {
data = new String(arg0, "UTF-8");
if(getEmptyBagData)
emptyBagData.add(data);
} catch (UnsupportedEncodingException e) {}
}
};
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) {
connection = usbManager.openDevice(device);
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) { //Set Serial Connection Parameters.
serialPort.setBaudRate(9600);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
} else {
Log.d("SERIAL", "PORT NOT OPEN");
}
} else {
Log.d("SERIAL", "PORT IS NULL");
}
} else {
Log.d("SERIAL", "PERM NOT GRANTED");
}
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
start();
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
stop();
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_data);
usbManager = (UsbManager) getSystemService(USB_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(broadcastReceiver, filter);
enterMax = (EditText) findViewById(R.id.enterMax);
enterMin = (EditText) findViewById(R.id.enterMin);
submitMax = (Button) findViewById(R.id.submitMax);
submitMin = (Button) findViewById(R.id.submitMin);
continueButton = (Button) findViewById(R.id.continueButton);
emptyBagTimer = (Chronometer) findViewById(R.id.emptyBagTimer);
firstMeasure = true;
getEmptyBagData = false;
canEnterMax = true;
canEnterMin = true;
emptyBagData = new ArrayList<>();
start();
}
// method: measureEmptyBag
// description: this method is called when the button to measure the mass of the empty bag is
// pressed. It starts the chronometer and serial port, first waiting TIMER_DELAY milliseconds
// from the button press, then sets a boolean to true that causes the serial data to be added to
// an arraylist over the next TIMER_LENGTH milliseconds. It then sets the next views in the
// enter data process to visible. The firstMeasure boolean is to prevent spamming.
public void measureEmptyBag(View view){
if(firstMeasure) {
firstMeasure = false;
start();
emptyBagTimer.setBase(SystemClock.elapsedRealtime());
emptyBagTimer.start();
emptyBagTimer.setFormat("Waiting - %s");
emptyBagTimer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer chronometer) {
if (SystemClock.elapsedRealtime() - emptyBagTimer.getBase() <= TIMER_DELAY)
emptyBagTimer.setFormat("Waiting - %s");
else if (SystemClock.elapsedRealtime() - emptyBagTimer.getBase() <= TIMER_DELAY + TIMER_LENGTH) {
emptyBagTimer.setFormat("Calculating - %s");
getEmptyBagData = true;
}
else if (SystemClock.elapsedRealtime() - emptyBagTimer.getBase() > TIMER_DELAY + TIMER_LENGTH) {
getEmptyBagData = false;
emptyBagTimer.stop();
enterMax.setVisibility(View.VISIBLE);
submitMax.setVisibility(View.VISIBLE);
}
else
emptyBagTimer.setFormat("Waiting - %s");
}
});
}
}
// method: setMaxLoad
// description: called when the submit button is pressed for the max load, this method trys to
// pull the max load value from it edit text and store it. If that is successful (the user has
// entered in a number) then it sets the next views in the enter data process to visible.
public void setMaxLoad(View view){
if(canEnterMax){
try {
canEnterMax = false;
maxLoad = Float.parseFloat(enterMax.getText().toString());
enterMin.setVisibility(View.VISIBLE);
submitMin.setVisibility(View.VISIBLE);
} catch (Exception e) {} // in case the user enters a non number
}
}
// method: setMinLoad
// description: called when the submit button is pressed for the min load, this method trys to
// pull the min load value from its edit text and store it. If that is successful (the user has
// entered in a number) then it sets the next view in the enter data process to visible.
public void setMinLoad(View view){
if(canEnterMin){
try {
canEnterMin = false;
minLoad = Float.parseFloat(enterMin.getText().toString());
continueButton.setVisibility(View.VISIBLE);
} catch (Exception e) {} // in case the user enters a non number
}
}
// method: continuePressed
// description: this method is called when the continue button is pressed. It averages all of the
// data read in over the measure empty mass period to find the mass when empty, then writes that
// value along with maxLoad and minLoad to a file for later use. Finally it starts the pump
// activity
public void continuePressed(View view){
int emptyMassSum = 0;
int emptyMass;
// cleaning up emptyBagData to only include 3,2, or 1 digit numbers (the serial output gets
// wonky sometimes and spits out weird numbers that would throw off the calculations below,
// so those numbers need to be removed)
for (int i = emptyBagData.size() - 1; i >= 0; i--)
if (emptyBagData.get(i).length() != 3)
emptyBagData.remove(i);
// add up all the values in emptyBagData (try catch in case a non-number was read in)
for (int i = emptyBagData.size() - 1; i >= 0; i--) {
try {
emptyMassSum += Integer.parseInt(emptyBagData.get(i));
} catch (Exception e) {
emptyBagData.remove(i);
}
}
emptyMass = emptyMassSum / emptyBagData.size();
FileOutputStream outputStream;
String dataOut = "E" + emptyMass + "Mx" + maxLoad + "Mn" + minLoad + ";";
try {
outputStream = openFileOutput("BagData.txt", Context.MODE_PRIVATE);
outputStream.write(dataOut.getBytes());
outputStream.close();
} catch (Exception e) {
continueButton.setText(R.string.file_write_error_message);
}
Intent intent = new Intent(this, PumpActivity.class);
startActivity(intent);
}
// serial port methods:
public void start() {
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
if (deviceVID == 10755 || deviceVID == 9025)//Arduino Vendor ID
{
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, pi);
keep = false;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
}
}
public void stop() {
if(serialPort!=null)
serialPort.close();
}
}
By "it works", I mean that I can get the data coming in from the serial port and use it. However, the same code does not work here:
public class PumpActivity extends AppCompatActivity {
File calibrationData, bagData;
int mass1, mass2, read1, read2, emptyMassNum;
float maxLoad, minLoad;
double slope, currentMassVal, emptyMass;
boolean status, runTimer;
TextView statusTextView, currentMassTextView;
Button stop;
Thread updateMass;
ArrayList<String> inData;
// this does two things when the handleMessage method is called:
// 1) it takes the most recent data read in and calculates the current mass from it, then updates
// the current mass text view to reflect that
// 2) it takes that newly calculated mass and sees if status should change, depending on how much
// mass there currently is. It also writes a value to the serial port (back to the arduino)
// depending on that status. It then updates the status text view to reflect this
Handler updateMassHandler = new Handler(){
public void handleMessage(Message msg){
// mass calculation
try{currentMassVal = calculateMass(Integer.parseInt(inData.get(inData.size()-1)));} catch (Exception e){} // try-catch in case data isn't an int
inData.clear();
currentMassTextView.setText(String.format(getResources().getString(R.string.current_mass_string), currentMassVal));
// status check with new mass
if (currentMassVal >= maxLoad)
status = true;
else if (currentMassVal <= minLoad)
status = false;
statusTextView.setText(String.format(getResources().getString(R.string.pump_status), getStatus()));
// writing back to arduino
if (serialPort != null) {
if (status)
serialPort.write("1".getBytes());
else
serialPort.write("0".getBytes());
}
}
};
// serial port variables:
public final String ACTION_USB_PERMISSION = "com.example.jake.USB_PERMISSION";
UsbManager usbManager;
UsbDevice device;
UsbSerialDevice serialPort;
UsbDeviceConnection connection;
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
#Override
public void onReceivedData(byte[] arg0) {
String data;
try {
data = new String(arg0, "UTF-8");
inData.add(data);
} catch (UnsupportedEncodingException e) {}
}
};
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) {
connection = usbManager.openDevice(device);
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) { //Set Serial Connection Parameters.
serialPort.setBaudRate(9600);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
} else {
Log.d("SERIAL", "PORT NOT OPEN");
}
} else {
Log.d("SERIAL", "PORT IS NULL");
}
} else {
Log.d("SERIAL", "PERM NOT GRANTED");
}
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
start();
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
stop();
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pump);
usbManager = (UsbManager) getSystemService(USB_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(broadcastReceiver, filter);
status = false;
statusTextView = (TextView) findViewById(R.id.statusTextView);
statusTextView.setText(String.format(getResources().getString(R.string.pump_status), getStatus()));
currentMassTextView = (TextView) findViewById(R.id.currentMassTextView);
currentMassTextView.setText(R.string.calculating_text);
stop = (Button) findViewById(R.id.stopButton);
runTimer = true;
currentMassVal = 0;
inData = new ArrayList<>();
// thread that "calls" the handleMessage method in the upDateMassHandler every 100 milliseconds
updateMass = new Thread(new Runnable() {
#Override
public void run() {
while(runTimer){
updateMassHandler.sendEmptyMessage(0);
try{Thread.sleep(100);} catch (InterruptedException e){}
}
}
});
// thanks to stackOverflow for the file reading code
// reading and parsing from calibration data
calibrationData = new File(getFilesDir(), "CalibrationData.txt");
StringBuilder text = new StringBuilder();
// reading in the calibration data from the file (of the same name)
try {
BufferedReader br = new BufferedReader(new FileReader(calibrationData));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
br.close();
} catch (IOException e) {}
// parsing values from calibration data
String calibData = text.toString();
calibData = calibData.substring(3);
mass1 = Integer.parseInt(calibData.substring(0, calibData.indexOf('R')));
calibData = calibData.substring(calibData.indexOf(':') + 1);
read1 = Integer.parseInt(calibData.substring(0, calibData.indexOf('M')));
calibData = calibData.substring(calibData.indexOf(':') + 1);
mass2 = Integer.parseInt(calibData.substring(0, calibData.indexOf('R')));
calibData = calibData.substring(calibData.indexOf(':') + 1);
read2 = Integer.parseInt(calibData.substring(0, calibData.indexOf('.')));
slope = ((double) (mass2 - mass1) / (read2 - read1)); // calculating slope of masses and reads to allow
// calculation of mass of an unknown read
// reading and parsing from bag data
bagData = new File(getFilesDir(), "BagData.txt");
StringBuilder text2 = new StringBuilder();
// reading in the bag data from the file (of the same name)
try {
BufferedReader br = new BufferedReader(new FileReader(bagData));
String line;
while ((line = br.readLine()) != null) {
text2.append(line);
text2.append('\n');
}
br.close();
} catch (IOException e) {}
// parsing values frm bag data
String bagData = text2.toString();
bagData = bagData.substring(1);
emptyMassNum = Integer.parseInt(bagData.substring(0, bagData.indexOf('M')));
bagData = bagData.substring(bagData.indexOf('x') + 1);
maxLoad = Float.parseFloat(bagData.substring(0, bagData.indexOf('M')));
bagData = bagData.substring(bagData.indexOf('n') + 1);
minLoad = Float.parseFloat(bagData.substring(0, bagData.indexOf(';')));
emptyMass = calculateMass(emptyMassNum); // emptyMassNum is the values read in from the arduino
// this converts it to a mass
updateMass.start();
start();
}
// method: calculateMass
// description: calculates the mass of the object on the transducer based off of the value read
// in and the data gotten from calibration
// input: int readVal - the value read in
// output: double - the calculated mass
public double calculateMass(int readVal){
return (slope * (readVal-read1)) + mass1;
}
// method: getStatus
// description: returns a string representation of the status
public String getStatus(){
if(status)
return "running";
else
return "stopped";
}
// method: stop
// description: stops everything when the stop button is pressed
public void stop(View view){
status = false;
runTimer = false;
stop();
stop.setText(R.string.button_stopped);
}
// serial port methods:
public void start() {
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
if (deviceVID == 10755 || deviceVID == 9025)//Arduino Vendor ID
{
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, pi);
keep = false;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
}
}
public void stop() {
if(serialPort!=null)
serialPort.close();
}
}
For some reason, the onReceivedData method in the mCallback variable does not seem to be called in the second activity (the one not working). I'm pretty sure this is the problem, I'm just not sure why it is being called in one activity and not in another with the same code. If that method is not called, then I can't access the data coming in, which is my problem.
Also, here's my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.stylosa.hangingtransducer">
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.WRITE_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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</activity>
<activity
android:name=".CalibrateActivity">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</activity>
<activity
android:name=".InputActivity"
android:parentActivityName=".MainActivity">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</activity>
<activity
android:name=".EnterDataActivity">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</activity>
<activity
android:name=".PumpActivity">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</activity>
</application>
Any and all help would be greatly appreciated!