Switching between activities raises Thread error - java

I make an app with two windows, when I go from main window to the preferences one everything is fine, but when I try to return back to main activity app crashes with Thread already started error.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameView(this));
startService(new Intent(this, MyService.class));
}
public void onResume(){
super.onResume();
}
// Initiating Menu XML file (menu.xml)
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.layout.menu, menu);
return true;
}
public void onBackPressed() {
super.onBackPressed();
stopService(new Intent(this, MyService.class));
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
Update:
Here is the log from LogCat (I am using Eclipse):
09-30 11:59:17.348: D/AndroidRuntime(2917): Shutting down VM
09-30 11:59:17.348: W/dalvikvm(2917): threadid=1: thread exiting with uncaught exception (group=0x40aa7210)
09-30 11:59:17.368: E/AndroidRuntime(2917): FATAL EXCEPTION: main
09-30 11:59:17.368: E/AndroidRuntime(2917): java.lang.IllegalThreadStateException: Thread already started.
09-30 11:59:17.368: E/AndroidRuntime(2917): at java.lang.Thread.start(Thread.java:1045)
09-30 11:59:17.368: E/AndroidRuntime(2917): at com.examples.todolist.GameView$1.surfaceCreated(GameView.java:45)
The ManiFest file (activity from it):
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service
android:name="MusicService"
android:enabled="true">
</service>
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="PreferencesActivity"></activity>
<service android:enabled="true" android:name=".MyService" />
</application>
In my project I have MainActivity.java - which is main window, PreferencesActivity.java - which is preferences window, GameView.java - which is responsible for drawing stuff and GameManager.java - which controls FPS. In game view I have main, onDraw and onTouch events.
Here is main from GameView:
public GameView(Context context) {
super(context);
gameLoopThread = new GameManager(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
bmp1 = BitmapFactory.decodeResource(getResources(),
R.drawable.wall_sprite);
}
Here is a gameManager.java, since I figured out that it is something to do with run. I still trying to figure out how to make thread (or screen?) destroyed and then make it again.
public class GameManager extends Thread {
static final long FPS = 30;
private GameView view;
private boolean running = false;
// class constructor
public GameManager(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {
}
}
}
}

Ok here is the deal, surfaceCreated() seems to hold a thread, and that thread can only be started once and only once. That is the immediate issue.
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
// This is unsafe
gameLoopThread.start();
}
Without knowing the entire design of your app there are a few ways this can be triggered multiple times.
A Surface can be created, destroyed and then a new surface can be created. In this case, the GameView would have the same thread reference and try to start it again. So you have Activity-A with SurfaceView. Creates Surface, then you start another activity, your surface view will probably be destroyed around the time of the onPause(). You finish your Preferences and come back to your activity, onResume() gets called and your surface will be recreated ... firing twice. This is all assuming that your app goes something like this:
Activity -> PreferencesActivity -> original Activity.
You seem to start another task so I am unsure why you do that, but the old activity is still on the backstack, so if it resumes, it will probably recreate the surface.
Not sure what GameManager is required for but it looks like a run loop of some sort. You can either make sure it isn't started if it already is. Or if there is a case where there may be desired separate GameManager instances, you could keep track of multiple instances and make sure not to start them again.

Related

Android NFC Reader in MVP - onNewIntent not firing

