Skip to content
This repository was archived by the owner on Apr 23, 2023. It is now read-only.

Commit 21e3b96

Browse files
author
Tobias Scholze
committed
Added source to the example.
1 parent 73b3f2d commit 21e3b96

File tree

18 files changed

+732
-0
lines changed

18 files changed

+732
-0
lines changed

app/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

app/build.gradle

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apply plugin: 'com.android.application'
2+
3+
android {
4+
compileSdkVersion 26
5+
defaultConfig {
6+
applicationId "io.github.tscholze.firebasepager"
7+
minSdkVersion 26
8+
targetSdkVersion 26
9+
versionCode 1
10+
versionName "1.0"
11+
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12+
}
13+
buildTypes {
14+
release {
15+
minifyEnabled false
16+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17+
}
18+
}
19+
}
20+
21+
dependencies {
22+
implementation fileTree(dir: 'libs', include: ['*.jar'])
23+
implementation 'com.google.android.things.contrib:driver-ht16k33:0.3'
24+
implementation 'com.android.support:support-v4:26.1.0'
25+
implementation 'com.google.firebase:firebase-messaging:11.0.4'
26+
testImplementation 'junit:junit:4.12'
27+
androidTestImplementation 'com.android.support.test:runner:1.0.1'
28+
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
29+
compileOnly 'com.google.android.things:androidthings:+'
30+
}
31+
32+
33+
apply plugin: 'com.google.gms.google-services'

app/proguard-rules.pro

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.github.tscholze.firebasepager;
2+
3+
import android.content.Context;
4+
import android.support.test.InstrumentationRegistry;
5+
import android.support.test.runner.AndroidJUnit4;
6+
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
10+
import static org.junit.Assert.*;
11+
12+
/**
13+
* Instrumented test, which will execute on an Android device.
14+
*
15+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
16+
*/
17+
@RunWith(AndroidJUnit4.class)
18+
public class ExampleInstrumentedTest
19+
{
20+
@Test
21+
public void useAppContext() throws Exception
22+
{
23+
// Context of the app under test.
24+
Context appContext = InstrumentationRegistry.getTargetContext();
25+
26+
assertEquals("io.github.tscholze.firebasepager", appContext.getPackageName());
27+
}
28+
}

