open Accessory in einer 2. Activity

  • Antworten:9
Alfred Banause
  • Forum-Beiträge: 15

11.02.2013, 16:46:43 via Website

Hallo an alle Android Entwickler,

ich habe folgendes Problem:

in meiner Main Activity öffne ich die Android accessory Kommunikation und lese fleißig in einem thread die kommenden Daten ein.

In einer 2. Activity sollen auch die kommenden Daten empfangen und analysiert werden. OHNE dass die Kommunkation die hergestellt wird, da der thread der MainActivity im Hintergrund weiterlaufen muss.

Meine frage ist nun, wie greife ich in meiner neuen Activity auf die bestehende Kommunikation zu??

mein Quellcode ( SENDER ):

1final Intent i=new Intent(this,RangeActivity.class);
2
3 ButtonNextActivity.setOnClickListener(new OnClickListener(){
4
5 @Override
6 public void onClick(View v) {
7 i.putExtra("mFileDescriptor", mFileDescriptor);
8 startActivity(i);
9
10 }});


EMPFÄNGER:
1private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
2
3
4 private boolean mPermissionRequestPending;
5 private UsbManager mUsbManager;
6 private UsbAccessory mAccessory;
7 private ParcelFileDescriptor mFileDescriptor;
8 private FileInputStream mInputStream;
9 private FileOutputStream mOutputStream;
10 private PendingIntent mPermissionIntent;
11
12 byte[] bufferSendeRxTxFrequenz = new byte[20];
13
14 Bundle bn= new Bundle();
15
16 Properties proberties = new Properties();
17 final String TAG="";
18
19 @Override
20 public void onCreate(Bundle savedInstanceState) {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_range);
23
24
25
26 bn=getIntent().getBundleExtra("mFileDescriptor");
27
28 //eine Referenz zum USB system service
29 mUsbManager = UsbManager.getInstance(this);
30 //Erlaubnis für USB wird definiert --> daher die Abfrage wenn ein Accessoir angeschlossen wird
31 mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
32 //IntenFilter wird zusammen mit dem Broadcast receiver verwendet, um zu gewährleisten, dass die Activity nur auf sichere broadcasts zuhört
33 IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
34 filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
35 //Der Broadcast Receiver wird registriert
36 registerReceiver(mUsbReceiver, filter);
37
38 //mFileDescriptor = (ParcelFileDescriptor) getIntent().getExtras().get("mFileDescriptor");
39
40
41
42 }
43
44
45 @Override
46 public void onResume() {
47 super.onResume();
48
49 //erhalte Referenz von dem Accessoir vom UsbManager
50 UsbAccessory[] accessories = mUsbManager.getAccessoryList();
51
52 UsbAccessory accessory = (accessories == null ? null : accessories[0]);
53 if (accessory != null) {
54 if (mUsbManager.hasPermission(accessory)) {
55 openAccessory(accessory);
56 } else {
57 synchronized (mUsbReceiver) {
58 if (!mPermissionRequestPending) {
59 mUsbManager.requestPermission(accessory,
60 mPermissionIntent);
61 mPermissionRequestPending = true;
62 }
63 }
64 }
65 } else {
66 Log.d("", "mAccessory is null");
67 }
68 }
69
70 @Override
71 public void onDestroy() {
72 super.onDestroy();
73
74 closeAccessory();
75 unregisterReceiver(mUsbReceiver);
76
77 Log.i("LifeCycle","onDestroy");
78 }
79
80
81 private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
82 //diese MMethode wird aufgerufen, wenn der broadcast receiver
83 //registriert ist und wenn
84 @Override
85 public void onReceive(Context context, Intent intent) {
86 String action = intent.getAction();
87 if (ACTION_USB_PERMISSION.equals(action)) {
88 synchronized (this) {
89 UsbAccessory accessory = UsbManager.getAccessory(intent);
90 if (intent.getBooleanExtra(
91 UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
92 openAccessory(accessory);
93
94 runOnUiThread(new Runnable() {
95 @Override
96 public void run() {
97 Toast toast = Toast.makeText(RangeActivity.this, "1 !!", Toast.LENGTH_LONG);
98 toast.show();
99
100 }
101 });
102
103 } else {
104 Log.d("", "permission denied for accessory "
105 + accessory);
106 }
107 mPermissionRequestPending = false;
108 }
109 } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
110 UsbAccessory accessory = UsbManager.getAccessory(intent);
111 if (accessory != null && accessory.equals(mAccessory)) {
112 closeAccessory();
113 }
114 }
115 }
116 };
117
118 private void openAccessory(UsbAccessory accessory) {
119
120 mFileDescriptor = mUsbManager.openAccessory(accessory);
121
122 if (mFileDescriptor != null) {
123
124 mAccessory = accessory;
125 FileDescriptor fd = mFileDescriptor.getFileDescriptor();
126 mInputStream = new FileInputStream(fd);
127 mOutputStream = new FileOutputStream(fd);
128
129 // Empfangen
130 Thread thread1 = new Thread(null, commRunnableRx, "");
131 thread1.start();
132 Thread thread2 = new Thread(null, commRunnableTx, "");
133 thread2.start();
134
135// Timer t1=new Timer();
136// t1.scheduleAtFixedRate(timerTask,0,500);
137 // --
138 Log.d("", "accessory opened");
139
140 runOnUiThread(new Runnable() {
141 @Override
142 public void run() {
143 Toast toast = Toast.makeText(RangeActivity.this, "opened !!", Toast.LENGTH_LONG);
144 toast.show();
145
146 }
147 });
148
149
150
151 } else {
152
153 Log.d("", "accessory open fail");
154
155 runOnUiThread(new Runnable() {
156 @Override
157 public void run() {
158 Toast toast = Toast.makeText(RangeActivity.this, "fail !!", Toast.LENGTH_LONG);
159 toast.show();
160
161 }
162 });
163
164 }
165 }
166
167 private void closeAccessory() {
168 try {
169 if (mFileDescriptor != null) {
170 mFileDescriptor.close();
171 }
172 } catch (IOException e) {
173 } finally {
174 mFileDescriptor = null;
175 mAccessory = null;
176 }
177 }
178
179 Runnable commRunnableTx = new Runnable() {
180 @Override
181 public void run() {
182
183 runOnUiThread(new Runnable() {
184 @Override
185 public void run() {
186 Toast toast = Toast.makeText(RangeActivity.this, "TX 1 !!", Toast.LENGTH_LONG);
187 toast.show();
188
189 }
190 });
191
192 try {
193 mOutputStream.write(bufferSendeRxTxFrequenz);
194 runOnUiThread(new Runnable() {
195 @Override
196 public void run() {
197 Toast toast = Toast.makeText(RangeActivity.this, "wurde gesendet !!", Toast.LENGTH_LONG);
198 toast.show();
199
200 }
201 });
202 } catch (IOException e) {
203 // TODO Auto-generated catch block
204 e.printStackTrace();
205 }
206
207 runOnUiThread(new Runnable() {
208 @Override
209 public void run() {
210 Toast toast = Toast.makeText(RangeActivity.this, "TX !!", Toast.LENGTH_LONG);
211 toast.show();
212
213 }
214 });
215
216 }
217 };
218 Runnable commRunnableRx = new Runnable() {
219 @Override
220 public void run() {
221
222 runOnUiThread(new Runnable() {
223 @Override
224 public void run() {
225 Toast toast = Toast.makeText(RangeActivity.this, "RX !!", Toast.LENGTH_LONG);
226 toast.show();
227
228 }
229 });
230 }
231 };
232
233 @Override
234 public boolean onCreateOptionsMenu(Menu menu) {
235 getMenuInflater().inflate(R.menu.activity_rage, menu);
236 return true;
237 }