I have a working NFC reader/writer code. Using the same code, I added the reader function in another app which is following MVP architecture.
The activity is named NFCReaderActivity. A separate NFC class is created (NFCReader), which implements Sensor interface.
The app is supposed to work both in the foreground and launch showing the NFC tag info. The launch part is working fine and app launches and reads the tag and shows its content.
However, in the foreground, on scanning, it does nothing. I only hear the scan beep but no onNewIntent is firing.
Below are the log entries captured for foreground and launch actions. There is a difference in the class names:
When not launching
I/ActivityManager: START u0 {act=android.nfc.action.NDEF_DISCOVERED typ=application/com.abc.vi flg=0x14008000 cmp=com.abc.vi/.ui.reader.NFCReader (has extras)} from uid 10038 on display 0
When launching
I/ActivityManager: START u0 {act=android.nfc.action.NDEF_DISCOVERED typ=application/com.abc.vi cmp=com.abc.vi/.ui.reader.NFCReaderActivity (has extras)} from uid 1027 on display 0
Activity
onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "__onCreate__ " );
setContentView(R.layout.activity_nfc_reader);
VI.setNFCReaderActivityContext(this); //VI is the Application class
ButterKnife.bind(this);
presenter = new ReaderPresenter(this);
}
onNewIntent
#Override
public void onNewIntent(Intent intent) {
Log.i(TAG, "__onNewIntent__ " );
// onResume gets called after this to handle the intent
// setIntent(intent);
presenter.onNewIntent(intent);
}
onResume, onPause
#Override
protected void onResume() {
super.onResume();
Log.i(TAG, "__onResume__ " );
presenter.onResume();
}
#Override
protected void onPause() {
super.onPause();
Log.i(TAG, "__onPause__ " );
presenter.onPause();
}
Presenter
ReaderPresenter(ReaderContract.View view) {
this.view = view;
initSensor();
}
#Override
public void initSensor() {
nfcReader = new NFCReader(VI.getNFCReaderActivityContext(), this); //VI is the Application class
}
#Override
public void onNewIntent(Intent intent) {
nfcReader.resolveIntent(intent);
}
#Override
public void onResume() {
nfcReader.onResume();
}
#Override
public void onPause() {
nfcReader.onPause();
}
#Override
public void onDestroy() {
speech.onDestroy();
}
NFCReader
public class NFCReader implements Sensors {
private static final String TAG = NFCReader.class.getSimpleName();
private NfcAdapter nfcAdapter;
private PendingIntent nfcPendingIntent;
private NFCReaderActivity activity;
private ReaderPresenter presenter;
NFCReader(NFCReaderActivity nfcReaderActivity, ReaderPresenter readerPresenter) {
this.activity = nfcReaderActivity;
this.presenter = readerPresenter;
init();
}
#Override
public void init() {
//Initialize NFC adapter
nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
nfcPendingIntent = PendingIntent.getActivity(activity, 0, new Intent(activity,
getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP), 0);
}
public void onResume() {
if (nfcAdapter != null) {
nfcAdapter.enableForegroundDispatch(activity, nfcPendingIntent, null, null);
// if NFC not enabled
if (!nfcAdapter.isEnabled()) {
new AlertDialog.Builder(activity)
.setPositiveButton(activity.getString(R.string.update_setting_btn),
(dialog, which) -> {
Intent setNfc = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
activity.startActivity(setNfc);
})
.setOnCancelListener(
dialog -> activity.finish()
)
.create().show();
}
resolveIntent(activity.getIntent());
} else {
Toast.makeText(VI.getAppContext(),
activity.getString(R.string.error_no_nfc_found), Toast.LENGTH_LONG).show();
}
}
public void onPause() {
if (nfcAdapter != null) {
nfcAdapter.disableForegroundDispatch(activity);
}
}
public void resolveIntent(Intent intent){
Log.i(TAG, "__resolveIntent__");
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
NdefMessage[] messages = null;
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
messages = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
messages[i] = (NdefMessage) rawMsgs[i];
}
}
if ((messages != null ? messages[0] : null) != null) {
StringBuilder result = new StringBuilder();
byte[] payload = messages[0].getRecords()[0].getPayload();
for (byte aPayload : payload) {
result.append((char) aPayload);
}
Log.i(TAG,"Decoded --> "+result.toString());
presenter.getData(result.toString());
}
}
}
}
Manifest
<activity android:name=".ui.reader.NFCReaderActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="#string/mime_type" />
</intent-filter>
</activity>
UPDATE
I moved all the code from NFCReader class to NFCReaderActivity and both foreground and launch modes are working. The issue is with MVP architecture. How to convert it back to MVP?
You seem to register the pending intent for the wrong (actually an invalid) component (not your activity class). The reason is that when you create the PendingIntent that you assign to nfcPendingIntent, you use getClass() to obtain the class of the NFCReader instance. Instead you would need to use activity.getClass() to obtain the class of your activity component.

Android app opens after a few seconds after pressing home button during splash screen