app/src/main/AndroidManifest.xml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="io.github.tscholze.firebasepager">
4+
5+
<application>
6+
<uses-library android:name="com.google.android.things" />
7+
8+
<activity android:name=".MainActivity">
9+
<intent-filter>
10+
<action android:name="android.intent.action.MAIN" />
11+
12+
<category android:name="android.intent.category.LAUNCHER" />
13+
</intent-filter>
14+
<intent-filter>
15+
<action android:name="android.intent.action.MAIN" />
16+
17+
<category android:name="android.intent.category.IOT_LAUNCHER" />
18+
<category android:name="android.intent.category.DEFAULT" />
19+
</intent-filter>
20+
</activity>
21+
22+
<service
23+
android:name=".MyFirebaseMessagingService">
24+
<intent-filter>
25+
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
26+
</intent-filter>
27+
</service>
28+
</application>
29+
30+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package io.github.tscholze.firebasepager;
2+
3+
import android.app.Activity;
4+
import android.content.BroadcastReceiver;
5+
import android.content.Context;
6+
import android.content.Intent;
7+
import android.content.IntentFilter;
8+
import android.os.Bundle;
9+
10+
import java.io.IOException;
11+
import java.util.LinkedList;
12+
import java.util.List;
13+
14+
import android.os.Handler;
15+
import android.util.Log;
16+
17+
import com.google.android.things.contrib.driver.ht16k33.AlphanumericDisplay;
18+
import com.google.firebase.iid.FirebaseInstanceId;
19+
import com.google.firebase.messaging.FirebaseMessaging;
20+
21+
/**
22+
* This activity is responsible to display messages from Firebase
23+
* Cloud Messaging notifications on an alphanumerical display.
24+
*/
25+
public class MainActivity extends Activity implements IRunningTextContext
26+
{
27+
private static final String TAG = MainActivity.class.getSimpleName();
28+
private static final String TOPIC_IDENTIFIER = "messages";
29+
private static final String I2C1_BUS_IDENTIFIER = "I2C1";
30+
31+
private AlphanumericDisplay alphanumericDisplay;
32+
private List<String> messages = new LinkedList<>();
33+
private Handler runningTextHandler;
34+
35+
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
36+
{
37+
@Override
38+
public void onReceive(Context context, Intent intent)
39+
{
40+
messages.add(intent.getStringExtra(MyFirebaseMessagingService.EXTRA_BODY));
41+
42+
if (messages.size() == 1)
43+
{
44+
postTextToDisplay();
45+
}
46+
}
47+
};
48+
49+
@Override
50+
protected void onCreate(Bundle savedInstanceState)
51+
{
52+
super.onCreate(savedInstanceState);
53+
54+
FirebaseMessaging.getInstance().subscribeToTopic(TOPIC_IDENTIFIER);
55+
Log.d(TAG, "FCM token: " + FirebaseInstanceId.getInstance().getToken());
56+
57+
setupAlphanumericDisplay();
58+
runningTextHandler = new Handler();
59+
IntentFilter intentFilter = new IntentFilter(MyFirebaseMessagingService.NEW_MESSAGE_ITENT);
60+
registerReceiver(broadcastReceiver, intentFilter);
61+
62+
messages.add("Teeeeeest");
63+
postTextToDisplay();
64+
}
65+
66+
@Override
67+
protected void onDestroy()
68+
{
69+
super.onDestroy();
70+
71+
destroyAlphanumericDisplay();
72+
FirebaseMessaging.getInstance().unsubscribeFromTopic(TOPIC_IDENTIFIER);
73+
}
74+
75+
@Override
76+
public AlphanumericDisplay getAlphaNumericDisplay()
77+
{
78+
return alphanumericDisplay;
79+
}
80+
81+
@Override
82+
public Handler getRunningTextHandler()
83+
{
84+
return runningTextHandler;
85+
}
86+
87+
@Override
88+
public void onRunningTextFinished()
89+
{
90+
Log.d(TAG, "Running text finished");
91+
postTextToDisplay();
92+
}
93+
94+
private void setupAlphanumericDisplay()
95+
{
96+
try
97+
{
98+
alphanumericDisplay = new AlphanumericDisplay(I2C1_BUS_IDENTIFIER);
99+
alphanumericDisplay.setBrightness(1.0f);
100+
alphanumericDisplay.setEnabled(true);
101+
alphanumericDisplay.clear();
102+
}
103+
catch (IOException e)
104+
{
105+
Log.e(TAG, "Error configuring display", e);
106+
}
107+
}
108+
109+
private void destroyAlphanumericDisplay()
110+
{
111+
if (alphanumericDisplay != null)
112+
{
113+
Log.i(TAG, "Closing display");
114+
try
115+
{
116+
alphanumericDisplay.close();
117+
}
118+
catch (IOException e)
119+
{
120+
Log.e(TAG, "Error closing display", e);
121+
}
122+
finally
123+
{
124+
alphanumericDisplay = null;
125+
}
126+
}
127+
}
128+
129+
private void postTextToDisplay()
130+
{
131+
if (messages.isEmpty())
132+
{
133+
return;
134+
}
135+
136+
String message = messages.get(0);
137+
Log.d(TAG, "Will post new message: "+ message);
138+
139+
RunningTextRunnable runnable = new RunningTextRunnable(this, message);
140+
messages.remove(0);
141+
runningTextHandler.post(runnable);
142+
}
143+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package io.github.tscholze.firebasepager;
2+
3+
import android.util.Log;
4+
5+
import java.io.IOException;
6+
7+
import io.github.tscholze.firebasepager.interfaces.IRunningTextContext;
8+
9+
10+
/**
11+
* Running text Runnable that prepares the given text to be
12+
* more segment display friendly.
13+
*
14+
* Original inspiration:
15+
* - Author: JS Koran (https://github.com/jdkoren)
16+
* - Gist: https://gist.github.com/jdkoren/a3c37883f839c0b3adcee43821128329
17+
*/
18+
public class RunningTextRunnable implements Runnable
19+
{
20+
private static final String TAG = RunningTextRunnable.class.getSimpleName();
21+
private static final int MAX_CHARS_PER_CYCLE = 4;
22+
23+
private IRunningTextContext context;
24+
private String text;
25+
private int beginIndex = 0;
26+
private boolean isFirstRun = true;
27+
28+
RunningTextRunnable(IRunningTextContext context, String text)
29+
{
30+
this.context = context;
31+
32+
StringBuilder stringBuilder = new StringBuilder();
33+
34+
// Append leading spaces (text runs completely from right to left).
35+
for(int i = 0; i < MAX_CHARS_PER_CYCLE; i++)
36+
{
37+
stringBuilder.append(' ');
38+
}
39+
40+
// Append trimmed text.
41+
stringBuilder.append(text.trim());
42+
43+
44+
// Append trailing spaces.
45+
int spacesCount = MAX_CHARS_PER_CYCLE - (text.length() % MAX_CHARS_PER_CYCLE);
46+
for(int i = 0; i < spacesCount; i++)
47+
{
48+
stringBuilder.append(' ');
49+
}
50+
51+
this.text = stringBuilder.toString();
52+
53+
Log.d(TAG, "Running text with trailed text: '"+this.text+"'");
54+
}
55+
56+
@Override
57+
public void run()
58+
{
59+
// Try to display the current visible part of the text string.
60+
try
61+
{
62+
context.getAlphaNumericDisplay().display(text.substring(beginIndex));
63+
}
64+
catch (IOException e)
65+
{
66+
e.printStackTrace();
67+
}
68+
69+
// Check if finished parameters are valid.
70+
if(!isFirstRun && beginIndex == 0)
71+
{
72+
context.onRunningTextFinished();
73+
return;
74+
}
75+
76+
// Update the beginIndex for the next cycle.
77+
beginIndex = (beginIndex + 1) % text.length();
78+
isFirstRun = false;
79+
80+
// Post next cycle execution with a delay.
81+
context.getRunningTextHandler().postDelayed(this, 750L);
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.github.tscholze.firebasepager.interfaces;
2+
3+
4+
import android.os.Handler;
5+
6+
import com.google.android.things.contrib.driver.ht16k33.AlphanumericDisplay;
7+
8+
/**
9+
* Describes the required information and listener of a RunningTextRunnable.
10+
*/
11+
public interface IRunningTextContext
12+
{
13+
/**
14+
* Gets the display that will be used to show
15+
* information
16+
* @return An assigned AlphanumericDisplay.
17+
*/
18+
AlphanumericDisplay getAlphaNumericDisplay();
19+
20+
/**
21+
* Gets the activity handler to post runnables.
22+
* @return Assigned handler.
23+
*/
24+
Handler getRunningTextHandler();
25+
26+
/**
27+
* Raised if running text has been finished.
28+
*/
29+
void onRunningTextFinished();
30+
}

0 commit comments

Comments
 (0)