I am using the below code to Play Audio file (.wav), but it plays the file with Echo(like playing two voice simultaneously) when activity is in Landscape mode.
public class Find_n_Display_StationActivity extends Activity
{
GPSTracker gps;
TextView txtvw,locNameTV;
boolean calculating_distance=false;
ArrayList<String>data=new ArrayList<String>();
ArrayList<String>latArray=new ArrayList<String>();
ArrayList<String>longArray=new ArrayList<String>();
MySQLiteHelper db = new MySQLiteHelper(this);
ImageView profileIV;
PendingIntent intent;
String reached_station="empty";
MediaPlayer mp;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.find_n__display__statn_activity);
txtvw=(TextView)findViewById(R.id.textView2);
locNameTV=(TextView)findViewById(R.id.textView1);
profileIV=(ImageView)findViewById(R.id.image11);
profileIV.setVisibility(View.GONE);
//Put in LANDSCAPE MODE...
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//Show FULL-SCREEN Activity
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//Calling/Starting Thread to Handl Uncaught Exeption
Thread.setDefaultUncaughtExceptionHandler(onRuntimeError);
//(((( This will retrieve DATA from service to this Activity ))))
gps = new GPSTracker(this);
LocalBroadcastManager.getInstance(this.getApplicationContext()).registerReceiver(
mMessageReceiver, new IntentFilter("GPSLocationUpdates"));
// mp=new MediaPlayer();
}//EOF Oncreate Method...
//(((( This Function is Called if App Crash, So, App is start Automatically after crash ))))
private Thread.UncaughtExceptionHandler onRuntimeError= new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread thread, Throwable ex)
{
Intent i=new Intent(getApplicationContext(),MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
};
// (((( This Class Get Data From Service class GPSTracker.class() ))))
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String message = intent.getStringExtra("Status");
Bundle b = intent.getBundleExtra("Location");
Location lastKnownLoc = (Location) b.getParcelable("Location");
if (lastKnownLoc != null)
{
String s1=String.valueOf(lastKnownLoc.getLatitude());
String s2=String.valueOf(lastKnownLoc.getLongitude());
double current_lat=Double.parseDouble(s1);
double current_long=Double.parseDouble(s2);
txtvw.setText("____________________________\n\n\n"+current_lat+"\n"+current_long);
//showtoast("You have changed your Location");
if(calculating_distance==false)
{
calculating_distance=true;
FindDistance(current_lat,current_long);
}
Turn_On_Screen();
}
}};
private String stationPlayed="empty";
#SuppressWarnings("deprecation")
public void Turn_On_Screen()
{
WakeLock screenLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
screenLock.acquire();
//later
//screenLock.release();
}
//(((( Find Distance Betwee All Points ))))))
public void FindDistance(double current_lat,double current_long)
{
Move_App_Back_to_ForeGround();
ArrayList<String>stationNameArray=new ArrayList<String>();
ArrayList<String>imageArray=new ArrayList<String>();
ArrayList<String>voiceArray=new ArrayList<String>();
imageArray=db.Get_ImageList();
voiceArray=db.Get_VoiceList();
stationNameArray=db.Get_StionNameAraay();
latArray=db.Get_LatAraay();
longArray=db.Get_LongAraay();
float smallest_dis=10000;
String next_station="";
boolean found_station=false;
for(int i=1;i<latArray.size();i++)
{
float lat1 = Float.parseFloat(latArray.get(i));
float long1 = Float.parseFloat(longArray.get(i));
float dis=FindDistance((float)current_lat,(float)current_long,lat1, long1);
if(dis<smallest_dis)
{
smallest_dis=dis;
next_station=stationNameArray.get(i);
}
if(dis<=50)
{
Set_Pic_n_Voice(imageArray.get(i),voiceArray.get(i),stationNameArray.get(i));
// showtoast("station-name="+ stationNameArray.get(i));
break;
}
}
locNameTV.setText("You are Heading towards Station="+next_station+"\n You are only "+smallest_dis+" Meter away...");
calculating_distance=false;
}
public void Set_Pic_n_Voice(String image,final String voice,final String station_name)
{
DisplayImage(image);
if(!reached_station.equalsIgnoreCase(station_name))
reached_station=""+station_name; //Don't play voice for same station just display pic always
//Wait for 4 seconds to play this voice
Runnable r = new Runnable()
{
public void run()
{
if(!stationPlayed.equalsIgnoreCase(station_name))
{
PlayVoice(voice);
stationPlayed=station_name;
}
}
};
android.os.Handler h = new android.os.Handler();
h.postDelayed(r, 5000);// */
}
//(((( Displaying Picture For the Station ))))
public void DisplayImage(String image)
{
profileIV.setVisibility(View.VISIBLE);
File imageFile = new File(Environment.getExternalStorageDirectory()+File.separator+"Bus_StationApp_Folder/Images",image);
if (imageFile.exists())
{
File imgFile = new File(imageFile.getAbsolutePath()); // path of your file
Picasso.with(this).load(Uri.fromFile(new File(imageFile.getAbsolutePath()))).into(profileIV);
/*
FileInputStream fis = null;
try {
fis = new FileInputStream(imgFile);
} catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 8;
//options.inPurgeable = true;
// options.inScaled = true;
Bitmap bm = BitmapFactory.decodeStream(fis, null,options);
profileIV.setImageBitmap(bm);//*/
}
else
profileIV.setImageResource(R.drawable.default_station_pic);
}
//(((( Playing Voice For The Station ))))))
public void PlayVoice(String voice)
{
calculating_distance=true;
// Play_Audio_File ob=new Play_Audio_File(this);
//ob.PlayVoice(voice);
File voiceFile = new File(Environment.getExternalStorageDirectory()+File.separator+"Bus_StationApp_Folder/Voices",voice);
if (voiceFile.exists())
{
if(!mp.isPlaying())
{
mp.reset();
try {
mp.setDataSource(voiceFile.getAbsolutePath());
mp.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
}
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer mp)
{
calculating_distance=false;
}
});
}
else
{
//mp.reset();
mp= MediaPlayer.create(this, R.drawable.default_station_voice);
if(!mp.isPlaying())
{
mp.start();
}
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer mp)
{
calculating_distance=false;
}
});
}
//*/
}
//((((( Find distance between two geolocation )))
public float FindDistance(float lat1, float lng1, float lat2, float lng2)
{
double earthRadius = 6371000; //meters
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
float dist = (float) (earthRadius * c);
return dist;
}
//((( Move App To Screen from Background ))))
public void Move_App_Back_to_ForeGround()
{
boolean foregroud=false;
try
{
foregroud = new ForegroundCheckTask().execute(getApplicationContext()).get();
} catch (InterruptedException e)
{ e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
if(!foregroud)
{
//Open Activity IF it is in Background...
Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(this.getPackageName(), Find_n_Display_StationActivity.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.getApplicationContext().startActivity(it);
}
}
class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {
#Override
protected Boolean doInBackground(Context... params) {
final Context context = params[0].getApplicationContext();
return isAppOnForeground(context);
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
//SHOW-TOAST-MESSAGE
public void showtoast(String str)
{
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show();
}
public void OnBackPressed()
{
}
}//EOF Activity...
You are somehow calling the PlayVoice() method twice. The reason your inner if statement isn't preventing this is because you must be calling mp = new MediaPlayer(); before calling PlayVoice(), otherwise the first call to that method would result in a NullPointerException from the mp.isPlaying() call in the if condition. Since mp now points to a new MediaPlayer instance, isPlaying() returns false, and the if block executes again, even though the previous instance is still playing.
To prevent multiple instances of MediaPlayer playing concurrently, instantiate the MediaPlayer only once in the declaration line, remove the mp = new MediaPlayer(); line in PlayVoice() (and anywhere else you might have it), and un-comment the mp.reset(); call there.
The PlayVoice() method is being called twice because you're requesting an orientation change to landscape in the Activity's onCreate() method, and you're not handling configuration changes yourself. This is causing the Activity started in portrait mode to be destroyed and recreated, which means that onCreate() runs a second time, but the MediaPlayer started in the first Activity instance is still playing when a new one is created and started in the second instance.
You can prevent this from happening by forcing the Activity to launch in a landscape orientation from the start. You can do this by adding android:screenOrientation="landscape" to the <activity>'s tag in the manifest. You can also remove the setRequestedOrientation() call now, as it is no longer needed.
Related
I am creating a class witch loads up a few sounds. However, isPlaying keeps on throwing an exception after a while and then stops playing that particular sound permanently, while other sounds keep playing OK.
public class MySound {
int m_IdMyId;
int m_ResId;
boolean m_IsLoaded;
MediaPlayer m_Media;
public MySound(int idMyId, int resId){
m_IdMyId = idMyId;
m_ResId = resId;
m_IsLoaded = false;
m_Media = null;
}
}
In this m_IdMyId is just an id for my game. m_ResId is something like R.raw.mysound1. m_IsLoaded I think is automatically set to true as I am loading synconously. m_Media is the MediaPlayer object.
I am calling stop() very regularly, as it is a game and I need to check every second or so to make sure certain sounds are stopped. It is here that it throws an exception when snd.m_Media.isPlaying() is called.
I cannot seem to access e to see what the error is.
Also I would like to know how I can set m_IsLoaded correctly. How do I know when the sound is fully loaded and ready to use?
Here is my management class:
public class MySoundManager {
MainActivity m_Context;
ArrayList<MySound> mySounds;
public MySoundManager(MainActivity context) {
m_Context = context;
mySounds = new ArrayList<MySound>();
mySounds.add(new MySound(8, R.raw.mysound1));
mySounds.add(new MySound(10, R.raw.mysound2));
mySounds.add(new MySound(22, R.raw.mysound3));
mySounds.add(new MySound(100, R.raw.click));
mySounds.add(new MySound(101, R.raw.error));
for(MySound mysound : mySounds) {
mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
mysound.m_IsLoaded = true;
}
}
// I call this when the main thread calls onResume
public void onResume(){
for(MySound mysound : mySounds) {
if(mysound.m_Media == null) {
mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
mysound.m_IsLoaded = true;
}
}
}
// I call this when the main thread calls onPause
public void onPause(){
for(MySound mysound : mySounds) {
if(mysound.m_Media != null) {
mysound.m_Media.stop();
mysound.m_Media.release();
mysound.m_Media = null;
}
}
}
public boolean IsAllLoaded(){
for(MySound mysound : mySounds) {
if(!mysound.m_IsLoaded) return false;
}
return true;
}
public MySound FindMySoundByIdMyId(int idMyId){
try {
for(MySound mysound : mySounds) {
if (mysound.m_IdMyId == idMyId) return mysound;
}
}catch(Exception e) {
MySound snd;
snd = null; // ToDo
}
return null;
}
public void play(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null)
snd.m_Media.start();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
public void pause(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null &&
snd.m_Media.isPlaying())
snd.m_Media.pause();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
public void pauseAll(){
try{
for (MySound mysound : mySounds) {
if(mysound.m_Media.isPlaying())
mysound.m_Media.pause();
}
}catch(IllegalStateException e) {
MySound snd;
snd = null; // ToDo
}
}
public boolean isPlaying(int idMyId, MySound[] fill){
MySound snd;
fill[0] = null;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null){
fill[0] = snd;
return snd.m_Media.isPlaying();
}
}catch(IllegalStateException e) {
snd = null; // ToDo
}
return false;
}
public void stop(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null &&
snd.m_Media.isPlaying())
snd.m_Media.stop();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
// The str is in the format
// number id, 1 = on 0 = off,dont play if this id playing;
public void PlaySound(String str) {
boolean isplaying;
int i, len, id, idDontPlay, milliNow;
String[] strARR = str.split(";");
String[] strARR2;
Integer[] tmpIntARR;
ArrayList<Integer[]> onARR = new ArrayList<Integer[]>();
ArrayList<Integer> offARR = new ArrayList<Integer>();
MySound snd;
for (i = 0, len = strARR.length; i < len; i++) {
if(strARR[i].length() <= 0) continue;
if((strARR2 = strARR[i].split(",")) != null &&
strARR2.length >= 3 &&
strARR2[0].length() > 0 &&
strARR2[1].length() > 0 &&
strARR2[2].length() > 0){
id = Integer.parseInt(strARR2[0]);
idDontPlay = Integer.parseInt(strARR2[2]);
tmpIntARR = new Integer[2];
tmpIntARR[0] = id;
tmpIntARR[1] = idDontPlay;
if(Integer.parseInt(strARR2[1]) == 1){
onARR.add(tmpIntARR);
} else offARR.add(id);
}
}
// Turn off all sounds that need to be turned off
for (i=0,len=offARR.size();i<len;i++) {
id = offARR.get(i);
stop(id);
}
// Turn all sounds that need to be turned on,
// but only if the sound that blocks a new sound is not playing
for (i=0,len=onARR.size();i<len;i++) {
tmpIntARR = onARR.get(i);
id = tmpIntARR[0];
idDontPlay = tmpIntARR[1];
// We dont play if the idDontPlay sound is already playing
if((snd = FindMySoundByIdMyId(idDontPlay)) != null &&
snd.m_Media.isPlaying())
continue;
if((snd = FindMySoundByIdMyId(id)) != null){
isplaying = snd.m_Media.isPlaying();
milliNow = snd.m_Media.getCurrentPosition();
if(milliNow > (snd.m_Media.getDuration() - 1000) ||
(!isplaying && milliNow > 0)){
snd.m_Media.seekTo(0); // Half a second inside
}
if(!isplaying) snd.m_Media.start();
}
}
}
}
Creating a MediaPlayer instance for every sound is not a good practice to get low latency, especially for short clips. MediaPlayer is for longer clips such as Music files it uses large buffer so, larger buffer means high latency. Also, there is AudioFocus mechanism on Android that may interfere your sound playing session. So, I strongly recommend you to use SoundPool to play short clips like game sounds.
I'm using viewpager to show music and on swip left/right changing music according to that.When i swip viewpager it takes few sec in swip(it doesnot swip smoothly).
Code:
#Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
if (mCurrentPage > arg0) {
try {
Constant.position--;
musicService = new Intent(getApplicationContext(),
MusicService.class);
musicService.putExtra(Constant.NEXT, Constant.PREVIOUS);
startService(musicService);
musicService = null;
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
Constant.position++;
musicService = new Intent(getApplicationContext(),
MusicService.class);
musicService.putExtra(Constant.NEXT, Constant.NEXT);
startService(musicService);
musicService = null;
} catch (Exception e) {
e.printStackTrace();
}
}
mCurrentPage = arg0;
}
whenever I remove this code from onPageSelected, it swip smoothly. I had also putted this code inside handler but no befinits same issue.
Suggest me where I'm doing wrong and how to resolver this.
Update:
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
mThread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
sPosition = Constant.position;
if (intent != null) {
try {
mPrevious = (String) intent.getExtras().get(
Constant.NEXT);
System.out.println("value of previous=" + mPrevious);
if (mPrevious.equalsIgnoreCase(Constant.PLAY)) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
cancelNotification();
} else {
mediaPlayer.start();
buildNotification(title, album);
}
} else if (mPrevious
.equalsIgnoreCase(Constant.PREVIOUS)) {
playPrevious();
} else if (mPrevious.equalsIgnoreCase(Constant.NEXT)) {
playNext();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
mThread.start();
return START_NOT_STICKY;
}
From the guide topic Services:
Caution: A services runs in the same process as the application in which it is declared and in the main thread of that application, by default. So, if your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service will slow down activity performance. To avoid impacting application performance, you should start a new thread inside the service
Make sure your music service starts a thread to delegate work to.
I had written certain code such that my android app should go to airplane mode and come back to connected mode with the network for around some time until i close the application forcibly.
Its working with the code I had written but the problem is that the screen or display is not showing the flight symbol.
When I go to settings, I can see that the code is enabling and disabling the air plane mode properly.
Can any one please give me a solution for this.
My code is as follows
public class Airplane_ModeActivity extends Activity implements Runnable{
private static final int SLEEP_TIME_VALUE = 10000;
private static Context context;
private static ContentResolver contentResolver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = getApplicationContext();
contentResolver = context.getContentResolver();
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", false);
sendBroadcast(intent);
Runnable runnable = new Airplane_ModeActivity();
Thread thread = new Thread(runnable);
thread.start();
}
public void run(){
while(true) {
while(0==Settings.System.getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 0) ) {
Settings.System.putInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 1);
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
}
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
while(1==Settings.System.getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 1) ) {
Settings.System.putInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 0);
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
}
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
}
}
}
boolean isEnabled = Settings.System.getInt(thisActivity.getContentResolver(),Settings.System.AIRPLANE_MODE_ON, 0) == 1;
Settings.System.putInt(thisActivity.getContentResolver(),Settings.System.AIRPLANE_MODE_ON,isEnabled ? 0 : 1);
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", !isEnabled);
sendBroadcast(intent);
Check with this one., I think this will help you ..
I have an Android activity that is launching a child activity, which runs Sygic navigation on a surfaceview.
Launching the child activity works great, the navigation starts up. However, when they exit out of the Sygic application, I want to close the child activity and return back to showing the parent activity. As you can see, in the Finish() method I've tried calling both this.finish(); and getParent().finish(); however neither are working. All it does is show a black screen, which I'm guessing is the surface view. Any ideas how I can get it to successfully close the child activity and show the parent activity again?
Here is the code to launch the child activity:
NavigationActivity.SygicModule = this;
Log("Creating intent for navigation activity");
Intent intent = new Intent(getActivity(), NavigationActivity.class);
Log("Starting navigation activity");
getActivity().startActivity(intent);
Here is the xml for the child navigation activity view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/layout">
<SurfaceView android:id="#+id/surfaceView" android:layout_height="match_parent" android:layout_width="match_parent"></SurfaceView>
</LinearLayout>
And here is the code for the child navigation activity:
package ti.sygic;
public class NavigationActivity extends SygicDriveActivity {
private static final String LCAT = "SygicModule";
private static SError error = new SError();
private static Activity currentActivity = null;
public static SygicModule SygicModule;
private Handler mHandler = new Handler();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
currentActivity = this;
super.onCreate(savedInstanceState);
try {
setContentView(TiRHelper.getApplicationResource("layout.sygicmain"));
final ApiCallback apicallback = new ApiCallback() {
public void onRunDrive() {
try {
final SurfaceView surface = (SurfaceView) findViewById(TiRHelper.getApplicationResource("id.surfaceView"));
mHandler.post(new Runnable() {
public void run() {
runDrive(surface, getPackageName()); // starts the drive app
}
});
} catch (ResourceNotFoundException e) {
// TODO Auto-generated catch block
Log("Failed to find id.surfaceView!");
e.printStackTrace();
} // surface
}
public void onInitApi() // gets called after runDrive();
{
// code to make sure that gps is enabled before initializing
Log("Checking that gps is enabled");
String provider = "com.android.settings.widget.SettingsAppWidgetProvider";
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.NO_REQUIREMENT);
criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
criteria.setCostAllowed(false);
ContentResolver contentResolver = getContentResolver();
if (!Settings.Secure.isLocationProviderEnabled(contentResolver, LocationManager.GPS_PROVIDER)) {
Log("Gps is not enabled, showing gps settings");
final Intent poke = new Intent();
poke.setClassName("com.android.settings", provider);
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
}
int status = ApplicationAPI.InitApi(getPackageName(), true, msgHandler); // api initialization
Log("Status = " + Integer.toString(status));
if (status != 1) {
Log("InitApi failed! " + status);
}
else {
//start checking every second if application is running. if it isn't then finish this and parent activities.
//note: we wouldn't have to do this if APP_EXIT event actually fired. :(
CheckIfRunning();
}
}
};
ApplicationAPI.startDrive(apicallback);
} catch (ResourceNotFoundException e1) {
Log("Failed to find resource!");
e1.printStackTrace();
}
}
public static void navigateTo(Float latitude, Float longitude) {
try
{
Log("navigateTo: " + latitude + " / " + longitude);
Integer lat = (int)(latitude * 100000);
Integer lon = (int)(longitude * 100000);
//start navigation.
Log("Starting navigation for " + lat + " / " + lon);
SWayPoint wayPoint = new SWayPoint();
wayPoint.SetLocation(lat, lon);
ApplicationAPI.StartNavigation(error, wayPoint, 0, true, true, 0);//NavigationParams.NpMessageAvoidTollRoadsUnable
Log("Start navigation result: " + error.nCode + " " + error.GetDescription());
//if waiting for gps, call in a bit.
if(error.nCode == -6)
{
Thread.sleep(5000);
navigateTo(latitude, longitude);
}
}
catch(Exception exc)
{
Log(exc.getMessage());
}
}
final ApplicationHandler msgHandler = new ApplicationHandler() {
#Override
public void onApplicationEvent(int nEvent, String strData) {
Log("Event No. " + Integer.toString(nEvent) + " detected."); // event handling
switch (nEvent) {
case ApplicationEvents.EVENT_APP_EXIT:
Log("In EVENT_APP_EXIT event");
Finish();
break;
case ApplicationEvents.EVENT_WAIPOINT_VISITED:
Log("Waypoint visited.");
break;
case ApplicationEvents.EVENT_ROUTE_COMPUTED:
Log("Route computed.");
break;
case ApplicationEvents.EVENT_ROUTE_FINISH:
Log("Route finished.");
break;
case ApplicationEvents.EVENT_POI_WARNING:
Log("Poi warning!.");
break;
case ApplicationEvents.EVENT_CHANGE_LANGUAGE:
Log("Language changed.");
break;
case ApplicationEvents.EVENT_EXIT_MENU:
Log("Menu exited.");
break;
case ApplicationEvents.EVENT_MAIN_MENU:
Log("Entering main menu.");
break;
case ApplicationEvents.EVENT_BORDER_CROSSING:
Log("Crossing border.");
}
}
};
private void CheckIfRunning()
{
new Thread(new Runnable() {
#Override
public void run() {
try
{
int numTimesNotRunning = 0;
while(true)
{
boolean isRunning = ApplicationAPI.IsApplicationRunning(error, 0) == 1;
if(isRunning)
{
Log("App is running, will check again in 2 seconds");
numTimesNotRunning = 0;
Thread.sleep(2000);
}
else {
if(numTimesNotRunning < 3)
{
numTimesNotRunning++;
Log("App not running, num times " + numTimesNotRunning);
Thread.sleep(2000);
}
else
break;
}
}
Log("App is not running, calling sygicmodule finish!");
Finish();
}
catch(Exception exc)
{
Log(exc.getMessage());
}
}
}).start();
}
private void Finish()
{
Log("In NavigationActivity Finish");
runOnUiThread(new Runnable() {
public void run() {
try
{
//launch parent activity.
Log("Starting parent activity");
Intent intent = new Intent(currentActivity, SygicModule.getActivity().getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
currentActivity.startActivity(intent);
//finish current activity.
Log("Finishing activity");
//setContentView(null);
currentActivity.finish();
}
catch(Exception exc)
{
Log(exc.getMessage());
}
}
});
}
private static void Log(String message) {
//org.appcelerator.kroll.common.Log.i(LCAT, message);
if(message != null && message.length() > 0)
android.util.Log.i(LCAT, message);
}
}
You will have to reference the parent activity instead of just calling finish();
i.e. YourActivityClassName.this.finish();
Would cause your activity to finish, Make sure to add this call on the DriveEvent.EVENT_APP_EXIT and your activity should close moments after Sygic has exited
I was wondering how to use a handler in android to send two messages from a separate thread to update UI. The thread is declared in another file. I understand that using java Thread is not desirable in Android, but I have given up using android methods, they are terrible. The handler messages are sent every 200 miliseconds from my declared thread. I cannot find a decent example of how to implement it.
Here is my extended thread. This is called from the activity.
import java.io.IOException;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Message;
public class MPlayer extends Thread {
private volatile boolean playing = false;
private volatile boolean finished = false;
MediaPlayer player;
Message msg;
Bundle bundle;
String filepath;
/* other fields, constructor etc. */
public MPlayer(String path) {
filepath = path;
player = new MediaPlayer();
bundle = new Bundle();
msg = new Message();
start();
}
public void seekMPlayer(int i) {
// TODO Auto-generated method stub
player.seekTo(i);
}
public boolean getPlaying() {
// TODO Auto-generated method stub
return playing;
}
#Override
public void run() {
try {
player.setDataSource(filepath);
player.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (!finished) {
while (playing && !finished) {
try {
Thread.sleep(200);
if (playing && !finished) {
bundle.putString("progval", songTime());
// msg.setData(bundle);
// threadHandler.sendMessage(msg);
} else
break;
} catch (InterruptedException e) {
}
}
}
}
public synchronized void pauseMPlayer() {
playing = false;
player.pause();
}
public synchronized void PlayMPlayer() {
playing = true;
player.start();
// call notify() here when you switch to wait/notify.
}
public void stopMPlayer() {
playing = false;
finished = true;
player.release();
// call notify() here too.
}
private String songTime() {
// TODO Auto-generated method stub
if (filepath != null) {
int progressseconds = (int) ((player.getCurrentPosition() / 1000) % 60);
int progressminutes = (int) ((player.getCurrentPosition() / 1000) / 60);
int durationseconds = (int) ((player.getDuration() / 1000) % 60);
int durationminutes = (int) ((player.getDuration() / 1000) / 60);
String progmin, progsec, durmin, dursec;
if (progressminutes >= 10)
progmin = Integer.toString(progressminutes);
else
progmin = "0" + Integer.toString(progressminutes);
if (progressseconds >= 10)
progsec = Integer.toString(progressseconds);
else
progsec = "0" + Integer.toString(progressseconds);
if (durationminutes >= 10)
durmin = Integer.toString(durationminutes);
else
durmin = "0" + Integer.toString(durationminutes);
if (durationseconds >= 10)
dursec = Integer.toString(durationseconds);
else
dursec = "0" + Integer.toString(durationseconds);
return (progmin + ":" + progsec + "/" + durmin + ":" + dursec);
} else {
return ("No File!");
}
}
}
Handler should bind a Looper of the thread. Use this constructor to specify a thread looper
Handler handler = new Handler(Looper.getMainLooper());
And now the you can send message to the main thread
There is nothing wrong in using Java threads in Android but it is a bit overkill to use it just for sending periodic messages. The recommended way to do it is to use Handler.postDelayed. This article suggests following method: put all your updating code into a Runnable and add postDelayed call to the end of this Runnable's run() to schedule it again. This approach eliminates overhead of having a background thread.
However it is easy to use Handler to send messages from the other thread. As I understand you are trying to send messages to some UI component so it can update itself.
In my application I faced a similar problem. I declared a handler inside the UI component and passed this handler to a background thread in a constructor parameter.
The UI part looks like:
class MyActivity extends Activity {
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
// update UI according to a content of msg from background thread
// ...
}
};
private Thread mBackgroundWorker = new BackgroundThread(mHandler);
protected void onCreate(Bundle savedInstanceState) {
// ...
mBackgroundWorker.start();
// ...
}
protected void onDestroy() {
// we created the thread in this activity
// so we should manage its lifecycle here
mBackgroundWorker.interrupt();
}
}
And the background thread is implemented like
class BackgroundThread extends Thread {
private final mHandler;
public BackgroundThread(Handler h) {
mHandler = h;
}
public void run() {
// do some processing...
mHandler.sendMessage(/*some message to update an UI*/);
// ...
}
}