I am having an issue I can't seem to figure out the reason for.
When you launch the app, a splash screen is first displayed for 2.5 seconds before finishing and starting a new activity. If you press the home or back button during this time the app will close as normal. However after a few seconds (longer than 2.5) the app will open and start from the activity that comes after the splash screen.
Any help on why this happens is appreciated!
Here is the implementation of the Splash screen (I do however not believe anything here causes this issue as I've tried different implementations)
`public class SplashScreenActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
Thread myThread = new Thread(){
#Override
public void run() {
try {
sleep(2500);
Intent intent = new Intent(getApplicationContext(),MainActivity.class);
startActivity(intent);
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
myThread.start();`
Here's the manifest
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".activities.MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar"
android:launchMode = "singleInstance">
</activity>
<activity android:name=".activities.SplashScreenActivity"
android:theme="#style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".alert.BroadCaster" >
</receiver>
<service android:name=".timer.TimerService"
android:process=":timerservice" />
</application>
It happens because you are creating a new Thread and this thread will be still alive after you put your app in background. You can change your approach using an Handler. If you need that your next Activity won't start if the splash screen is in background, you have to store the current time before the delay starts.
private static final long SPLASH_SCREEN_MS = 2500;
private long mTimeBeforeDelay;
private Handler mSplashHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
// Create a new Handler.
mSplashHandler = new Handler();
}
#Override
protected void onResume() {
super.onResume();
// The first time mTimeBeforeDelay will be 0.
long gapTime = System.currentTimeMillis() - mTimeBeforeDelay;
if (gapTime > SPLASH_SCREEN_MS) {
gapTime = SPLASH_SCREEN_MS;
}
mSplashHandler.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
SplashScreenActivity.this.finish();
}
}, gapTime);
// Save the time before the delay.
mTimeBeforeDelay = System.currentTimeMillis();
}
#Override
protected void onPause() {
super.onPause();
mSplashHandler.removeCallbacksAndMessages(null);
}
Just use handler instead of thread sleep like this
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
SplashScreenActivity.this.finish();
}
}, SPLASH_DURATION);
You need to implement the onStop() method, only if you want to save data and memory.

