// IPTV extension for App Inventor by Marco Perrone package Iptv; import com.google.appinventor.components.runtime.*; import android.app.Activity; import android.content.Intent; import com.google.appinventor.components.annotations.DesignerComponent; import com.google.appinventor.components.annotations.DesignerProperty; import com.google.appinventor.components.annotations.PropertyCategory; import com.google.appinventor.components.annotations.SimpleFunction; import com.google.appinventor.components.annotations.SimpleEvent; import com.google.appinventor.components.annotations.SimpleObject; import com.google.appinventor.components.annotations.SimpleProperty; import com.google.appinventor.components.annotations.UsesPermissions; import com.google.appinventor.components.annotations.UsesActivities; import com.google.appinventor.components.annotations.UsesLibraries; import com.google.appinventor.components.annotations.UsesActivityMetadata; import com.google.appinventor.components.annotations.androidmanifest.*; import com.google.appinventor.components.common.ComponentCategory; import com.google.appinventor.components.common.PropertyTypeConstants; import com.google.appinventor.components.common.YaVersion; import com.google.appinventor.components.runtime.util.GingerbreadUtil; import com.google.appinventor.components.runtime.util.SdkLevel; import com.google.appinventor.components.runtime.util.AsynchUtil; import com.google.appinventor.components.runtime.util.YailList; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URI; import java.net.URISyntaxException; import java.net.CookieHandler; import java.util.Scanner; import java.util.Iterator; import java.util.Map; import java.util.List; import java.util.ArrayList; import java.io.FileWriter; import java.io.BufferedWriter; import java.io.StringWriter; import java.io.PrintWriter; import java.io.IOException; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.DataOutputStream; import java.io.BufferedReader; import java.io.OutputStream; @SimpleObject(external=true) @UsesPermissions(permissionNames = "android.permission.INTERNET") @DesignerComponent(version = YaVersion.WEB_COMPONENT_VERSION, description = "

