My goal is to have UDP packets receiving app continuously running from boot up in the back ground when ever it receives the valid packet it has to process the message and display them.
After some research, I did the following.
Broadcast Receiver class - which start the service on boot UP (mstart.java).
Service Class to monitor for UDP packets (udp.java).
Display Class to display the messages as text (Rmsgs.java).
GlobalState.Java for Global variable.
I wrote a standalone with UDP app with list view it works fine. Hence, I know there is no problem on that.
When I compiled ran the code service start on boot and then crashes. To debug I have taken away the UDP Packet receiving part. The UDP class after receiving the packets it will produce two arrays list and will save it in the Global class and the Display class will obtain it.
This code is working now, I found mistake I have made and corrected it.
Now I have to modify to receive the udp packets.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.QUICKBOOT_POWERON"/>
<application
android:name="com.mmm.rmsg.GlobalState"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:largeHeap="true"
android:theme="#style/AppTheme" >
<activity
android:name=".MsgView"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:enabled="true" android:exported="true"
android:name=".mstart"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name=".udp"
/>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
Broadcast Receiver Class
package com.mmm.rmsg;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class mstart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Intent detcted.", Toast.LENGTH_LONG).show();
Intent pushIntent = new Intent(context, udp.class);
context.startService(pushIntent);
}
}
Service Class
package com.mmm.rmsg;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.PowerManager;
import android.widget.Toast;
import java.util.ArrayList;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
public class udp extends Service {
private static final String LOG_TAG =udp.class.getSimpleName();
GlobalState gs = (GlobalState)getApplication();
#Override
public IBinder onBind(Intent arg0){
return null;
}
#Override public int onStartCommand(Intent intent, int flags, int startId) {
setWakeLock();
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
new Thread(new Server()).start();
return START_STICKY;
}
private void setWakeLock(){
PowerManager.WakeLock mWakeLock;
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakeLock=powerManager.newWakeLock(PARTIAL_WAKE_LOCK, LOG_TAG);
}
public class Server implements Runnable {
#Override
public void run() {
ArrayList<String> list = new ArrayList<>();
ArrayList<String> clist = new ArrayList<>();
// here udp packets are recvd & processed into 2 list arrays
list.add(0, "MAIN FAIL");
list.add(1,"BOILER HEATER 20C");
list.add(2, "COOLING NEED ATT");
clist.add(0, "6");
clist.add(1,"1");
clist.add(2, "5");
GlobalState gs = (GlobalState)getApplication();
gs.setGmlist(list);
gs.setGclist(clist);
call();
}
}
public void call() {
Intent dialogIntent = new Intent(getBaseContext(), MsgView.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dialogIntent);
}
}
Global Class
package com.mmm.rmsg;
import java.util.ArrayList;
import android.app.Application;
public class GlobalState extends Application
{
private ArrayList<String> Gmlist = new ArrayList<>();
private ArrayList<String> Gclist = new ArrayList<>();
private boolean chk = true;
private boolean cchk = true;
public ArrayList<String> getGmlist() {
chk = Gmlist.isEmpty();
if(chk==true)
{
Gmlist.add(0,"No Calls");
}
return Gmlist;
}
public ArrayList<String> getGclist() {
cchk = Gclist.isEmpty();
if(cchk==true)
{
Gclist.add(0,"0");
}
return Gclist;
}
public void setGmlist(ArrayList<String> Gmlit) {
for (int i = 0; i < Gmlit.size(); i++) {
this.Gmlist.add(i, Gmlit.get(i));
}
}
public void setGclist(ArrayList<String> Gclit) {
for (int i = 0; i < Gclit.size(); i++) {
this.Gmlist.add(i, Gclit.get(i));
}
}
}
Display Class
package com.mmm.rmsg;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.content.Context;
import android.graphics.Color;
import android.widget.ArrayAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Arrays;
public class MsgView extends AppCompatActivity {
ListView listView ;
ArrayList<String> mlist = new ArrayList<>();
ArrayList<String> plist = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_msg_view);
// Get ListView object from xml
listView = (ListView) findViewById(R.id.list);
GlobalState gs = (GlobalState) getApplication();
mlist= gs.getGmlist();
plist= gs.getGclist();
String[] msgArray = mlist.toArray(new String[mlist.size()]);
Arrays.toString(msgArray);
String[] clrArray = plist.toArray(new String[plist.size()]);
Arrays.toString(clrArray);
listView.setAdapter(new ColorArrayAdapter(this, android.R.layout.simple_list_item_1, msgArray,clrArray));
}
public class ColorArrayAdapter extends ArrayAdapter<Object>{
private String[] list;
private String[] p;
public ColorArrayAdapter(Context context, int textViewResourceId,
Object[] objects, Object[] obj) {
super(context, textViewResourceId, objects);
list = new String[objects.length];
for (int i = 0; i < list.length; i++)
list[i] = (String) objects[i];
p = new String[objects.length];
for (int i = 0; i < p.length; i++)
p[i] = (String) obj[i];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = (TextView)super.getView(position, convertView, parent);
String c;
for(int x=0; x< list.length; x++)
{
c=chk(x,p);
if("R".equals(c) && position==x ) {
view.setBackgroundColor(Color.RED);
}
else
if("Y".equals(c) && position==x) {
view.setBackgroundColor(Color.YELLOW);
}
else
if("G".equals(c) && position==x) {
view.setBackgroundColor(Color.GREEN);
}
}
return view;
}
}
public String chk(int idx, String[] table){
String res;
if("6".equals(table[idx]) || "7".equals(table[idx]) || "8".equals(table[idx])) {
res = "R";
}
else
if("4".equals(table[idx]) || "5".equals(table[idx])) {
res = "Y";
}
else
if("1".equals(table[idx])|| "2".equals(table[idx]) || "3".equals(table[idx]) ) {
res = "G";
}
else{
res = "W";
}
return res;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_msg_view, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy(){
super.onDestroy();
}
}
You haven't started your thread. You can do it like this:
Thread initBkgThread = new Thread(new Runnable() {
public void run() {
udp();
}
});
initBkgThread .start();
Is this a full code or just some snips?
First thing is that your text1 is not initialized.
text1 = findViewById(R.id.<id_of_text_view_in_activity_calls_layout>) ?
To start an activity from your service you should create your intent like:
//Starting Smsgs
Intent startAct = new Intent(context, Smsgs.class);
startAct.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startAct);
You need at least two thread for this, one for the receiving of the UDP packets and the other is to compute the data. You need to modify your udp() function like this:
//Warning, I did not test this code, handle it like pseude-code.
private void udp(){
// ...
// Wait to receive a datagram
dsocket.receive(packet);
Thread showMsg = new Thread(new Runnable() {
public void run() {
// Convert the contents to a string,
String message = new String(buffer, 0, packet.getLength());
Intent intent = new Intent(this, Smsgs.class);
intent.putExtra("msg",message);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
showMsg.start();
// ...
}
and also don't forget to start your another thread: initBkgThread.start()
hope it helps.
Related
Please Share code in answers if possible
Here is My code, basically I think my app is not responding after sometime maybe because the freezing gui and high memory usage, It is using even 16.8 MB of memory while in background. Please share some tips by which I can make my app simple and fast without losing functionality.
StopWatch.java
package com.study.meter;
import android.app.Service;
import android.os.IBinder;
import android.content.Intent;
import android.widget.Toast;
import android.os.Handler;
import java.util.Locale;
import android.app.PendingIntent;
import androidx.core.app.NotificationCompat;
import android.app.NotificationManager;
import android.app.Notification;
import android.content.Context;
public class StopWatch extends Service{
public static StopWatch getStopWatch;
public static int StopWatchSecs;
public static boolean isStopWatchRunning = false;
public static boolean isRunning;
public String StopWatchTime;
private NotificationCompat.Builder builder;
private Intent notificationIntent;
private PendingIntent contentIntent;
private Notification notificaton;
private NotificationManager manager;
private String StopWatchNotificationText,StopWatchNotificationTitle;
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
return START_CONTINUATION_MASK;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
getStopWatch = this;
}
#Override
public void onDestroy() {
isRunning = false;
Toast.makeText(getBaseContext(),"Destroyed",Toast.LENGTH_SHORT).show();
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
super.onStart(intent,startid);
isRunning = true;
}
public Handler StopWatchHandler = new Handler();
public Runnable StopWatchRunnable = new Runnable()
{
#Override
public void run()
{
StopWatchSecs++;
int seconds = StopWatchSecs;
int hours = seconds / 3600;
int minutes = (seconds % 3600) / 60;
int secs = seconds % 60;
// Format the seconds into hours, minutes,
// and seconds.
StopWatchTime
= String
.format(Locale.getDefault(),
"%d:%02d:%02d", hours,
minutes, secs);
// if app is running then change counting
if(MainActivity.Stop_Watch!=null && MainActivity.isAppRunning)
{
// Set the text view text.
MainActivity.Stop_Watch.setText(StopWatchTime);
}
addStopWatchNotification("StopWatch",StopWatchTime);
StopWatchHandler.postDelayed(StopWatchRunnable,1000);
}
};
public void Start_Watch()
{
StopWatchHandler.post(StopWatchRunnable);
}
public void Stop_Watch()
{
StopWatchHandler.removeCallbacks(StopWatchRunnable);
}
public String Start_Or_Stop_Watch()
{
String result = "Start";
if(isStopWatchRunning)
{
result = "Resume";
isStopWatchRunning = false;
Stop_Watch();
}
else if(!isStopWatchRunning)
{
result = "Pause";
isStopWatchRunning = true;
Start_Watch();
}
return result;
}
// adding new Handler for notifications to not overload memory
public Handler StopWatchNotificationHandler = new Handler();
public Runnable StopWatchNotificationRunnable;
public void addStopWatchNotification(String title,String text)
{
if(builder==null)
{
builder = new NotificationCompat.Builder(this);
builder
.setSmallIcon(R.drawable.notify_icon)
.setAutoCancel(false)
.setOnlyAlertOnce(true);
}
if(notificationIntent==null)
{
notificationIntent = new Intent(this, MainActivity.class);
}
if(contentIntent==null)
{
contentIntent = PendingIntent.getActivity(this, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
}
if(manager==null)
{
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
if(StopWatchNotificationRunnable==null)
{
StopWatchNotificationRunnable = new Runnable()
{
#Override
public void run()
{
builder
.setContentTitle(title)
.setContentText(text);
notificaton = builder.build();
notificaton.flags |= Notification.FLAG_NO_CLEAR;
manager.notify(0, notificaton);
}
};
}
StopWatchNotificationText = text;
StopWatchNotificationTitle = title;
StopWatchNotificationHandler.post(StopWatchNotificationRunnable);
}
}
MainActivity.java
package com.study.meter;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.content.Context;
public class MainActivity extends AppCompatActivity
{
public static boolean isAppRunning;
public static TextView Stop_Watch;
public static MainActivity activity;
public Button Start_Watch;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// set content view
setContentView(R.layout.activity_main);
// hide statusbar
getSupportActionBar().hide();
activity = this;
// set the value of StopWatch
Stop_Watch = findViewById(R.id.StopWatch);
Start_Watch = findViewById(R.id.StartWatch);
//if StopWatch service is not running
if(!StopWatch.isRunning)
{
// start the service
startService(new Intent(this, StopWatch.class));
}
}
#Override
public void onResume()
{
super.onResume();
isAppRunning = true;
if(StopWatch.StopWatchSecs!=0)
{
// if stopwatchsecs is not equal to null or 0
if(StopWatch.isStopWatchRunning)
{
// if stopwatch is running in background
Start_Watch.setText("Pause");
}else
{
// if stopwatch is not running in background
Start_Watch.setText("Resume");
}
}
}
#Override
public void onPause()
{
isAppRunning = false;
super.onPause();
}
// "StartWatch" click
public void StartorStop(View v)
{
Button sv = (Button)v;
String StartWatchText = StopWatch.getStopWatch.Start_Or_Stop_Watch();
sv.setText(StartWatchText);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.study.meter"
android:installLocation="auto">
<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/Theme.StudyMeter">
<service
android:name=".StopWatch"
android:stopWithTask="false"/>
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize|screenLayout">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/StopWatch"
android:textSize="65dp"
android:text="0:00:00"
app:layout_constraintBottom_toTopOf="#id/StartWatch"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:layout_height="50dp"
android:layout_width="wrap_content"
android:id="#+id/StartWatch"
android:text="Start"
android:onClick="StartorStop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/StopWatch"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Seems like an architecture problem, try to modulate more your Java code by dividing it in more activities, too much tasks in few activities causes crashes and poor performance ;)
However, I try only when my app has a launcher property will the activity detect the NFC intent. Even if I have a intent filter in another application. Here is my manifest and both the activities. I even have foreground dispatch managed.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.melin.vustudentattendence">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<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=".AddStudentsActivity"></activity>
<activity android:name=".AddClassesActivity" />
<activity android:name=".AddTeachersActivity" />
<activity android:name=".TestActivity">
<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="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
<activity android:name=".ClassAttendenceActivity">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
<activity
android:name=".LecutererClassesListActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity android:name=".InstituteDashboardActivity" />
<activity android:name=".TodaysClassesActivity" />
<activity
android:name=".LecturerDashboardActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".LoginActivity"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
This is my TestActivity.java
package com.melin.vustudentattendence;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ClipDescription;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class TestActivity extends AppCompatActivity {
public static final String TAG="NFCDemo";
private TextView mTextView;
private NfcAdapter mNfcAdapter;
public class NdefReaderTask extends AsyncTask<Tag,Void,String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
mTextView.setText("Read content: " + result);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mTextView=(TextView)findViewById(R.id.textView_explanation);
mNfcAdapter= NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter==null){
Toast.makeText(this,"This device doesn't support NFC",Toast.LENGTH_LONG).show();
finish();
return;
}
if(!mNfcAdapter.isEnabled()){
mTextView.setText("Nfc is disabled");
}else{
mTextView.setText(R.string.explanation);
}
handleIntent(getIntent());
}
#Override
protected void onResume() {
super.onResume();
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
stopForegroundDispatch(this,mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(ClipDescription.MIMETYPE_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
private void handleIntent(Intent intent){
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (ClipDescription.MIMETYPE_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
}
and this is my ClassesAttendenceActivity
package com.melin.vustudentattendence;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ClipDescription;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class ClassAttendenceActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ClassAttendenceRowAdapter adapter;
private List<Student> students=new ArrayList<>();
private FirebaseFirestore fs;
private String incomingIntentData;
private NfcAdapter mNfcAdapter;
private static String TAG="Attendence Activity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_class_attendence);
//check nfc first
mNfcAdapter=NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter==null){
Toast.makeText(this,"This device doesn't support NFC",Toast.LENGTH_LONG).show();
finish();
return;
}
if(!mNfcAdapter.isEnabled()){
Toast.makeText(this,"NFC is disabled.Please enable it",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "NFC is in reader mode", Toast.LENGTH_SHORT).show();
}
//incomingIntentData=getIntent().getExtras().getString("document");
//fs=FirebaseFirestore.getInstance();
//Toast.makeText(this,incomingIntentData,Toast.LENGTH_LONG).show();
//recyclerView=(RecyclerView)findViewById(R.id.attendenceListRecyclerView);
// LinearLayoutManager layoutManager=new LinearLayoutManager(ClassAttendenceActivity.this);
// recyclerView.setLayoutManager(layoutManager);
// populateStudentList(incomingIntentData);
handleIntent(getIntent());
}
private void populateStudentList(String url){
fs.collection(url+"/students")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Map<String,Object> data=document.getData();
Student student=new Student();
student.setStatus("ABSENT");
for (Map.Entry<String,Object> entry : data.entrySet()){
if(entry.getKey().equals("name")){
student.setName(entry.getValue().toString());
}
if(entry.getKey().equals("student_id")){
student.setStudent_id(entry.getValue().toString());
}
}
students.add(student);
Log.d("List", document.getId() + " => " + document.getData());
}
} else {
Log.d("List", "Error getting documents: ", task.getException());
}
adapter=new ClassAttendenceRowAdapter(students);
recyclerView.setAdapter(adapter);
}
});
}
public void simulatingAnIntent(){
String student_id="101";
for(Student student:students){
if(student.getStudent_id().equals(student_id)){
student.setStatus("PRESENT");
Toast.makeText(ClassAttendenceActivity.this,"Student ID"+student.getStudent_id()+"Detected",Toast.LENGTH_LONG).show();
}
}
adapter=new ClassAttendenceRowAdapter(students);
recyclerView.setAdapter(adapter);
}
#Override
protected void onResume() {
super.onResume();
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
stopForegroundDispatch(this,mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(ClipDescription.MIMETYPE_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
private void handleIntent(Intent intent){
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (ClipDescription.MIMETYPE_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
public class NdefReaderTask extends AsyncTask<Tag,Void,String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(ClassAttendenceActivity.this,"Student ID"+result+"Detected",Toast.LENGTH_LONG).show();
// for(Student student:students){
// if(student.getStudent_id().equals(result)){
// student.setStatus("PRESENT");
// Toast.makeText(ClassAttendenceActivity.this,"Student ID"+student.getStudent_id()+"Detected",Toast.LENGTH_LONG).show();
// }
// }
//
// adapter=new ClassAttendenceRowAdapter(students);
// recyclerView.setAdapter(adapter);
}
}
}
}
As you can see both the activities are almost identical
while one reads the data another doesn't
It turns out that using emulated nfc tag was the error.Using real nfc tag worked well.Though no one answered the question I am answering my own question so that when someone encounters this problem they can see this answer.Thank you.
Working on an app that is supposed to generate random characters via a broadcast. I need to broadcast the random characters generated by my custom service, so that the main activity registered to intercept the broadcast can get the random numbers and display them on an EditText. The layout is shown here: app layout
The start button will trigger the random character generator service. The EditText will display the random numbers generated in real time (without any button press). The stop button will stop the service. The EditText won’t display any numbers. I have created a service(RandomCharacterService) and registered it in my manifest. Upon running the app, my app crashes. I am sure it is because I did not register my broadcast in my manifest, but I do not understand how to do that. And perhaps there is something wrong with how I am handling the broadcast in my main activity. In my button click method for the start button, I tried to do a for-loop, but this resulted in the app crashing as well.
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cs7455rehmarazzaklab8">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".RandomCharacterService"></service>
</application>
MainActivityjava:
package com.example.cs7455rehmarazzaklab8;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.support.constraint.ConstraintLayout;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import java.util.Random;
public class MainActivity extends AppCompatActivity
{
private Button btnStart, btnStop;
private EditText myTV;
private Intent serviceIntent;
private RandomCharacterService myService;
private ServiceConnection myServiceConnection;
private boolean isServiceOn; //checks if the service is on
private int myRandomCharacter;
char MyRandomCharacter = (char)myRandomCharacter;
private boolean isRandomGeneratorOn;
private final int MIN = 65;
char m = (char)MIN;
private final int MAX = 26;
char x = (char)MAX;
private final String TAG = "Random Char Service: ";
private final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private Context mContext;
private Random mRandom = new Random();
// Initialize a new BroadcastReceiver instance
private BroadcastReceiver mRandomCharReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
// Get the received random number
myRandomCharacter = intent.getIntExtra("RandomCharacter",-1);
// Display a notification that the broadcast received
Toast.makeText(context,"Received : " + myRandomCharacter,Toast.LENGTH_SHORT).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the application context
mContext = getApplicationContext();
btnStart = (Button) findViewById(R.id.StartButton);
btnStop = (Button) findViewById(R.id.StopButton);
myTV = (EditText)findViewById(R.id.RandomCharText);
// Register the local broadcast
LocalBroadcastManager.getInstance(mContext).registerReceiver(mRandomCharReceiver, new IntentFilter("BROADCAST_RANDOM_CHARACTER"));
// Change the action bar color
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#FFFF00BF")));
// Set a click listener for start button
btnStart.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
isServiceOn = true;
serviceIntent = new Intent(getApplicationContext(), RandomCharacterService.class);
startService(serviceIntent);
setRandomNumber();
// Generate a random char
myRandomCharacter = new Random().nextInt(x)+m;
// Initialize a new intent instance
Intent intent = new Intent("BROADCAST_RANDOM_CHARACTER");
// Put the random character to intent to broadcast it
intent.putExtra("RandomCharacter",myRandomCharacter);
// Send the broadcast
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
// Update the TextView with random character
myTV.setText(" " + myRandomCharacter );
}
});
btnStop.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
isServiceOn = false;
stopService(serviceIntent);
}
});
}
private void setRandomNumber()
{
myTV.setText("Random Character: " + (char)myService.getRandomCharacter());
String alphabet = myTV.getText().toString();
}
}
RandomCharacterService.java:
package com.example.cs7455rehmarazzaklab8;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.Random;
public class RandomCharacterService extends Service
{
private int myRandomCharacter;
char MyRandomCharacter = (char)myRandomCharacter;
private boolean isRandomGeneratorOn;
private final int MIN = 65;
char m = (char)MIN;
private final int MAX = 26;
char x = (char)MAX;
private final String TAG = "Random Char Service: ";
private final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
class RandomCharacterServiceBinder extends Binder{
public RandomCharacterService getService()
{
return RandomCharacterService.this;
}
}
private IBinder myBinder = new RandomCharacterServiceBinder();
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG, "In OnStartCommand Thread ID is "+Thread.currentThread().getId());
isRandomGeneratorOn = true;
new Thread(new Runnable()
{
#Override
public void run()
{
startRandomGenerator();
}
}
).start();
return START_STICKY;
}
private void startRandomGenerator()
{
while(isRandomGeneratorOn)
{
char alphabet = 'A';
for (int i = 65; i < 90; i++)
{
try
{
Thread.sleep(1000);
if(isRandomGeneratorOn)
{
alphabet++;
myRandomCharacter = new Random().nextInt(x)+m;
Log.i(TAG, "Thread ID is "+Thread.currentThread().getId() + ", Random character is "+(char)myRandomCharacter);
}
}
catch(InterruptedException e)
{
Log.i(TAG, "Thread Interrupted.");
}
}
}
}
private void stopRandomGenerator()
{
isRandomGeneratorOn = false;
}
public int getRandomCharacter()
{
return myRandomCharacter;
}
public boolean isRandomGeneratorOn() {
return isRandomGeneratorOn;
}
#Override
public void onDestroy()
{
super.onDestroy();
stopRandomGenerator();
Log.i(TAG, "Service Destroyed.");
}
#Nullable
#Override
public IBinder onBind(Intent intent)
{
Log.i(TAG, "In onBind ...");
return myBinder;
}
}
Call Stack:callstack from running the app
Call Stack from attempting to press the stop button:crash from attempting to press stop button
Since you are using the bound service (using Ibinder). You will have to start the service by calling bindService instead of startService. But before that you need to initialize your ServiceConnection variable and better use the isServiceOn boolean as in the below example.
private ServiceConnection myServiceConnection = new ServiceConnection() {
#Override
// IBinder interface is through which we receive the service object for communication.
public void onServiceConnected(ComponentName name, IBinder binder) {
RandomCharacterServiceBinder myBinder = (RandomCharacterServiceBinder) binder;
isServiceOn = true;
myService = myBinder.getService();
Toast.makeText(context,"Service connected", Toast.LENGTH_SHORT).show();
}
#Override
public void onServiceDisconnected(ComponentName name) {
isServiceOn = false;
myService = null;
}
};
After onServiceConnected is called, you will get your service object. Most probably your service will be initialized before you perform a click. But just to ensure you can TOAST some message within it.
And you should start the service in Activity's onCreate method, so service will get some time in creation. So move the below code from you click listener to onCreate method.
serviceIntent = new Intent(getApplicationContext(), RandomCharacterService.class);
// startService(serviceIntent); <-- remove this line, call bindService
bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);
and wait for the service connection Toast to appear.
I have a problem with my Android client/server app. I would like to connect devices by WiFi Direct and send through some media files.
I made an Activity and Service for both Client and Server. Code is below.
ServerActivity:
import java.util.ArrayList;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WpsInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ServerActivity extends Activity {
private WifiP2pManager wifiManager;
private Channel wifichannel;
private BroadcastReceiver wifiServerReceiver;
private IntentFilter wifiServerReceiverIntentFilter;
private WifiP2pConfig config;
private String deviceName;
private Intent intent;
PeerListListener myPeerListListener;
ArrayList<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
WifiP2pDeviceList peerList;
TextView text;
EditText et2;
Button button1;
ListView listView;
ArrayAdapter<String> BTArrayAdapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.server_activity);
// Block auto opening keyboard
this.getWindow()
.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
listView = (ListView) findViewById(R.id.listView1);
listView.setAdapter(BTArrayAdapter);
wifiManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
wifichannel = wifiManager.initialize(this, getMainLooper(), null);
wifiServerReceiverIntentFilter = new IntentFilter();
;
wifiServerReceiverIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
wifiServerReceiverIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
wifiServerReceiverIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
wifiServerReceiverIntentFilter
.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
intent = null;
registerReceiver(wifiServerReceiver, wifiServerReceiverIntentFilter);
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
wifiManager.discoverPeers(wifichannel, null);
wifiManager.requestPeers(wifichannel, new PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
peers.clear();
peers.addAll(peerList.getDeviceList());
}
});
for (int i = 0; i < peers.size(); i++) {
WifiP2pDevice device = peers.get(i);
deviceName = device.deviceName;
config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
wifiManager.connect(wifichannel, config, new ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(
getApplicationContext(),
"Połączono z: " + deviceName + "\n Mac: "
+ config.deviceAddress, Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int reason) {
Toast.makeText(getApplicationContext(), "Nie udało się połączyć",
Toast.LENGTH_SHORT).show();
}
});
}
wifiManager.requestConnectionInfo(wifichannel,
new WifiP2pManager.ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
// TODO Auto-generated method stub
String groupOwnerAddress = info.groupOwnerAddress.getHostAddress();
Toast.makeText(getApplicationContext(),
"GroupOwnAddress: " + groupOwnerAddress, Toast.LENGTH_SHORT)
.show();
}
});
StartServer(null);
}
});
}
public void StartServer(View v) {
// Construct our Intent specifying the Service
intent = new Intent(this, ServerService.class);
startService(intent);
}
}
ServerService:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.widget.Toast;
public class ServerService extends IntentService {
Handler mHandler;
private int port = 2178;
ServerSocket welcomeSocket = null;
Socket socket = null;
public ServerService() {
super("ServerService");
mHandler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
try {
mHandler.post(new DisplayToast(this, "Creating ServerSocket.."));
welcomeSocket = new ServerSocket(port);
welcomeSocket.setReuseAddress(true);
mHandler.post(new DisplayToast(this, "Waiting for connection on port: "
+ welcomeSocket.getLocalPort()));
socket = welcomeSocket.accept();
// while(true && flag){
// socket = welcomeSocket.accept();
mHandler.post(new DisplayToast(this, "Coneccted!"));
// }
mHandler.post(new DisplayToast(this, "Succes!"));
} catch (IOException e) {
mHandler.post(new DisplayToast(this, "IOException"));
} catch (Exception e) {
mHandler.post(new DisplayToast(this, "Exception"));
}
mHandler.post(new DisplayToast(this, "ServerService"));
}
/*
public void onDestroy() {
try {
welcomeSocket.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stopSelf();
}*/
}
class DisplayToast2 implements Runnable {
private final Context mContext;
String mText;
public DisplayToast2(Context mContext, String text) {
this.mContext = mContext;
mText = text;
}
public void run() {
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
ClientActivity:
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
public class ClientActivity extends Activity {
Button button;
private WifiP2pManager wifiManager;
private Channel wifichannel;
private BroadcastReceiver wifiClientReceiver;
private IntentFilter wifiClientReceiverIntentFilter;
private WifiP2pInfo wifiInfo;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.client_activity);
// Block auto opening keyboard
this.getWindow()
.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
wifiManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
wifichannel = wifiManager.initialize(this, getMainLooper(), null);
wifiClientReceiver = new WiFiClientBroadcastReceiver(wifiManager, wifichannel, this);
wifiClientReceiverIntentFilter = new IntentFilter();
;
wifiClientReceiverIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
wifiClientReceiverIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
wifiClientReceiverIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
wifiClientReceiverIntentFilter
.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
wifiInfo = null;
registerReceiver(wifiClientReceiver, wifiClientReceiverIntentFilter);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
StartClient(null);
}
});
}
public void setNetworkToReadyState(boolean status, WifiP2pInfo info, WifiP2pDevice device) {
wifiInfo = info;
// targetDevice = device;
// connectedAndReadyToSendFile = status;
}
public void StartClient(View v) {
Intent intent = new Intent(this, ClientService.class);
intent.putExtra("wifiInfo", wifiInfo);
if (wifiInfo == null) {
Toast.makeText(this, "WifiInfo = null!", Toast.LENGTH_SHORT).show();
}
startService(intent);
}
}
ClientService:
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.p2p.WifiP2pInfo;
import android.os.Handler;
import android.widget.Toast;
public class ClientService extends IntentService {
Handler mHandler;
private WifiP2pInfo wifiInfo;
private int port = 2178;
Socket clientSocket = null;
OutputStream os = null;
public ClientService() {
super("ClientService");
mHandler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
wifiInfo = (WifiP2pInfo) intent.getExtras().get("wifiInfo");
InetAddress targetIP = wifiInfo.groupOwnerAddress;
clientSocket = new Socket();
if(wifiInfo.isGroupOwner)
{
try {
mHandler.post(new DisplayToast(this, "Try to connect: /N IP: " + targetIP + "/nPort: " +port));
clientSocket.connect(new InetSocketAddress(targetIP, port));
mHandler.post(new DisplayToast(this, "Connected!"));
//os = clientSocket.getOutputStream();
} catch (IOException e) {
mHandler.post(new DisplayToast(this, "serwer IOException: " + e.getMessage()));
} catch (Exception e) {
mHandler.post(new DisplayToast(this, "serwer Exception"));
}
}else{
mHandler.post(new DisplayToast(this, "Group owner = " + wifiInfo.isGroupOwner));
}
}
/*
public void onDestroy()
{
try {
os.close();
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stopSelf();
}*/
}
class DisplayToast implements Runnable {
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text) {
this.mContext = mContext;
mText = text;
}
public void run() {
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".AppModeSelection"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".ServerService"
android:exported="false" />
<service
android:name=".ClientService"
android:exported="false" />
<activity android:name=".ServerActivity" >
</activity>
<activity android:name=".ClientActivity" >
</activity>
</application>
</manifest>
I am using two phones with WiFi Direct (Samsung GT-I9505 Android 4.4.2 and Samsung GT-I8190N Adroid 4.1.2). First of all I turned off all connections (BT, WIFI) and then connected by WiFi Direct. GT-I9505 is Server and other one is Client. While establishing a connection IOException error appears:
IOException: failed to connect to /192.168.49.1 (port 2178): connect failed: ECONNREFUSED (Connection refused)
I tried to use plenty of others Pors but nothing works. What I did wrong?
Thank you in advance for any help!
UPDATE:
I noticed that when I disconnect WiFi direct and connect again but in other direction it works but only for moment.
the main issue with your code is that you do need to make it event driven, in the current state I'm surprised that it even does anything really.
So, please try making it to something like following:
1. Start Discovering peers, once you get Peers Changed event, then do requestPeers
2. if you need some listener etc. to be ready for you on the other side, then you likely would identify those devices by advertising a service, so next look start discovery for services.
3. After you get service discovered, start 5-second timer to wait for any additional, reset the timer after each service discovered, and once the timer finally gets to run uninterrupted 5 seconds, you likely have discovered all services available at that time.
4. Select ONE service and connect to that device (you can not have multiple connection really).
5. Once you get event that you are connected, then use requestConnectionInfo to get info for the connection.
Then do remember that before you start you need to create the local service, so the other side can see it. Then, if your device gets selected as Group owner, you could keep the advertisement on, and let more clients connect to you. But if you are selected as Client, then you can not have incoming connections, so you should get rid of the advertisement.
When I try to start my IntenetService I get no errors, but it never hits the breakpoint in onHandleIntent
MainActivity.java
package com.peterchappy.filewatcher.activities;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.peterchappy.filewatcher.R;
import com.peterchappy.filewatcher.services.FileDownloadService;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class MainActivity extends Activity {
public static final String INTENT_EXTRA_FILE_URL = "URL";
private FileDownloadBroadcastReceiver broadcastReceiver;
private Button go;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
go = (Button) findViewById(R.id.go);
go.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
downloadFile("http://www.reddit.com/");
}
});
}
#Override
protected void onStart() {
super.onStart();
broadcastReceiver = new FileDownloadBroadcastReceiver();
registerReceiver(broadcastReceiver, new IntentFilter(FileDownloadService.FILE_DOWNLOADED));
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(broadcastReceiver);
}
private void downloadFile(String text) {
Intent intent = new Intent(this, FileDownloadService.class);
intent.putExtra(INTENT_EXTRA_FILE_URL, text);
this.startService(intent);
}
private void readFileAndDisplayContent(String fileName) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(openFileInput(fileName)));
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
reader.close();
System.out.println(content.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
private class FileDownloadBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String localFileName = intent.getStringExtra(FileDownloadService.INTENT_LOCAL_FILE_NAME);
readFileAndDisplayContent(localFileName);
}
}
}
FileDownloadService.java
package com.peterchappy.filewatcher.services;
import android.app.IntentService;
import android.content.Intent;
import com.peterchappy.filewatcher.activities.MainActivity;
import com.peterchappy.filewatcher.helpers.FileDownloader;
public class FileDownloadService extends IntentService {
public static final String INTENT_LOCAL_FILE_NAME = "local_file_name";
public static final String FILE_DOWNLOADED = "FILE_DOWNLOADED";
public FileDownloadService() {
super("FILE_DOWNLOAD_SERVICE");
}
#Override
protected void onHandleIntent(Intent intent) {
FileDownloader fileDownloader = new FileDownloader(this);
String localFileName = fileDownloader.downloadFile(intent.getStringExtra(MainActivity.INTENT_EXTRA_FILE_URL));
Intent resultIntent = new Intent(FILE_DOWNLOADED);
resultIntent.putExtra(INTENT_LOCAL_FILE_NAME, localFileName);
sendBroadcast(resultIntent);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".activities.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<service android:name=".filewatcher.services.FileDownloadService"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Ok, now I think I see it in your manifest. <service> tag is outside <application> tag, try moving it inside.