/AndroidInfraRed

Open source project for transmitting signals via IR-blasters on Android devices

Primary LanguageJava

Android Infra Red

Open source project for transmitting signals via IR-blasters on Android devices

Created in Android Studio

Supports Samsung, HTC, some LG devices with IR

Contains:

  • SampleApplication
  • InfraRed library

Email: one.button.developer@gmail.com

Menu

Basis

Basic theory

In order to remotely control a device via IR, you require a transmitter (mobile phone with IR blaster) and a control signal sequence that you want to send. This sequence is the key to the function that the device is supposed to perform (e.g. the function of a TV to turns itself on). The built-in IR receiver of the controlled device analyzes all incoming signals. When they match a pattern of a particular function, the devices calls that function.

The control signal sequence consists of two parameters: The frequency (in Hertz) and the pattern, which is a time sequence of ON/OFF signals on the specified carrier frequency. Such patterns can be found on the Internet.

Sequence types

The pattern is pictured by a sequence of numbers either of the hexadecimal (HEX) or the decimal (DEC) numeral system.

Here's an example:

Frequency:
  33000 Hertz (33KHz)
Patterns:
  0) 0x01f4 0x1c84 0x01f4 0x00c8 or (01f4 1c84 01f4 00c8)
  1) 500 7300 500 200
  2) 17 241 17 7

The main difference between the patterns in this example is their notation. Each number in the pattern describes the duration of a single ON/OFF signal, only that patterns 0 and 1 describe it in microseconds, while patterns 2 describes it in cycles.

One cycle always consists of an an ON and an OFF signal (the image below shows cycles with a frequency of 40000 Hz).

Difference between sequences

Converting the patterns

The length of a single period T in microseconds equals 1 000 000 (1 second in microseconds) divided by the frequency f (in Hertz)

T = 1 000 000 ms / f

For example

T = 1 000 000 ms/ 33000 Hz ≈ 30.3 ms

To covert a microsecond pattern to a cycle pattern, divide each value by T

To convert a cycle pattern to a microsecond pattern, simply multiply each value by T

How to use

0. Include the InfraRed library to your project

  • Download the AndroidInfraRed project
  • Run the project on a device or an emulator
  • Find the infrared-release.aar file in the project folder (infrared/build/outputs/aar/infrared-release.aar)
  • Import this file into your own project in Android Studio (File > New > New Module... > Import .JAR/.AAR package)

Tip! Your can download the infrared-release.aar file from releases

Known issue! One of the project files contains broken characters. Just rename it again.

1. Add the following permissions to your AndroidManifest.xml

	<uses-permission android:name="android.permission.TRANSMIT_IR" android:required="false"/>
	<uses-feature android:name="android.hardware.consumerir" android:required="false"/>

2. Initialize logging

You can choose between printing your logs to an EditText view (LogToEditText), the LogCat console (LogToConsole) and not logging at all (LogToAir)

	// print log messages to EditText
	EditText console = (EditText) this.findViewById(R.id.console);
	log = new LogToEditText(console, TAG);

	// print Log messages with Log.d(), Log.w(), Log.e() (LogCat)
	// LogToConsole log = new LogToConsole(TAG);

	// Turn off logs
	// LogToAir log = new LogToAir(TAG);

LogToEditText is the default option

3. Initialize the InfraRed class

Create a new InfraRed object with the parameters Context and Logger

	infraRed = new InfraRed(this, log);

4. Initialize the transmitter

	TransmitterType transmitterType = infraRed.detect();

	// initialize transmitter by type
	infraRed.createTransmitter(transmitterType);

The "detect()" method returns the TransmitterType. Possible values:

  • Actual - The signals will be transmitted by the ConsumerIrManager
  • Obsolete - The signals will be transmitted by a Samsung IR service
  • HTC - The signals will be transmitted by the HTC IR SDK
  • LG, LG_WithOutDevice - The signals will be transmitted by the QRemote SDK
  • Undefined - the "empty" implementation will be used to transmitt the signals

5. Initialize the raw patterns

	// initialize raw patterns
	List<PatternConverter> rawPatterns = new ArrayList<>();
	// Canon
	// rawPatterns.add(new PatternConverter(PatternType.Intervals, 33000, 500, 7300, 500, 200));
	// Nikon D7100 v.1
	rawPatterns.add(new PatternConverter(PatternType.Cycles, 38400, 1, 105, 5, 1, 75, 1095, 20, 60, 20, 140, 15, 2500, 80, 1));
	// Nikon D7100 v.2
	rawPatterns.add(new PatternConverter(PatternType.Cycles, 38400, 77, 1069, 16, 61, 16, 137, 16, 2427, 77, 1069, 16, 61, 16, 137, 16));
	// Nikon D7100 v.3
	rawPatterns.add(new PatternConverter(PatternType.Intervals, 38000, 2000, 27800, 400, 1600, 400, 3600, 400, 200));
	// Nikon D7100 v.3 fromString
	rawPatterns.add(PatternConverterUtils.fromString(PatternType.Intervals, 38000, "2000, 27800, 400, 1600, 400, 3600, 400, 200"));
	// Nikon D7100 v.3 fromHexString
	rawPatterns.add(PatternConverterUtils.fromHexString(PatternType.Intervals, 38000, "0x7d0 0x6c98 0x190 0x640 0x190 0xe10 0x190 0xc8"));
	// Nikon D7100 v.3 fromHexString without 0x
	rawPatterns.add(PatternConverterUtils.fromHexString(PatternType.Intervals, 38000, "7d0 6c98 190 640 190 e10 190 c8"));