Non-visible component to search IPTV from all over the world.", category = ComponentCategory.EXTENSION, nonVisible = true, iconName = "images/nearfield.png") public class Iptv extends AndroidNonvisibleComponent implements Component { private final Activity activity; private final CookieHandler cookieHandler; private String twoHyphens = "--"; private String boundary = "*****"+Long.toString(System.currentTimeMillis())+"*****"; private String LINE = "\r\n"; private URL url; private HttpURLConnection httpConn = null; private OutputStream outputStream; private PrintWriter writer; private String charset = "utf-8"; @SimpleEvent(description = "Got Countries") public void GotCountries(int responseCode, String response, YailList country, YailList countryCode, YailList language, String message) { EventDispatcher.dispatchEvent(this, "GotCountries", responseCode, response, country, countryCode, language, message); } @SimpleEvent(description = "Got Categories") public void GotCategories(int responseCode, String response, YailList categories, String message) { EventDispatcher.dispatchEvent(this, "GotCategories", responseCode, response, categories, message); } @SimpleEvent(description = "Got Channels") public void GotChannels(int responseCode, YailList name, YailList website ,YailList logo, YailList urlStream, YailList category, String message) { EventDispatcher.dispatchEvent(this, "GotChannels", responseCode, name, website, logo, urlStream, category, message); } @SimpleFunction(description = "Get Countries") public void GetCountries() { AsynchUtil.runAsynchronously(new Runnable() { @Override public void run() { GetCountries_Exec(); } }); } @SimpleFunction(description = "Get Categories") public void GetCategories() { AsynchUtil.runAsynchronously(new Runnable() { @Override public void run() { GetCategories_Exec(); } }); } @SimpleFunction(description = "Get Channels") public void GetChannels(final String country, final String limit, final String name ) { AsynchUtil.runAsynchronously(new Runnable() { @Override public void run() { int limitInt; try { limitInt = Integer.parseInt(limit); } catch (Exception e) { limitInt = 1000; } GetChannels_Exec(country, limitInt, name); } }); } public Iptv(ComponentContainer container) { super(container.$form()); activity = container.$context(); cookieHandler = (SdkLevel.getLevel() >= SdkLevel.LEVEL_GINGERBREAD) ? GingerbreadUtil.newCookieManager() : null; } void GetCountries_Exec() { try { InputStream inputStream = null; String URLStr = "https://iptv-org.github.io/api/countries.json"; URL url = new URL(URLStr); httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); httpConn.setRequestProperty("Connection", "Keep-Alive"); httpConn.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0"); final int status = httpConn.getResponseCode(); List country = new ArrayList(); List countryCode = new ArrayList(); List language = new ArrayList(); String Msg = ""; if (status == HttpURLConnection.HTTP_OK) { inputStream = httpConn.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getInputStream())); String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } final String responseStr = response.toString(); String ImportantValues = ""; String countryStr = ""; String countryCodeStr = ""; String languageStr = ""; if (responseStr.indexOf("name") != -1) { ImportantValues = responseStr; while (ImportantValues.indexOf("name") != -1) { ImportantValues = ImportantValues.substring(ImportantValues.indexOf("name")+7); countryStr = ImportantValues.substring(0,ImportantValues.indexOf("\"")); country.add(countryStr); countryCodeStr = ImportantValues.substring(ImportantValues.indexOf("code")+7); countryCodeStr = countryCodeStr.substring(0,countryCodeStr.indexOf("\"")); countryCode.add(countryCodeStr); languageStr = ImportantValues.substring(ImportantValues.indexOf("lang")+7); languageStr = languageStr.substring(0,languageStr.indexOf("\"")); language.add(languageStr); } } else { if (responseStr.indexOf("message") != -1) { Msg = responseStr.substring(responseStr.indexOf("message")+10); Msg = Msg.substring(0,Msg.indexOf("\"")); } else { Msg = "No results found"; } } httpConn.disconnect(); final List countryFin = country; final List countryCodeFin = countryCode; final List languageFin = language; final String Message = Msg; // Dispatch the event. activity.runOnUiThread(new Runnable() { @Override public void run() { GotCountries(status, responseStr , YailList.makeList(countryFin), YailList.makeList(countryCodeFin), YailList.makeList(languageFin), Message); } }); } else { InputStream inputStreamErr = httpConn.getErrorStream(); BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getErrorStream())); String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } final String responseStr = response.toString(); httpConn.disconnect(); // Dispatch the event. activity.runOnUiThread(new Runnable() { @Override public void run() { GotCountries(status, responseStr , null, null, null, ""); } }); } } catch (Exception e) { e.printStackTrace(); StringWriter errors = new StringWriter(); e.printStackTrace(new PrintWriter(errors)); appendLog(errors.toString()); } } void GetCategories_Exec() { try { InputStream inputStream = null; String URLStr = "https://iptv-org.github.io/api/categories.json"; URL url = new URL(URLStr); httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); httpConn.setRequestProperty("Connection", "Keep-Alive"); httpConn.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0"); final int status = httpConn.getResponseCode(); List categories = new ArrayList(); String Msg = ""; if (status == HttpURLConnection.HTTP_OK) { inputStream = httpConn.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getInputStream())); String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } final String responseStr = response.toString(); String ImportantValues = ""; String categoriesStr = ""; if (responseStr.indexOf("name") != -1) { ImportantValues = responseStr; while (ImportantValues.indexOf("name") != -1) { ImportantValues = ImportantValues.substring(ImportantValues.indexOf("name")+7); categoriesStr = ImportantValues.substring(0,ImportantValues.indexOf("\"")); if (categoriesStr.indexOf("XXX") == -1) { categories.add(categoriesStr); } } } else { if (responseStr.indexOf("message") != -1) { Msg = responseStr.substring(responseStr.indexOf("message")+10); Msg = Msg.substring(0,Msg.indexOf("\"")); } else { Msg = "No results found"; } } httpConn.disconnect(); final List categoriesFin = categories; final String Message = Msg; // Dispatch the event. activity.runOnUiThread(new Runnable() { @Override public void run() { GotCategories(status, responseStr , YailList.makeList(categoriesFin) , Message); } }); } else { InputStream inputStreamErr = httpConn.getErrorStream(); BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getErrorStream())); String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } final String responseStr = response.toString(); httpConn.disconnect(); // Dispatch the event. activity.runOnUiThread(new Runnable() { @Override public void run() { GotCategories(status, responseStr , null, ""); } }); } } catch (Exception e) { e.printStackTrace(); StringWriter errors = new StringWriter(); e.printStackTrace(new PrintWriter(errors)); appendLog(errors.toString()); } } void GetChannels_Exec(String COUNTRY, int LIMIT, String NAME) { String Channels = ""; try { InputStream inputStream = null; String URLStr = "https://iptv-org.github.io/api/channels.json"; URL url = new URL(URLStr); httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); httpConn.setRequestProperty("Connection", "Keep-Alive"); httpConn.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0"); final int status = httpConn.getResponseCode(); String Msg = ""; if (status == HttpURLConnection.HTTP_OK) { inputStream = httpConn.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getInputStream())); String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } Channels = response.toString(); httpConn.disconnect(); } } catch (Exception e) { e.printStackTrace(); StringWriter errors = new StringWriter(); e.printStackTrace(new PrintWriter(errors)); appendLog(errors.toString()); } try { InputStream inputStream = null; String URLStr = "https://iptv-org.github.io/api/streams.json"; URL url = new URL(URLStr); httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); httpConn.setRequestProperty("Connection", "Keep-Alive"); httpConn.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0"); final int status = httpConn.getResponseCode(); List channelName = new ArrayList(); List website = new ArrayList(); List logo = new ArrayList(); List urlStream = new ArrayList(); List category = new ArrayList(); String Msg = ""; String ImportantValues = ""; String channelIdStr = ""; String urlStreamStr = ""; String statusStr = ""; String ChannelValues = ""; String CountryCode = ""; String CategoryChannel = ""; String ChannelNameStr = ""; String websiteStr = ""; String logoStr = ""; if (status == HttpURLConnection.HTTP_OK) { inputStream = httpConn.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getInputStream())); String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } final String responseStr = response.toString(); if (responseStr.indexOf("channel") != -1) { ImportantValues = responseStr; boolean ChannelLimit = true; int ChannelFound = 0; while ((ImportantValues.indexOf("channel") != -1) && (ChannelLimit == true)) { ImportantValues = ImportantValues.substring(ImportantValues.indexOf("channel\"")+10); channelIdStr = ImportantValues.substring(0,ImportantValues.indexOf("\"")); urlStreamStr = ImportantValues.substring(ImportantValues.indexOf("url")+6); urlStreamStr = urlStreamStr.substring(0,urlStreamStr.indexOf("\"")); statusStr = ImportantValues.substring(ImportantValues.indexOf("status")+9); statusStr = statusStr.substring(0,statusStr.indexOf("\"")); if (statusStr.equals("online") == true) // select only the channels online { if (Channels.indexOf(channelIdStr) != -1) { ChannelValues = Channels.substring(Channels.indexOf(channelIdStr)); CountryCode = ChannelValues.substring(ChannelValues.indexOf("country")+10); CountryCode = CountryCode.substring(0,CountryCode.indexOf("\"")); if (CountryCode.equals(COUNTRY) == true) { CategoryChannel = ChannelValues.substring(ChannelValues.indexOf("categories")+12); CategoryChannel = CategoryChannel.substring(0,CategoryChannel.indexOf("]")+1); if (CategoryChannel.indexOf("xxx") == -1) // filter to remove the adult channels { if (CategoryChannel.indexOf("[]") != -1) { CategoryChannel = "Other"; } else { CategoryChannel = CategoryChannel.substring(CategoryChannel.indexOf("[\"")+2); CategoryChannel = CategoryChannel.substring(0, CategoryChannel.indexOf("\"]")); } ChannelNameStr = ChannelValues.substring(ChannelValues.indexOf("name")+7); ChannelNameStr = ChannelNameStr.substring(0,ChannelNameStr.indexOf("\"")); if (NAME.length() > 0) { if (ChannelNameStr.indexOf(NAME) != -1) { channelName.add(ChannelNameStr); category.add(CategoryChannel); websiteStr = ChannelValues.substring(ChannelValues.indexOf("website")+10); websiteStr = websiteStr.substring(0,websiteStr.indexOf("\"")); if (websiteStr.compareTo("ull,") == 0) { websiteStr = "unavailable"; } website.add(websiteStr); logoStr = ChannelValues.substring(ChannelValues.indexOf("logo")+7); logoStr = logoStr.substring(0,logoStr.indexOf("\"")); if (logoStr.compareTo("ull,") == 0) { logoStr = "unavailable"; } logo.add(logoStr); urlStream.add(urlStreamStr); if (LIMIT > 0) { ChannelFound = ChannelFound + 1; if (ChannelFound == LIMIT) { ChannelLimit = false; } } } } else { channelName.add(ChannelNameStr); category.add(CategoryChannel); websiteStr = ChannelValues.substring(ChannelValues.indexOf("website")+10); websiteStr = websiteStr.substring(0,websiteStr.indexOf("\"")); if (websiteStr.compareTo("ull,") == 0) { websiteStr = "unavailable"; } website.add(websiteStr); logoStr = ChannelValues.substring(ChannelValues.indexOf("logo")+7); logoStr = logoStr.substring(0,logoStr.indexOf("\"")); if (logoStr.compareTo("ull,") == 0) { logoStr = "unavailable"; } logo.add(logoStr); urlStream.add(urlStreamStr); if (LIMIT > 0) { ChannelFound = ChannelFound + 1; if (ChannelFound == LIMIT) { ChannelLimit = false; } } } } } } } } } else { if (responseStr.indexOf("message") != -1) { Msg = responseStr.substring(responseStr.indexOf("message")+10); Msg = Msg.substring(0,Msg.indexOf("\"")); } else { Msg = "No results found"; } } httpConn.disconnect(); final List channelNameFin = channelName; final List websiteFin = website; final List logoFin = logo; final List urlStreamFin = urlStream; final List categoryFin = category; final String Message = Msg; // Dispatch the event. activity.runOnUiThread(new Runnable() { @Override public void run() { GotChannels(status, YailList.makeList(channelNameFin) , YailList.makeList(websiteFin), YailList.makeList(logoFin), YailList.makeList(urlStreamFin), YailList.makeList(categoryFin), Message); } }); } else { InputStream inputStreamErr = httpConn.getErrorStream(); BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getErrorStream())); String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } final String responseStr = response.toString(); httpConn.disconnect(); // Dispatch the event. activity.runOnUiThread(new Runnable() { @Override public void run() { GotChannels(status, null, null, null, null, null, ""); } }); } } catch (Exception e) { e.printStackTrace(); StringWriter errors = new StringWriter(); e.printStackTrace(new PrintWriter(errors)); appendLog(errors.toString()); } } public void appendLog(String text) { File logFile = new File("sdcard/IptvLog.txt"); if (!logFile.exists()) { try { logFile.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { //BufferedWriter for performance, true to set append to file flag BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true)); buf.append(text); buf.newLine(); buf.flush(); buf.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }