I am very new to Android developing, so hopefully this is an easy one to answer. I have done lots of searching but cannot find an answer - possibly I am going about it the wrong way.
I have two class files, one is to get the battery level info (class A below) and the other uses TelephonyManager to get the device IMEI and display that (class B below).
I cannot work out how you can get the values of these two classes to appear on the same layout.
This is class A:
package com.XXXXXX.XXXXXX;
import android.app.ListActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class AboutScreen extends ListActivity {
/** Called when the activity is first created. */
private String[] strText = new String[] {"Battery Level", "Voltage", "Status"};
private int voltage = 0;
private boolean trun = true;
private Handler myHandler = new Handler();
private Runnable myRun = new Runnable() {
public void run() {
updateNow();
}
};
// using Thread to keep the process running
private Thread myThread = new Thread() {
public void run () {
do {
batteryLevelUpdate();
myHandler.post(myRun);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} while (trun);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(getApplicationContext(), "email", 2000).show();
startMonitor();
}
#Override
public void onDestroy() {
trun = false;
super.onDestroy();
}
private void startMonitor() {
myThread.start();
}
private void updateNow() {
ListView thisListView = getListView();
thisListView.setEnabled(false);
ArrayAdapter<String> myList = new ArrayAdapter<String>(this, R.layout.about_screen, strText);
thisListView.setAdapter(myList);
}
private void batteryLevelUpdate() {
BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(this);
int rawlevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int level = -1;
if (rawlevel >= 0 && scale > 0) {
level = (rawlevel * 100) / scale;
}
voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
int onplug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
boolean onUSB = onplug == BatteryManager.BATTERY_PLUGGED_USB;
boolean onAC = onplug == BatteryManager.BATTERY_PLUGGED_AC;
String strStatus = "Charging on ";
if (isCharging && onUSB)
strStatus += "USB";
else if (isCharging && onAC)
strStatus += "AC Power";
else
strStatus = "Battery Discharging";
strText[0] = "Battery Level: " + Integer.toString(level) + "%";
strText[1] = "Voltage: " + Integer.toString(voltage) + "mV";
strText[2] = strStatus;
//strText[3] = "test";
}
};
IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryLevelReceiver, batteryLevelFilter);
}
}
This is class B:
package com.XXXXXX.XXXXXX;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.widget.TextView;
public class AndroidTelephonyManager extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.phone);
TextView textDeviceID = (TextView)findViewById(R.id.deviceid);
//retrieve a reference to an instance of TelephonyManager
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
textDeviceID.setText(getDeviceID(telephonyManager));
}
String getDeviceID(TelephonyManager phonyManager){
String id = phonyManager.getDeviceId();
if (id == null){
id = "not available";
}
int phoneType = phonyManager.getPhoneType();
switch(phoneType){
case TelephonyManager.PHONE_TYPE_NONE:
return "NONE: " + id;
case TelephonyManager.PHONE_TYPE_GSM:
return "GSM: IMEI=" + id;
case TelephonyManager.PHONE_TYPE_CDMA:
return "CDMA: MEID/ESN=" + id;
/*
* for API Level 11 or above
* case TelephonyManager.PHONE_TYPE_SIP:
* return "SIP";
*/
default:
return "UNKNOWN: ID=" + id;
}
}
}
This is the layout file which displays the battery level info just fine:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="12sp"
android:clickable="false" />
However I have no idea how you can get the IMEI info from the class B to show as well. Ideally it would be another list row underneath the battery level items. Any advice on how you can combine different activities into one layout would be really useful.
Apologies if my explanation isn't great, but my java understanding is novice at the moment.
Many thanks
Use static method, for example
static String getDeviceID(TelephonyManager phonyManager)
then call the methods with class name,
classB.getDeviceID(phonyManager);
I think you might have got some basic concept wrong here. Activity is only for UI. Its not required that you need one Activity for one particular functionality. So you can have both the functionalities in one single activity, and update its layout.
You can write these values into Sharedpreferences....
getSharedPreferences("sp", MODE_PRIVATE).
edit().
putString("login", ed_login.getText().toString()).
commit();
So then you can get it anywhere by ...
getSharedPreferences("sp", MODE_PRIVATE).getString("login", "");
Related
I'm making an application that plays audio files off the device's storage, and I have a seek bar that checks the progress of the audio file (how long it has played) every second, and updates the seekbar accordingly.
The audio is played through a service that runs in the foreground, and also displays a notification that the audio is playing.
When the audio ends, I noticed the handler still goes in it's cycle, and I want to end the handler once the audio is done.
What I'm currently trying to do is to end the handler from inside the runnable that the handler runs, as I'm not sure how else I can end it.
Main Activity, where I handle OnClick from the ListView where you can select an audio file and also handles the seekbar update.
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
SeekBar musicProgBar;
Handler progBarHandler = null;
Runnable r = null;
private MP3Service.MyBinder myService = null;
TextView progressText = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
musicProgBar = findViewById(R.id.musicProgressBar);
progressText = findViewById(R.id.progressText);
final ListView lv = (ListView) findViewById(R.id.musicList);
Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,
MediaStore.Audio.Media.IS_MUSIC + "!= 0",
null,
null);
progBarHandler = new Handler();
final int progBarDelay = 1000; // delay for the handler, making it repeat itself only every 1000 miliseconds (1 second)
lv.setAdapter(new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
cursor,
new String[] { MediaStore.Audio.Media.DATA},
new int[] { android.R.id.text1 }));
Intent tempIntent = new Intent(this, MP3Service.class);
startService(tempIntent);
bindService(tempIntent, serviceConnection, 0);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> myAdapter,
View myView,
int myItemInt,
long myLong) {
Cursor c = (Cursor) lv.getItemAtPosition(myItemInt);
String uri = c.getString(c.getColumnIndex(MediaStore.Audio.Media.DATA));
Log.d("g53mdp", uri);
if (myService.fetchPlayerState() != MP3Player.MP3PlayerState.STOPPED)
myService.stopMusic();
myService.loadMusic(uri);
myService.playMusic();
musicProgBar.setMax(myService.fetchDuration()); // set the max value of the seekbar to be the duration of the song
r = new Runnable()
{
#Override
public void run()
{
int tempInt = myService.fetchProgress();
Log.d("progress ticking", tempInt + " " + musicProgBar.getProgress());
musicProgBar.setProgress(tempInt); // sets the current progress of the seekbar to be the progress of the song
long minutes = TimeUnit.MILLISECONDS.toMinutes(tempInt);
long seconds = TimeUnit.MILLISECONDS.toSeconds(tempInt);
if (seconds >= 60)
seconds = seconds - 60;
String tempString = minutes + ":" + seconds;
progressText.setText(tempString);
progBarHandler.postDelayed(this, progBarDelay);
if (musicProgBar.getProgress() == myService.fetchDuration())
progBarHandler.removeCallbacks(this);
}
};
progBarHandler.post(r);
}});
}
private ServiceConnection serviceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myService = (MP3Service.MyBinder) service;
}
#Override
public void onServiceDisconnected(ComponentName name)
{
myService = null;
}
};
public void playButClicked(View view)
{
myService.playMusic();
}
public void pauseButClicked(View view)
{
myService.pauseMusic();
}
public void stopButClicked(View view)
{
myService.stopMusic();
}
#Override
protected void onDestroy()
{
unbindService(serviceConnection);
progBarHandler.removeCallbacks(r);
super.onDestroy();
}
}
What is strange is that in onDestroy(), I do use removeCallbacks to end the handler, and that works nicely. I know that it comes to the point where it calls for removeCallbacks in the Runnable r, confirmed through debugging and logging. Also tried implementing a method that is specifically for removing the handler and calling that, no luck. Also tried using return.
The part I'm struggling with is
r = new Runnable()
{
#Override
public void run()
{
int tempInt = myService.fetchProgress();
Log.d("progress ticking", tempInt + " " + musicProgBar.getProgress());
musicProgBar.setProgress(tempInt); // sets the current progress of the seekbar to be the progress of the song
long minutes = TimeUnit.MILLISECONDS.toMinutes(tempInt);
long seconds = TimeUnit.MILLISECONDS.toSeconds(tempInt);
if (seconds >= 60)
seconds = seconds % 60;
String tempString = minutes + ":" + seconds;
progressText.setText(tempString);
progBarHandler.postDelayed(this, progBarDelay);
if (musicProgBar.getProgress() == myService.fetchDuration())
progBarHandler.removeCallbacks(this);
}
};
progBarHandler.post(r);
}});
The service which handles the music player and handles playing the music
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
public class MP3Service extends Service
{
public static MP3Service instance = null; // implementing singleton by instantiating a reference to the instance
private final String SERVICE_ID = "100"; // id for the service
public static boolean isRunning = false; //
NotificationManager notificationManager = null;
int notificationID = 001;
private final IBinder binder = new MyBinder();
MP3Player mainPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return binder;
}
#Override
public void onRebind(Intent intent)
{
// TODO: implement Rebind for screen orientation change
}
#Override
public void onCreate()
{
instance = this;
isRunning = true;
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mainPlayer = new MP3Player();
super.onCreate();
Handler handler = new Handler();
}
#Override
public void onDestroy()
{
isRunning = false;
instance = null;
notificationManager.cancel(notificationID);
}
public void createNotification()
{
CharSequence name = "MP3 Notification";
String description = "Displays a notification when a song is playing";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(SERVICE_ID, name, importance);
channel.setDescription(description);
notificationManager.createNotificationChannel(channel);
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// when the user clicks the notification, this will bring them to the activity
PendingIntent navToMainActivity = PendingIntent.getActivity(this, 0, intent, 0);
// sets up the info and details for the notification
final NotificationCompat.Builder mNotification = new NotificationCompat.Builder(this, SERVICE_ID)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("MP3 Player")
.setContentText("Playing music")
.setContentIntent(navToMainActivity)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
startForeground(notificationID, mNotification.build());
}
public void removeNotification()
{
stopForeground(false);
notificationManager.cancelAll();
}
public class MyBinder extends Binder
{
public void loadMusic(String filePath)
{
mainPlayer.load(filePath);
}
public void playMusic()
{
mainPlayer.play();
createNotification();
}
public void pauseMusic()
{
mainPlayer.pause();
removeNotification();
}
public void stopMusic()
{
mainPlayer.stop();
removeNotification();
}
public MP3Player.MP3PlayerState fetchPlayerState()
{
return mainPlayer.getState();
}
public int fetchDuration()
{
return mainPlayer.getDuration();
}
public int fetchProgress()
{
return mainPlayer.getProgress();
}
}
}
Thanks in advance for any help, and I am happy to provide with more information if required
EDIT: changed the progBarHandler.postDelay() that is outside the runnable to a simple progBarHandler.post()
I think the only reason you failed to stop the handler is constantly invoking progBarHandler.postDelayed(this, progBarDelay);,you need to check why it's still running.
Managed to get it working by introducing a different kind of if statement to the runnable, like so
Runnable r = new Runnable()
{
#Override
public void run()
{
if (musicProgBar.getProgress() == myService.fetchProgress() && myService.fetchProgress() != 0)
Log.d("audio", "over");
else {
int tempInt = myService.fetchProgress();
long minutes = TimeUnit.MILLISECONDS.toMinutes(tempInt);
long seconds = TimeUnit.MILLISECONDS.toSeconds(tempInt);
if (seconds >= 60)
seconds = seconds % 60;
String tempString = minutes + ":" + seconds;
progressText.setText(tempString);
musicProgBar.setProgress(tempInt); // sets the current progress of the seekbar to be the progress of the song
progBarHandler.postDelayed(this, progBarDelay);
}
}
};
It seemed for some reason, using .fetchDuration() and .fetchProgress() will never equalize each other, so changing the if statement worked.
So I have an application which has to monitor and range after beacons and than calculates the position of the user. After calculating this , the value is passed to the Wayfindigoverlayactivity.class where the value should be putt on the map with the blue dot.
I don know how to assign the value to the blue dot but before that my application is working on an endless loop and is opening the activity on ranging about 100x .
RangingActivity:
package com.indooratlas.android.sdk.examples.wayfinding;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.widget.EditText;
import android.content.Context;
import com.google.android.gms.maps.model.LatLng;
import com.indooratlas.android.sdk.IALocationRequest;
import com.indooratlas.android.sdk.examples.R;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.BlockingQueue;
public class RangingActivity extends Activity implements BeaconConsumer,Runnable{
protected static final String TAG = "RangingActivity";
public LatLng center;
private final BlockingQueue queue;
private BeaconManager beaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ranging);
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.bind(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
public void onBeaconServiceConnect() {
RangeNotifier rangeNotifier = new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
int beacon_number = beacons.size();
Beacon[] beacon_array = beacons.toArray(new Beacon[beacons.size()]);
Beacon device1 = null, device2 = null, device3 = null;
Constants constants = new Constants();
float txPow1 = 0;
double RSSI1Unfiltered = 0;
double RSSI2Unfiltered = 0;
float txPow2 = 0;
double RSSI3Unfiltered = 0;
float txPow3 = 0;
if (beacon_number == 4) {
if (beacon_array[0].getIdentifier(0).toString() == constants.DEVICE1_UUID) {
device1 = beacon_array[0];
} else if (beacon_array[1].getIdentifier(0).toString() == constants.DEVICE1_UUID) {
device1 = beacon_array[1];
} else {
device1 = beacon_array[2];
}
if (beacon_array[0].getIdentifier(0).toString() == constants.DEVICE2_UUID) {
device2 = beacon_array[0];
} else if (beacon_array[1].getIdentifier(0).toString() == constants.DEVICE2_UUID) {
device2 = beacon_array[1];
} else {
device2 = beacon_array[2];
}
if (beacon_array[0].getIdentifier(0).toString() == constants.DEVICE3_UUID) {
device3 = beacon_array[0];
} else if (beacon_array[1].getIdentifier(0).toString() == constants.DEVICE3_UUID) {
device3 = beacon_array[1];
} else {
device3 = beacon_array[2];
}
RSSI1Unfiltered = device1.getRssi();
RSSI2Unfiltered = device2.getRssi();
RSSI3Unfiltered = device3.getRssi();
txPow1 = device1.getTxPower();
txPow2 = device2.getTxPower();
txPow3 = device3.getTxPower();
} else if (beacon_number > 0) {
Log.d(TAG, "didRangeBeaconsInRegion called with beacon count: " + beacons.size());
for (int i = 0; i < beacon_number; i++) {
Beacon nextBeacon = beacon_array[i];
Log.d(TAG, "The next beacon " + nextBeacon.getIdentifier(0) + " is about " + nextBeacon.getDistance() + " meters away." + "RSSI is: " + nextBeacon.getRssi());
logToDisplay("The next beacon" + nextBeacon.getIdentifier(0) + " is about " + nextBeacon.getDistance() + " meters away." + "RSSI is: " + nextBeacon.getRssi());
}
}
Log.d(TAG, "FLOAT!!!!!!!!" + txPow1);
LocationFinder locationFinder = new LocationFinder();
//pass location
center = locationFinder.findLocation(RSSI1Unfiltered, txPow1, RSSI2Unfiltered, txPow2, RSSI3Unfiltered, txPow3);
Log.d(TAG, "Current coordinates: asta e asta e !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " + center.toString());
Bundle args = new Bundle();
args.putParcelable("b", center);
Intent intent00 = new Intent(RangingActivity.this, WayfindingOverlayActivity.class);
intent00.putExtras(args);
startActivity(intent00);
}
private void logToDisplay(final String s) {
runOnUiThread(new Runnable() {
#Override
public void run() {
EditText editText = RangingActivity.this.findViewById(R.id.textView3);
editText.append(s+"\n");
}
});
}
};
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
beaconManager.addRangeNotifier(rangeNotifier);
} catch (RemoteException e) {
}
}
/* Blockinqueue try---not working
RangingActivity(BlockingQueue q)
{
queue = q;
}
public void run() {
LatLng res;
try
{
res = center;
queue.put(res);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
*/
}
Everything works fine here , until I open the next class where my map is the WayfindingOverlayActivity
package com.indooratlas.android.sdk.examples.wayfinding;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import androidx.fragment.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.GroundOverlay;
import com.google.android.gms.maps.model.GroundOverlayOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.indooratlas.android.sdk.IALocation;
import com.indooratlas.android.sdk.IALocationListener;
import com.indooratlas.android.sdk.IALocationManager;
import com.indooratlas.android.sdk.IALocationRequest;
import com.indooratlas.android.sdk.IAOrientationListener;
import com.indooratlas.android.sdk.IAOrientationRequest;
import com.indooratlas.android.sdk.IAPOI;
import com.indooratlas.android.sdk.IARegion;
import com.indooratlas.android.sdk.IARoute;
import com.indooratlas.android.sdk.IAWayfindingListener;
import com.indooratlas.android.sdk.IAWayfindingRequest;
import com.indooratlas.android.sdk.examples.R;
import com.indooratlas.android.sdk.examples.SdkExample;
import com.indooratlas.android.sdk.resources.IAFloorPlan;
import com.indooratlas.android.sdk.resources.IALatLng;
import com.indooratlas.android.sdk.resources.IALocationListenerSupport;
import com.indooratlas.android.sdk.resources.IAVenue;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import com.squareup.picasso.Target;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
#SdkExample(description = R.string.example_wayfinding_description)
public class WayfindingOverlayActivity extends FragmentActivity
implements GoogleMap.OnMapClickListener, OnMapReadyCallback ,Runnable{
private final BlockingQueue queue;
private static final String TAG = "IndoorAtlasExample";
/* used to decide when bitmap should be downscaled */
private static final int MAX_DIMENSION = 2048;
//kalman filter
private static final double KALMAN_R = 0.125d;
private static final double KALMAN_Q = 0.5d;
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
private Circle mCircle;
private IARegion mOverlayFloorPlan = null;
private GroundOverlay mGroundOverlay = null;
private IALocationManager mIALocationManager;
private Target mLoadTarget;
private boolean mCameraPositionNeedsUpdating = true; // update on first location
private Marker mDestinationMarker;
private Marker mHeadingMarker;
private IAVenue mVenue;
private List<Marker> mPoIMarkers = new ArrayList<>();
private List<Polyline> mPolylines = new ArrayList<>();
private IARoute mCurrentRoute;
private IAWayfindingRequest mWayfindingDestination;
private IAWayfindingListener mWayfindingListener = new IAWayfindingListener() {
#Override
public void onWayfindingUpdate(IARoute route) {
mCurrentRoute = route;
if (hasArrivedToDestination(route)) {
// stop wayfinding
showInfo("You're there!");
mCurrentRoute = null;
mWayfindingDestination = null;
mIALocationManager.removeWayfindingUpdates();
}
updateRouteVisualization();
}
};
private IAOrientationListener mOrientationListener = new IAOrientationListener() {
#Override
public void onHeadingChanged(long timestamp, double heading) {
updateHeading(heading);
}
#Override
public void onOrientationChange(long timestamp, double[] quaternion) {
// we do not need full device orientation in this example, just the heading
}
};
private int mFloor;
// circle
private void showLocationCircle(LatLng center, double accuracyRadius) {
if (mCircle == null) {
// location can received before map is initialized, ignoring those updates
if (mMap != null) {
mCircle = mMap.addCircle(new CircleOptions()
.center(center)
.radius(accuracyRadius)
.fillColor(0x201681FB)
.strokeColor(0x500A78DD)
.zIndex(1.0f)
.visible(true)
.strokeWidth(5.0f));
mHeadingMarker = mMap.addMarker(new MarkerOptions()
.position(center)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.map_blue_dot))
.anchor(0.5f, 0.5f)
.flat(true));
}
} else {
// move existing markers position to received location
mCircle.setCenter(center);
mHeadingMarker.setPosition(center);
mCircle.setRadius(accuracyRadius);
}
}
private void updateHeading(double heading) {
if (mHeadingMarker != null) {
mHeadingMarker.setRotation((float) heading);
}
}
private IALocationListener mListener = new IALocationListenerSupport() {
public void onLocationChanged(IALocation location) {
Log.d(TAG, "NEW" + location.getLatitude() + " " + location.getLongitude());
if (mMap == null) {
return;
}
final LatLng center = new LatLng(location.getLatitude(),location.getLongitude());
final int newFloor = location.getFloorLevel();
if (mFloor != newFloor) {
updateRouteVisualization();
}
mFloor = newFloor;
showLocationCircle(center, location.getAccuracy());
if (mCameraPositionNeedsUpdating) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(center, 15.5f));
mCameraPositionNeedsUpdating = false;
}
}
};
/**
* Listener that changes overlay if needed
*/
private IARegion.Listener mRegionListener = new IARegion.Listener() {
#Override
public void onEnterRegion(final IARegion region) {
if (region.getType() == IARegion.TYPE_FLOOR_PLAN) {
Log.d(TAG, "enter floor plan " + region.getId());
mCameraPositionNeedsUpdating = true; // entering new fp, need to move camera
if (mGroundOverlay != null) {
mGroundOverlay.remove();
mGroundOverlay = null;
}
mOverlayFloorPlan = region; // overlay will be this (unless error in loading)
fetchFloorPlanBitmap(region.getFloorPlan());
//setupPoIs(mVenue.getPOIs(), region.getFloorPlan().getFloorLevel());
} else if (region.getType() == IARegion.TYPE_VENUE) {
mVenue = region.getVenue();
}
}
#Override
public void onExitRegion(IARegion region) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// prevent the screen going to sleep while app is on foreground
findViewById(android.R.id.content).setKeepScreenOn(true);
// instantiate IALocationManager
mIALocationManager = IALocationManager.create(this);
// Try to obtain the map from the SupportMapFragment.
((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map))
.getMapAsync(this);
Intent myIntent = new Intent(this, RangingActivity.class);
this.startActivity(myIntent);
Intent intent00 = getIntent();
LatLng center = intent00.getParcelableExtra("b");
Log.d(TAG,"Location!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + center);
}
#Override
protected void onDestroy() {
super.onDestroy();
// remember to clean up after ourselves
mIALocationManager.destroy();
}
/*Some blockingqueue---does not work
public class BlockinQueueExample
{
public void main(String[] args) throws Exception
{
BlockingQueue q = new ArrayBlockingQueue(1000);
RangingActivity producer = new RangingActivity(q);
WayfindingOverlayActivity consumer = new WayfindingOverlayActivity(q);
new Thread(producer).start();
new Thread(consumer).start();
}
}
WayfindingOverlayActivity(BlockingQueue q)
{
this.queue = q;
}
public void run() {
try{
queue.take();
Log.d(TAG,"BIANCABICA"+queue.take());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
*/
#Override
protected void onResume() {
super.onResume();
// start receiving location updates & monitor region changes
mIALocationManager.requestLocationUpdates(IALocationRequest.create(), mListener);
mIALocationManager.registerRegionListener(mRegionListener);
mIALocationManager.registerOrientationListener(
// update if heading changes by 1 degrees or more
new IAOrientationRequest(1, 0),
mOrientationListener);
if (mWayfindingDestination != null) {
mIALocationManager.requestWayfindingUpdates(mWayfindingDestination, mWayfindingListener);
}
}
EDIT , LAUNCHER ACTIVITY
package com.indooratlas.android.sdk.examples;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.indooratlas.android.sdk.examples.imageview.ImageViewActivity;
import com.indooratlas.android.sdk.examples.wayfinding.MonitoringActivity;
import com.indooratlas.android.sdk.examples.wayfinding.RangingActivity;
import com.indooratlas.android.sdk.examples.wayfinding.WayfindingOverlayActivity;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import org.altbeacon.beacon.startup.RegionBootstrap;
public class Bianca extends Activity implements BootstrapNotifier {
private static final String TAG = "RANGE";
private RegionBootstrap regionBootstrap;
private Button button;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private MonitoringActivity monitoringActivity = null;
private String cumulativeLog = "";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
//--------------------------------meniu -------------------------------
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openAct();
}
});
Button button2 = findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openAct2();
}
});
Button button3 = findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openAct3();
}
});
Button button4 = findViewById(R.id.button4);
button4.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openAct4();
}
});
//-----------------------------meniu----------------------------------
Notification.Builder builder = new Notification.Builder(this);
Intent intent = new Intent(this,WayfindingOverlayActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel channel = new NotificationChannel("My Notification Channel ID",
"My Notification Name", NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("My Notification Channel Description");
NotificationManager notificationManager = (NotificationManager) getSystemService(
Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
builder.setChannelId(channel.getId());
}
beaconManager.enableForegroundServiceScanning(builder.build(), 456);
Log.d(TAG, "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
Region region = new Region("backgroundRegion",
null, null, null);
regionBootstrap = new RegionBootstrap((BootstrapNotifier) this, region);
backgroundPowerSaver = new BackgroundPowerSaver(this);
}
public void openAct()
{
Intent intent = new Intent(this, WayfindingOverlayActivity.class);
startActivity(intent);
}
public void openAct2()
{
Intent intent2 = new Intent(this, RangingActivity.class);
startActivity(intent2);
}
public void openAct3()
{
Intent intent4 = new Intent(this, ImageViewActivity.class);
startActivity(intent4);
}
public void openAct4()
{
Intent intent5 = new Intent(this,RegionsActivity.class);
startActivity(intent5);
}
public void disableMonitoring() {
if (regionBootstrap != null) {
regionBootstrap.disable();
regionBootstrap = null;
}
}
public void enableMonitoring() {
Region region = new Region("backgroundRegion",
null, null, null);
regionBootstrap = new RegionBootstrap((BootstrapNotifier) this, region);
}
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever a Beacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedBeaconsSinceBoot) {
Log.d(TAG, "auto launching MainActivity");
// The very first time since boot that we detect an beacon, we launch the
// MainActivity
Intent intent = new Intent(this, WayfindingOverlayActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Important: make sure to add android:launchMode="singleInstance" in the manifest
// to keep multiple copies of this activity from getting created if the user has
// already manually launched the app.
this.startActivity(intent);
haveDetectedBeaconsSinceBoot = true;
} else {
if (monitoringActivity != null) {
// If the Monitoring Activity is visible, we log info about the beacons we have
// seen on its display
Log.d(TAG, "I see a beacon again");
} else {
// If we have already seen beacons before, but the monitoring activity is not in
// the foreground, we send a notification to the user on subsequent detections.
Log.d(TAG, "Sending notification.");
}
}
}
public void didExitRegion(Region arg0) {
Log.d(TAG,"I no longer see a beacon.");
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
}
The second class is not fully posted , only where I make changes.
The intent in the second class is in the OnCreate part
The location is calculated in the logcat , the only problem is that the application is working in a loop
Please help me , I am stuck. Thanks
I guess, you only need to open RangingActivity from onCreate() of WayFindingOverlayActivity if center is null. This means, we need to open RangingActivity to get the value for center. Doing null check for the center will also ensure that the application doesn't go in loop and proceed when we have the value for center. The code in the onCreate() of WayFindingOverlayActivity may look like this :
// edited here
Bundle extras = getIntent().getExtras();
if(extras == null){
Intent myIntent = new Intent(this, RangingActivity.class);
this.startActivity(myIntent);
} else{
LatLng center = extras.getParcelable("b");
Log.d("Location!!", center);
// call showLocationCircle() to show the blue dot
showLocationCircle(center, yourAccuracyRadius);
}
I am having a problem and I ran out of ideas how to fix it.
The goal is, when the user clicks the button an URL is loaded depending on what's selected in settings.
Problem is, I am having trouble setting it up in a right way.
Logically(to me), I tried to set it up in a service. Button is clicked > Service starts > URL is loaded from "IF ELSE".
Problem is, I get an error in "IF ELSE" - "Method length must be called from the UI Thread, currently inferred thread is is worker.
public static class Service extends IntentService {
public Service() {
super("wallpaperchanger-download");
}
#Override
protected void onHandleIntent(Intent intent) {
MainActivity mainActivity;
mainActivity = new MainActivity();
if (mainActivity.mEditTextHashtag.length() > 2) {
WallpaperManager wm = WallpaperManager.getInstance(this);
int height = wm.getDesiredMinimumHeight();
int width = wm.getDesiredMinimumWidth();
String url = "https://source.unsplash.com/all/?" + mainActivity.mEditTextHashtag.getText() + "/" + width + "x" + height + "/";
try {
InputStream input = new URL(url).openStream();
Log.v(TAG, url);
wm.setStream(input);
input.close();
} catch (Exception e) {
e.printStackTrace();
}
loading = false;
}
}
}
Ok, fair enough.
I created new Method getPhoto(); in UI Thread and put the code in there. Then, I called mainActivity.getPhoto(); in Service.
Problem is, I get an error - "Attempt to invoke virtual method 'int android.widget.EditText.length()' on a null object reference"
Any ideas on what I should do?
Full code in all its glory:
package com.edip.splashwallpaper;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.Toast;
import java.io.InputStream;
import java.net.URL;
public class MainActivity extends android.app.Activity {
final static String TAG = "AllInOne";
final static int CHANGE_INTERVAL = 30 * 1000; //30 sec for testing
static boolean loading = false;
WallpaperManager wm;
//Layout Views
Switch mSwitchFixedPhoto, mSwitchControls, mSwitchSave, mSwitchPause;
Spinner mSpinnerCategories, mSpinnerInterval;
EditText mEditTextHashtag;
Button mWallpaperButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Layout Views Initialized
mSwitchFixedPhoto = (Switch) findViewById(R.id.sw_fixedphoto);
mSwitchControls = (Switch) findViewById(R.id.switch_controls);
mSwitchSave = (Switch) findViewById(R.id.switch_save);
mSwitchPause = (Switch) findViewById(R.id.switch_pause);
mSpinnerCategories = (Spinner) findViewById(R.id.spinner_categories);
mSpinnerInterval = (Spinner) findViewById(R.id.spinner_interval);
mEditTextHashtag = (EditText) findViewById(R.id.et_hashtag);
mWallpaperButton = (Button) findViewById(R.id.btn_set_wallpaper);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapterCategory = ArrayAdapter.createFromResource(this,
R.array.categories_array, R.layout.dialog_spinner_layout);
// Specify the layout to use when the list of choices appears
adapterCategory.setDropDownViewResource(R.layout.dialog_spinner_layout);
// Apply the adapter to the spinner
mSpinnerCategories.setAdapter(adapterCategory);
ArrayAdapter<CharSequence> adapterInterval = ArrayAdapter.createFromResource(this,
R.array.interval_array, R.layout.dialog_spinner_layout);
adapterInterval.setDropDownViewResource(R.layout.dialog_spinner_layout);
mSpinnerInterval.setAdapter(adapterInterval);
mWallpaperButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PendingIntent pending = PendingIntent.getBroadcast(MainActivity.this,
666, new Intent("com.edip.splashwallpaper.CHANGE_WALLPAPTER_TIMER"),
PendingIntent.FLAG_CANCEL_CURRENT);
((AlarmManager) getSystemService(Context.ALARM_SERVICE))
.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),
CHANGE_INTERVAL, pending);
}
});
}
public void getPhoto() {
if (mEditTextHashtag.length() > 2) {
wm = WallpaperManager.getInstance(this);
int height = wm.getDesiredMinimumHeight();
int width = wm.getDesiredMinimumWidth();
String url = "https://source.unsplash.com/all/?" + mEditTextHashtag.getText() + "/" + width + "x" + height + "/";
try {
InputStream input = new URL(url).openStream();
Log.v(TAG, url);
wm.setStream(input);
input.close();
} catch (Exception e) {
e.printStackTrace();
}
loading = false;
} else {
Toast.makeText(this, "Something else", Toast.LENGTH_SHORT).show();
}
}
public static class Service extends IntentService {
public Service() {
super("wallpaperchanger-download");
}
#Override
protected void onHandleIntent(Intent intent) {
MainActivity mainActivity;
mainActivity = new MainActivity();
mainActivity.getPhoto();
}
}
public static class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
if (!loading) {
loading = true;
context.startService(new Intent(context, Service.class));
}
}
}
}
Thanks :)
First of all, you should never instantiate an activity by yourself.
Second, as a best practice, your service shouldn't know about your activity, or that it has an edit text. Instead you should send the URL to load inside your intent, when the PendingIntent is created, like this :
Intent intent = new Intent("com.edip.splashwallpaper.CHANGE_WALLPAPTER_TIMER");
intent.putExtra("USER_URL", "https://source.unsplash.com/all/?" + mEditTextHashtag.getText() + "/" + width + "x" + height + "/");
PendingIntent pending = PendingIntent.getBroadcast(MainActivity.this,
666, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Then within your service, read the url like so :
#Override
protected void onHandleIntent(Intent intent) {
String url = intent.getStringExtra("USER_URL");
// ...
}
I got this code from the Internet and I modified it to upload a specific file automatically to Google Drive when starting the activity.
It is always ask me to select my Google account when I start this activity!
I want it ask about Google account once only when started for the first time after install it, How to do that?
package com.example.googledrive;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import java.util.Arrays;
import java.io.IOException;
import android.accounts.AccountManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.widget.Toast;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.FileContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
public class MainActivity extends Activity {
static final int REQUEST_ACCOUNT_PICKER = 1;
static final int REQUEST_AUTHORIZATION = 2;
static final int REQUEST_DOWNLOAD_FILE = 3;
static final int RESULT_STORE_FILE = 4;
private static Uri mFileUri;
private static Drive mService;
private GoogleAccountCredential mCredential;
private Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setup for credentials for connecting to the Google Drive account
mCredential = GoogleAccountCredential.usingOAuth2(this, Arrays.asList(DriveScopes.DRIVE));
// start activity that prompts the user for their google drive account
startActivityForResult(mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
// mContext = getApplicationContext();
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data)
{
switch (requestCode) {
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null && data.getExtras() != null) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
mService = getDriveService(mCredential);
}
saveFileToDrive();
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == Activity.RESULT_OK) {
//account already picked
} else {
startActivityForResult(mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
break;
}
}
private Drive getDriveService(GoogleAccountCredential credential)
{
return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential)
.build();
}
private void saveFileToDrive()
{
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
// Create URI from real path
String path;
path = "/sdcard/DCIM/Camera/a.png";
mFileUri = Uri.fromFile(new java.io.File(path));
ContentResolver cR = MainActivity.this.getContentResolver();
// File's binary content
java.io.File fileContent = new java.io.File(mFileUri.getPath());
FileContent mediaContent = new FileContent(cR.getType(mFileUri), fileContent);
showToast("Selected " + mFileUri.getPath() + "to upload");
// File's meta data.
File body = new File();
body.setTitle(fileContent.getName());
body.setMimeType(cR.getType(mFileUri));
com.google.api.services.drive.Drive.Files f1 = mService.files();
com.google.api.services.drive.Drive.Files.Insert i1 = f1.insert(body, mediaContent);
File file = i1.execute();
if (file != null)
{
showToast("Uploaded: " + file.getTitle());
}
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
} catch (IOException e) {
e.printStackTrace();
showToast("Transfer ERROR: " + e.toString());
}
}
});
t.start();
}
public void showToast(final String toast)
{
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), toast, Toast.LENGTH_SHORT).show();
}
});
}
}
It's been a while, so you probably managed to do this by now, but I was just looking for the same thing and it's fairly easy. In the code you use and how it's used on several sites you get an Intent after calling a static method on GoogleAccountCredential.
You can also create your own, by calling a static method on AccountPicker and define a params that it's only required to pick once.
Intent accountPicker = AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null, null, null, null);
startActivityForResult(accountPicker, GOOGLE_ACCOUNT_PICKED);
The fourth param is what you want and you can read more about it here:
https://developers.google.com/android/reference/com/google/android/gms/common/AccountPicker?hl=en
I am getting the following exception when I run the texter application in android.
STACK_TRACE :
java.lang.NullPointerException at
com.texter.messenger.SmsReceiverService$ServiceHandler.handleMessage(SmsReceiverService.java:116)
at android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loop(Looper.java:123) at
android.os.HandlerThread.run(HandlerThread.java:60) , PHONE_MODEL :
GT-I9000 , ANDROID_VERSION : 2.2 , APP_VERSION_CODE : 10
30.Nov.2011 00:33:50 AM , CUSTOM_DATA : , STACK_TRACE : java.lang.IllegalArgumentException: Receiver not registered:
android.widget.ViewFlipper$1#40597cc0 at
android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:634) at
android.app.ContextImpl.unregisterReceiver(ContextImpl.java:881) at
android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:331)
at
android.widget.ViewFlipper.onDetachedFromWindow(ViewFlipper.java:104)
at android.view.View.dispatchDetachedFromWindow(View.java:6235) at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1250)
at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
at
android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
at
android.view.ViewRoot.dispatchDetachedFromWindow(ViewRoot.java:1838)
at android.view.ViewRoot.doDie(ViewRoot.java:2916) at
android.view.ViewRoot.die(ViewRoot.java:2886) at
android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:254)
at
android.view.Window$LocalWindowManager.removeViewImmediate(Window.java:445)
at
android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3182)
at
android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3287)
at android.app.ActivityThread.access$1600(ActivityThread.java:132)
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1042)
at android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loop(Looper.java:150) at
android.app.ActivityThread.main(ActivityThread.java:4293) at
java.lang.reflect.Method.invokeNative(Native Method) at
java.lang.reflect.Method.invoke(Method.java:507) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at
dalvik.system.NativeStart.main(Native Method).
I am new to these errors. How to solve these errors.
package com.texter.messenger;
import java.util.List;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.SmsMessage.MessageClass;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.texter.common.TexterConstants;
import com.texter.common.TexterNotification;
import com.texter.common.Utils;
import com.texter.data.TexterDB;
import com.texter.data.TexterDB.Schedule;
import com.texter.preferences.TexterPreferenceManager;
import com.texterpro.app.ConversationList;
import com.texterpro.app.R;
import com.texterpro.app.SmsPopupView;
public class SmsReceiverService extends Service {
private static final String LOG_TAG = TexterConstants.COMMON_TAG;
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED";
private static final String ACTION_MESSAGE_RECEIVED = "net.everythingandroid.smspopup.MESSAGE_RECEIVED";
private static final String MMS_DATA_TYPE = "application/vnd.wap.mms-message";
// https://android.googlesource.com/platform/packages/apps/Mms/+/master/src/com/android/mms/transaction/SmsReceiverService.java
public static final String MESSAGE_SENT_ACTION = "com.android.mms.transaction.MESSAGE_SENT";
/*
* This is the number of retries and pause between retries that we will keep
* checking the system message database for the latest incoming message
*/
private static final int MESSAGE_RETRY = 8;
private static final int MESSAGE_RETRY_PAUSE = 1000;
private Context context;
private ServiceHandler mServiceHandler;
private Looper mServiceLooper;
private int mResultCode;
private static final Object mStartingServiceSync = new Object();
private static PowerManager.WakeLock mStartingService;
private static final int TOAST_HANDLER_MESSAGE_SENT = 0;
private static final int TOAST_HANDLER_MESSAGE_SEND_LATER = 1;
private static final int TOAST_HANDLER_MESSAGE_FAILED = 2;
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("Log.LOGTAG",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
context = getApplicationContext();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
Log.v(LOG_TAG, "Oncreate");
}
#Override
public void onStart(Intent intent, int startId) {
Log.v(LOG_TAG, "OnStart");
mResultCode = intent != null ? intent.getIntExtra("result", 0) : 0;
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
#Override
public void onDestroy() {
mServiceLooper.quit();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
Log.v(LOG_TAG, "handlemessage:");
Log.v(LOG_TAG, msg.toString());
int serviceId = msg.arg1;
Intent intent = (Intent) msg.obj;
String action = intent.getAction();
String dataType = intent.getType();
if (ACTION_SMS_RECEIVED.equals(action)) {
handleSmsReceived(intent);
} else if (ACTION_MMS_RECEIVED.equals(action)
&& MMS_DATA_TYPE.equals(dataType)) {
handleMmsReceived(intent);
} else if (MESSAGE_SENT_ACTION.equals(action)) {
handleSmsSent(intent);
} else if (ACTION_MESSAGE_RECEIVED.equals(action)) {
handleMessageReceived(intent);
}
// NOTE: We MUST not call stopSelf() directly, since we need to
// make sure the wake lock acquired by AlertReceiver is released.
finishStartingService(SmsReceiverService.this, serviceId);
}
}
/**
* Handle receiving a SMS message
*/
private void handleSmsReceived(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
SmsMessage[] messages = Utils.getMessagesFromIntent(intent);
if (messages != null) {
notifyMessageReceived(new SmsMmsMessage(context, messages,
System.currentTimeMillis()));
}
}
}
private void notifyMessageReceived(SmsMmsMessage message) {
// Class 0 SMS, let the system handle this
if (message.getMessageType() == SmsMmsMessage.MESSAGE_TYPE_SMS
&& message.getMessageClass() == MessageClass.CLASS_0) {
return;
}
TelephonyManager mTM = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
boolean callStateIdle = mTM.getCallState() == TelephonyManager.CALL_STATE_IDLE;
/*
* If popup is enabled for this user -AND- the user is not in a call
* -AND- -AND- phone is not docked -AND- (screen is locked -OR- (setting
* is OFF to only show on keyguard -AND- user is not in messaging app:
* then show the popup activity, otherwise check if notifications are on
* and just use the standard notification))
*/
boolean isApp = TexterPreferenceManager.getInstance(this)
.isAppEnabled();
boolean showPop = TexterPreferenceManager.getInstance(this)
.isPopupEnabled();
boolean showNotify = TexterPreferenceManager.getInstance(this)
.isNotifyEnabled();
// Log.v(LOG_TAG," App = "+ isApp );
// Log.v(LOG_TAG," pop = "+showPop );
// Log.v(LOG_TAG," notify = "+showNotify );
// if conversationList is visible then do not show pop
if (!ConversationList.isVisible()) {
if (isApp && callStateIdle && showPop) {
// Log.v(LOG_TAG," showing popup = " );
if (!SmsPopupView.isPopupVisible())
context.startActivity(message.getPopupIntent());
}
}
if (isApp && showNotify) {
TexterNotification.ShowMessageNotification(this, message);
}
}
/**
* Handle receiving a MMS message
*/
private void handleMmsReceived(Intent intent) {
}
/**
* Handle receiving an arbitrary message (potentially coming from a 3rd
* party app)
*/
private void handleMessageReceived(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
}
}
/*
* Handler to deal with showing Toast messages for message sent status
*/
public Handler mToastHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg != null) {
switch (msg.what) {
case TOAST_HANDLER_MESSAGE_SENT:
// TexterNotification.showToast(SmsReceiverService.this,R.string.quickreply_sent_toast);
break;
case TOAST_HANDLER_MESSAGE_SEND_LATER:
TexterNotification.showToast(SmsReceiverService.this,
R.string.quickreply_failed_send_later);
break;
case TOAST_HANDLER_MESSAGE_FAILED:
TexterNotification.showToast(SmsReceiverService.this,
R.string.quickreply_failed);
break;
}
}
}
};
/*
* Handle the result of a sms being sent
*/
private void handleSmsSent(Intent intent) {
Log.v(LOG_TAG, "HandleSMSSent called");
PackageManager pm = getPackageManager();
Intent sysIntent = null;
Intent tempIntent;
List<ResolveInfo> receiverList;
boolean forwardToSystemApp = true;
// Search for system messaging app that will receive our
// "message sent complete" type intent
tempIntent = intent.setClassName(
SmsMessageSender.MESSAGING_PACKAGE_NAME,
SmsMessageSender.MESSAGING_RECEIVER_CLASS_NAME);
tempIntent.setAction(SmsReceiverService.MESSAGE_SENT_ACTION);
receiverList = pm.queryBroadcastReceivers(tempIntent, 0);
if (receiverList.size() > 0) {
sysIntent = tempIntent;
}
Bundle b = intent.getExtras();
long rowid = 0;
rowid = b == null ? 0 : b.getLong("ROWID");
/*
* No system messaging app was found to forward this intent to,
* therefore we will need to do the final piece of this ourselves which
* is basically moving the message to the correct folder depending on
* the result.
*/
// TexterNotification.showToast(SmsReceiverService.this,
// "before moving folder");
if (sysIntent == null) {
forwardToSystemApp = false;
Uri uri = intent.getData();
Log.v(LOG_TAG, "id = " + rowid);
if (mResultCode == Activity.RESULT_OK) {
SmsMessageSender.moveMessageToFolder(this, uri,
SmsMessageSender.MESSAGE_TYPE_SENT);
} else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF)
|| (mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) {
SmsMessageSender.moveMessageToFolder(this, uri,
SmsMessageSender.MESSAGE_TYPE_QUEUED);
} else {
SmsMessageSender.moveMessageToFolder(this, uri,
SmsMessageSender.MESSAGE_TYPE_FAILED);
}
}
// Check the result and notify the user using a toast
if (mResultCode == Activity.RESULT_OK) {
mToastHandler.sendEmptyMessage(TOAST_HANDLER_MESSAGE_SENT);
TexterDB.getInstance().updateStatus(rowid,
Schedule.STATUS_SCHEDULED_SENT, 0);
} else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF)
|| (mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) {
TexterDB.getInstance().updateStatus(rowid,
Schedule.STATUS_NOT_SENT, -1);
} else {
mToastHandler.sendEmptyMessage(TOAST_HANDLER_MESSAGE_FAILED);
TexterDB.getInstance().updateStatus(rowid,
Schedule.STATUS_NOT_SENT, mResultCode);
}
if (forwardToSystemApp) {
try {
PendingIntent.getBroadcast(this, 0, sysIntent, 0).send(
mResultCode);
} catch (CanceledException e) {
e.printStackTrace();
}
}
}
/**
* Start the service to process the current event notifications, acquiring
* the wake lock before returning to ensure that the service will run.
*/
public static void beginStartingService(Context context, Intent intent) {
synchronized (mStartingServiceSync) {
if (mStartingService == null) {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
mStartingService = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"Texter.SmsReceiverService");
mStartingService.setReferenceCounted(false);
}
mStartingService.acquire();
context.startService(intent);
Log.v(LOG_TAG, "service started");
}
}
/**
* Called back by the service when it has finished processing notifications,
* releasing the wake lock if the service is now stopping.
*/
public static void finishStartingService(Service service, int startId) {
synchronized (mStartingServiceSync) {
if (mStartingService != null) {
if (service.stopSelfResult(startId)) {
mStartingService.release();
}
}
}
}
}
Look at the top of the trace... look at the code at:
com.texter.messenger.SmsReceiverService$ServiceHandler.handleMessage(SmsReceiverService.java:116)
Looking at the code... check that the variable intent is not null before you call handleSmsReceived
I had the same bug, still looking for the correct solution but temporarily I just comment out the onDetachFromWindow() method. In my case it was for testing purpose so commenting it out didn't affect me but not sure what's in your case but give it a try.
In general, this question/answer gives an introduction to reading these errors:
What is a stack trace, and how can I use it to debug my application errors?
Looking at the code, intent should not be null, after all intent.getAction() executes without error.
It seems more likely that you have a problem with ViewFlipper, getting some "Receiver not registered" exception in the nested stack trace:
java.lang.IllegalArgumentException: Receiver not registered: android.widget.ViewFlipper$1#40597cc0
Maybe this question can point you in the right direction:
ViewFlipper : Receiver not registered