my thread in java is showing errors [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am a beginner to android development. I have been trying to work this splashscreen with a audio file that kills itself after 3 secs. Then my Mainactivity is supposed to start. But my code is showing some error which i cannot figure out.the code n the java class is as follows:`
public class splash extends Activity {
MediaPlayer mySound;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
mySound=MediaPlayer.create(splash.this, R.raw.crowd_sound);
mySound.start();
}
Thread kill_Thread= new Thread(){
public void run(){
try {
sleep(3000);
Intent splash_intent=new Intent(splash.this,MainLFC.class);
startActivity(splash_intent);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
finish();
}
}
};
kill_Thread.start();
#Override
protected void onPause() {
super.onPause();
mySound.release();
}
}
the manifest file is as follows:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".splash"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainLFC"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.inten**strong text**t.action.MAINLFC" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
To get the behavior you pretend you must call your thread from within the onCreate method. For this you have two options, either keep using your thread and define it inside onCreate before calling it's start, or just use a Handler. Bellow theres your onCreate method for both options.
Using Thread.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
mySound=MediaPlayer.create(splash.this, R.raw.crowd_sound);
mySound.start();
Thread kill_Thread= new Thread(){
public void run(){
try {
sleep(3000);
Intent splash_intent=new Intent(splash.this,MainLFC.class);
startActivity(splash_intent);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
finish();
}
}
};
kill_Thread.start();
}
#Override
protected void onPause() {
super.onPause();
mySound.release();
}
Using Handler
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
mySound=MediaPlayer.create(splash.this, R.raw.crowd_sound);
mySound.start();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Intent splash_intent=new Intent(splash.this,MainLFC.class);
startActivity(splash_intent);
finish()
}
}, 3000);
}
#Override
protected void onPause() {
super.onPause();
mySound.release();
}
Starting a new activity should be done in the main (UI) thread.
If you want to communicate your thread with the main thread you can use a Handler and there start a new activity.
Example Handler:
Handler hander = new Handler(){
public void handleMessage(Message m){
Intent splash_intent=new Intent(splash.this,MainLFC.class);
startActivity(splash_intent);
}
};
Example sending a msg to the handler:
Thread kill_Thread= new Thread(){
public void run(){
try {
sleep(3000);
hander.sendMessage(Message.obtain());
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
finish();
}
}
};
kill_Thread.start();
try this outside your on create method:
public class kill_Thread extends Thread{
public void run(){
try {
sleep(3000);
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent splash_intent=new Intent(splash.this,MainLFC.class);
startActivity(splash_intent);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
finish();
}
}
};
where you declare your public variables set:
public kill_Thread kt;
and in your OnCreate call:
kt.start();

Splash Screen causes null pointer in Main Activity with AsyncTask

I'm trying to add a Splash Screen to my Android Rss Reader application, so that i can check network connectivity and determine which screen the user sees first, depending on connectivity.
Without the SplashScreen, the MainActivity.java works fine, but when I set SplashScreenActivity as the launcher within the Manifest, the Asynctask within MainActivity throws a null pointer when it runs. Does anybody know what the reason for this might be?
Thanks for your time!
SplashScreenActivity.java
enter code here
public class SplashScreenActivity extends MainActivity {
boolean alreadyExecuted = false;
private static String TAG = SplashScreenActivity.class.getName();
private static long SLEEP_TIME = 5;
#Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE); // Removes title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Removes notification bar
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
// Start timer and launch main activity
IntentLauncher launcher = new IntentLauncher();
launcher.start();
}
private class IntentLauncher extends Thread {
#Override
/**
* Sleep for some time and than start new activity.
*/
public void run() {
try {
// Sleeping
Thread.sleep(SLEEP_TIME*2000);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
//If this method is called once, set boolean alreadyExecuted to true
if(!alreadyExecuted)
{
Check();
alreadyExecuted=true;
}
}
}
//Check if network is available. If so go to MainActivity screen, which requires internet
//If not, go to MyFeeds screen
public void Check()
{
if (NetworkCheck.getInstance(this).isOnline()) {
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
SplashScreenActivity.this.startActivity(intent);
SplashScreenActivity.this.finish();
}
else
{
Intent intent = new Intent(SplashScreenActivity.this, MyFeedsScreen.class);
SplashScreenActivity.this.startActivity(intent);
SplashScreenActivity.this.finish();
}
}}
MainActivity.java
public class MainActivity extends Activity {
private MainActivity local;
private DatabaseHandler db;
//Method to create main application view
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
//**************************create a button to move to the user's saved feeds screen*****************************
Button myFeedsButton = (Button) findViewById(R.id.myFeedsButton);
myFeedsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
startActivity(new Intent(MainActivity.this, MyFeedsScreen.class));
}
});
//*****************************************************************************************************************
//Create new instance of database handler
db = new DatabaseHandler(this);
//set local ref to this activity
local = this;
//Calls the doInBackground method
GetRSSDataTask task = new GetRSSDataTask();
//start download Rss task - execute method calls the
task.execute("http://pitchfork.com/rss/reviews/best/albums/");
//debug thread name
Log.d("RssReaderApp", Thread.currentThread().getName());
}
//*******************************************************************************************************************
private class GetRSSDataTask extends AsyncTask<String, Void, List<RssItem>>
{
#Override
protected List<RssItem> doInBackground(String... urls) {
//debug task thread name
Log.d("RssReaderApp", Thread.currentThread().getName());
try {
//create a new reader
RssReader rssReader = new RssReader(urls[0]);
//Parse RSS, get items
return rssReader.getItems();
} catch (Exception e) {
Log.e("RssReaderApp", e.getMessage());
}
return null;
}//doInBackground
//is invoked on UI thread after background tasks are complete.
// Results of background task are passed here as a parameter
#Override
protected void onPostExecute(List<RssItem> result)
{
//Gets listview from main.xml
final ListView listItems = (ListView) findViewById(R.id.listMainView);
//Creates a new list adapter - displays an array of strings in listview
ArrayAdapter<RssItem> adapter = new ArrayAdapter<RssItem>(local, android.R.layout.simple_list_item_1, result);
//Set list adapter for listView
listItems.setAdapter(adapter);
//OnItemClick listener set to allow user to access content from title
listItems.setOnItemClickListener(new ListListener(result, local));
//*******************************LONG CLICK FUNCTIONALITY******************************************
//Set new long click listener which should allow item to be stored to db
listItems.setLongClickable(true);
listItems.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
try {
db.open();
RssItem fromList = (RssItem) listItems.getItemAtPosition(position);
RssItem item = new RssItem();
item.title = fromList.title;
item._id = fromList._id;
//item.completeTextLink = fromList.completeTextLink;
//item.mainBody = fromList.mainBody;
item.link = fromList.link;
item.description = fromList.description;
// item.page = fromList.page;
db.insertRssItem(item);
db.close();
} catch (SQLException e) {
e.printStackTrace();
}
Toast.makeText(getBaseContext(), "Item saved in My Feeds!", Toast.LENGTH_SHORT).show();
return true;
}
});
}//onPostExecute
}//getRssTaskClass}//class
Android Manifest, with SplashScreenActvity, rather than MainActivity now set as launcher:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:label="#string/app_name">
<activity android:name="com.example.rory.RssReaderApp.MainActivity">
</activity>
<activity android:name="com.example.rory.RssReaderApp.MyFeedsScreen"></activity>
<activity android:name=".DetailsActivity"></activity>
<activity android:name="com.example.rory.RssReaderApp.SplashScreenActivity">
android:icon="#drawable/newspaper"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
LogCat error:
08-19 02:23:52.467 15372-15372/com.example.rory.readerapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.rory.readerapp, PID: 15372
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
at com.example.rory.RssReaderApp.MainActivity$GetRSSDataTask.onPostExecute(MainActivity.java:113)
at com.example.rory.RssReaderApp.MainActivity$GetRSSDataTask.onPostExecute(MainActivity.java:79)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Try referencing your MainActivity in your onPostExecute when setting your listItems.
final ListView listItems = (ListView) local.findViewById(R.id.listMainView);
Solved the problem! I had accidentally made the SplashScreenActivity.java class extend MainActivity rather than Activity.
Thanks for the help guys!

Hang up and decline incoming call by custom activity[buttons] Android

I am just in process by learning Android a bit, and i have stumbled on this problem.
I want to do a "custom incoming call screen". My current Solution is a class(IncomingCallInterceptor) that extends from BroadcastReceiver. In IncomingCallInterceptor class i override the onReceive and starting my activity(MainActivity) with layout when the phone is ringing.
In that activity(MainActivity) i have three buttons:
Accept Call, Hang Up, Decline Call
Those buttons should do what they say, Answer the phone, hang up the phone or decline the call.
I have in someway got the Accept Call to work, but not Hang Up and Decline.
Heres my code below:
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.uppgift.six.one.incoming61.sixone" >
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name="IncomingCallInterceptor">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
</activity>
</application>
</manifest>
IncomingCallInterceptor that extends from BroadcastReceiver:
public class IncomingCallInterceptor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Context appContext = context.getApplicationContext();
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String msg = "Phone state changed to " + state;
if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
String incomingNumber = intent.getStringExtra
(TelephonyManager.EXTRA_INCOMING_NUMBER);
msg += ". Incoming number is this " + incomingNumber;
//START MY ACTIVITY!
Intent i = new Intent(appContext, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appContext.startActivity(i);
}
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
}
}
Here is my Activity(The Layout is nothing to post, just now is basically three buttons)
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnAnswer = (Button)findViewById(R.id.btnAnswer);
Button btnDecline= (Button)findViewById(R.id.btnDecline);
Button btnHangUp= (Button)findViewById(R.id.btnHangUp);
btnAnswer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON);
i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_HEADSETHOOK));
sendOrderedBroadcast(i, null);
}
});
btnDecline.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Decline Call (I need help here)
}
});
btnHangUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Hang Up Call (I need help here)
}
});
}
In the MainActivity class it is marked by comments where i need some help.
I have also seen something about a "Telephonyservice interface"(thingy) solution, but i don't understand how that worked when i was testing it.
Reject Call:
try {
TelephonyManager tm = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
try {
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
Object telephonyService = m.invoke(tm); // Get the internal ITelephony object
c = Class.forName(telephonyService.getClass().getName()); // Get its class
m = c.getDeclaredMethod("endCall"); // Get the "endCall()" method
m.setAccessible(true); // Make it accessible
m.invoke(telephonyService); // invoke endCall()
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
}

Categories