— geändert am 11.02.2013, 16:58:45

Antworten
Andreas Weichert
  • Forum-Beiträge: 287

11.02.2013, 19:51:12 via Website

Ohne, dass ich mir den Code jetzt genau angeschaut habe gehört konzeptionell deine Accessory eben nicht zur MainActivity.
Da du auch von andere Activities darauf zugreifen will muß eben auch der Kontext globaler sein.

Also entweder eigenständige Klasse oder static Member der MainActivity.

Außerdem kannst Du nicht davon ausgehen - wenn ich es richtig verstanden habe - dass selbst die MainActivity nicht von Adroid bei Speichermangel gekillt wird.

Antworten
Alfred Banause
  • Forum-Beiträge: 15

11.02.2013, 20:42:20 via Website

Hallo Andreas,

vielen Dank für deine Anregungen.
Ich werde zunächst versuchen die Deklarationen global zu gestalten, sodass auch andere Activities darauf zugreifen können.

Achso, wieso sollte die App wegen Speichermangel gekillt werden? Ich bekomme die Daten, analysiere sie, stelle sie grafisch dar und speichere auf einer SD-Card. Den möglichen Speichermangel bei der SD-Karte habe ich berücksichtigt.

Würde mich über weitere Anregungen freuen.


Viele Grüße,
Alfred

— geändert am 11.02.2013, 20:46:07

Antworten
Andreas Weichert
  • Forum-Beiträge: 287

11.02.2013, 21:12:28 via Website