The PatternConverter can be used to easily define and convert IR patterns between the different patterns types (Cycles and Intervals in ms)

6. Adapt the patterns for the device that is used to transmit the patterns

	PatternAdapter patternAdapter = new PatternAdapter(log);
	
	// initialize TransmitInfoArray
	TransmitInfo[] transmitInfoArray = new TransmitInfo[rawPatterns.size()];
	for (int i = 0; i < transmitInfoArray.length; i++) {
	    transmitInfoArray[i] = patternAdapter.createTransmitInfo(rawPatterns.get(i));
	}
	this.patterns = transmitInfoArray;

PatternAdapter automatically detects the device's manufacturer (LG/HTC/Samsung) and uses that information to determine how the raw patterns have to be converted in order to be compatible with the transmitter of the used device.

7. Implement the start and stop methods

    @Override
    protected void onResume() {
        super.onResume();
        infraRed.start();
    }
   
    @Override
    protected void onDestroy() {
        super.onDestroy();

        infraRed.stop();

        if (log != null) {
            log.destroy();
        }
    }

Always call the start() method before transmit IR signals and call the stop() method when you are done.

It is a good idea to call them in the onCreate/onDestroy or onResume/onPause methods.

8. Transmit the adapted patterns via IR

    private int currentPattern = 0;

    @Override
    public void onClick(View v) {
        TransmitInfo transmitInfo = patterns[currentPattern++];
        if (currentPattern >= patterns.length) currentPattern = 0;
        infraRed.transmit(transmitInfo);
    }

Now we can send IR signals (TransmitInfo) to the device we want to control

In addition

Examples for the individual steps can be found in this project

What's in the box?

Android Project - Sample Application

The sample project gives you an idea how the infrared library is supposed to be used. The project contains an activity (MainActivity.java) with a predefined layout (activity_main.xml). The layout contains a console (EditText) and a IR button.

The onCreate() method contains the full initialization of the InfraRed library

When you run the application, the console will show you what is happening inside the library. When you click on the button, the IR blaster on your device will send a IR signal, of course only if your device is supported by the library.

Please note that you wont get any runtime exceptions because your device is not supported.

Logging to a EditText can be quite useful when you want to understand what's happening on your customer's devices. I often send special .apk files to users in order to obtain a log from their devices.

Android Library - Infrared

This library allows you to easily create raw IR signals in code, to detect device types and adapt raw signals for specific devices, to detect the devices' IR transmitters and to use them to send the adapted IR signals to a devices with a IR receiver.

The Library consists of several packages that are explained below.

Provides different ways to log data. All classes in this package inherit from the Logger class.

LogToConsole is useful when your can debug the application on a device that is connected to an IDE with LogCat.

LogToEditText can be used to to display the log messages on the user's screen.

LogToAir won't log anything (you can apply this in your application's release version)

Enum PatternType tetermines the type of the IR signals in an integer array (a single value in the array is either the number of cycles or the time interval in microseconds).

The PatternConverter class allows you to convert patterns from one pattern type to another.

The PatternConverterUtils class can be used to create PatternConverter objects from strings containing a pattern in the DEC or HEX numeral system.

PatternAdapterType enum contains values that are required to convert raw patterns. It also includes a method that determines which pattern type will be in use on the current device. It returns ToIntervals by default, which will convert all raw patterns to time interval based patterns.

The PatternAdapter class will help you to adapt PatternConverter instances to TransmitInfo objects according to the PatternAdapterType enum.

The DeviceDetector class is used to determine the manufacturer of the user's device by checking Android's Build.MANUFACTURER constant. This information is required in order to adapt the IR signals correctly.

The InfraRedDetector class checks if the devices has a built-in IR blaster. This procedure may vary depending on the IR Blaster, so there are a few different classes for this feature with a common interface named IDetector. Concrete implementations of the IDetector can be found in the "infrared/detection/concrete" folder.

InfraRedDetector has a main function detect() that verifies the availability of each initialized detector and returns corresponding TransmitterType. The method returns TransmitterType.Undefined if the device is not supported.

TransmitterType enum contains the supported transmitters which also includes the Undefined transmitter.

The TransmitInfo class contains the adapted IR signal data that will be send by the device's IR blaster.

The Transmitter class the is general interface type for all transmitters. Concrete implementations of them can be found in the "infrared/transmit/concrete" folder. Each transmitter can implement start() and stop() methods and must have a transmit function that sends the pattern data with a TransmitInfo.

A Transmitter can initialize concrete transmitters based on the TransmitterType.

The InfraRed class integrate packages functionality to easily use library.

  1. Create InfraRed class
  2. Call the detect() method to get the TransmitterType
  3. Call the createTransmitter() method to initialize a concrete transmitter
  4. Call the start() method
  5. Send different IR signals (TransmitInfo objects) with the transmit() function

! Don't forget to call stop() once you are done!