Nein, es geht um den RAM Speicher.
Dieser Speicher wird ja von allen Apps verwendet und wenn eine neue App/Activity gestartet wird werden die alten eben rausgeschmissen wenns nicht reicht. (Activity-LiveCyle).
Dieses mußte ich bei meiner App die immer im Hintergrund laufen soll auch beachten und lernen. (Ist eben kein Windows).
Ein Activity sollte so programmierte werden, dass die jederzeit geschlossen und in dem alten Zustand wieder geöffnet werden kann.
Kannst ja mal testen deine App starten, dann Home und 1-3 andere Apps starten. (Google Play eigent sich dazu gut).
Wenn dann deine App sich mit den Taskmanager wieder wie gewünscht starten läßt ist alles ok. Sonst eben nicht.......

Antworten
Alfred Banause
  • Forum-Beiträge: 15

12.02.2013, 11:00:16 via Website

Vielen Dank für deine Hinweise, darauf werde ich achten.

leider konnte ich weder über eine Klasse noch über die globale Handhabung etwas in der 2. Activity über den OutputStream hinausschicken bzw. über den InputStream etwas empfangen.
Könntest du mir bitte ein Beispiel dazu geben?

Antworten
Andreas Weichert
  • Forum-Beiträge: 287

12.02.2013, 14:44:14 via Website

Es ist mir nicht ganz klar was du meinest und was Du vor hast.

Du hast erstmal eine globale Klassen erzeugt die deine ganze Streamfunktionalität kapselt !?

Möchtest Du jetzt, dass Activities auf irgendwelche Aktivitäten in deiner "Stream"-Klasse reagieren ?

— geändert am 12.02.2013, 14:44:39

Antworten
Alfred Banause
  • Forum-Beiträge: 15

13.02.2013, 07:56:28 via Website

Also mein Vorhaben ist, dass ich in meiner ersten Ativity mit open Acessory die Kommunikation herstelle und mit den in-und outputStreams darauf zugreife (soweit funktioniert alles). nun möchte ich in einer weiteren Activity auf diese in- und outputsstreams zugreifen, so dass ich auch hier senden und empfangen kann über die geöffnete Schnittstelle.

mit der globen Klasse hat es nicht geklappt.

Antworten
Andreas Weichert
  • Forum-Beiträge: 287

13.02.2013, 09:29:44 via Website

Soweit hatte ich das schon verstanden.
Ich kann mich in meiner Antwort nur wiederholen:

Auf deine Kommunikation willst Du von verschiedenen Stellen des Programmes aus zugreifen. Daher muß deren Kontext globaler sein.

(Kamikaze-technisch könntes Du natürlich auch in deiner 2.Activity eine Reference auf die 1. verwenden - wegen live-cycle aber nicht zu empfehlen)

Also Kommunikatonsobjekt global machen:
Durch eigene Klasse (java-file) oder eben als statische Member der 1. Activity. Somit kann Du von alllen Stellen des Code auf deine Kommunikation zugreifen.
Ich verstehen nicht wo das Problem liegt !?

Antworten
Alfred Banause
  • Forum-Beiträge: 15

13.02.2013, 09:40:41 via Website

Soweit hatte ich das auch verstanden.
jedoch habe ich Probleme mit der Umsetzung. (habe wenig OOP Erfahrung, programmiere sonst eher in C)

— geändert am 13.02.2013, 09:43:37

Antworten
Andreas Weichert
  • Forum-Beiträge: 287

13.02.2013, 10:23:24 via Website

Ok, dachte ich mir.
OOP ist die natürlichste und einfachste Form der Programmierung für mich inzwischen, da sie dem natürlichem Denken des Menschen (nicht nur bei uns Nerds:grin:) enspricht. Es gibt Objekte, die Eigenschaften (Daten) und Fähigkeiten (Funktionen) haben. Die Objekte kommunizieren miteinander.

Mit nach diesem Bild solltes Du deine App in Module zerlegen/aufbauen.
Ich gehe sogar soweit, das ich behaupte, dass der Entwurf der Daten/Klassenstruktur die eigentlich Programmierarbeit ist. "Eine genau dem Problem angepasste Datenstruktur ist der halbe Algorithmus !"
(Habe schon oft festgestellt, dass wenn ich eine Algorithmus/Logik kompliziert programmiert werden mußte, das die Datenstruktur nicht passte)

Die Worte helfen Dir wahrscheinlich bei deiner Aufgabe auch nicht weiter. Aber ich kann Dir nur sagen, es lohn sich OOP zu lernen und anzuwenden.

Also Du sollte einfach eine neue Kommunkation-Klasse anlegen und alles was in der MainActivity die Kommunikation betrifft dort reinkopieren.
Ev. brauchst Du dort noch eine Activity bzw. ein Context, den Du einfach von der MainActivity der neue Klassen übergibst.
Dann hast Du die Kommunikation in ein Modul gekapselt und kann von jeder Stelle des Codes darauf komfortabel (Memberfunktionen,etc.) zugreifen.

Antworten