alexbirukov

[Статья] PHP сервер для рассылки Push на Android и iOS

46 сообщений в этой теме

В статья я максимально подробно попытался описать работу с PHP скриптом для рассылки Push сообщений из любой программы вне зависимости от платформы. Затрагивается вопроса от экспорта скриптов до кода программы: отправка и получение Push, регистрация устройств.

 

Надеюсь кому-нибудь пригодится. Буду рад комментариям, обоснованной критике и доработкам.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

чорт, я всю неделю провел, раскапывая эту тему, и то до конца не достал ))

а надо было просто немного подождать ))))

огромное спасибо за статью

alexbirukov понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Админы, а нельзя это перенести в раздел "статьи"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Добрый день.Статья хорошая,все подробно написано и в принципе понятно.Решил попробовать,в PHP не силен.Все сделал,регистрация устройства проходит,в таблицу заносится.Но при попытке отправки ругается вот на что:

function SendAndroid($tokens, $text, $config)
	{
		# Создаём поток для отправки с использование API ключа
		$sender = new /CodeMonkeysRu/GCM/Sender/ ($config['gcm']['apikey']);
		# Создаём сообщение для указаных токенов
		$message = new /CodeMonkeysRu/GCM/Message/ ($tokens (array("message" => $text))); 

На строке:

$sender = new /CodeMonkeysRu/GCM/Sender/ ($config['gcm']['apikey']); 

Выдает ошибку:

 

Parse error: syntax error, unexpected '/' in /public_html/push.php on line 235

 

Я вижу что ему не нравится символ '/'.Но никак не могу понять в чем подвох.

 

Изменено пользователем dante333

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Странно, у меня код всё несколько другой:

 

# Создаём поток для отправки с использование API ключа
$sender = new \CodeMonkeysRu\GCM\Sender($config['gcm']['apikey']);
# Создаём сообщение для указаных токенов
$message = new \CodeMonkeysRu\GCM\Message($tokens, array("message" => $text));

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо,теперь ошибок нет.Теперь загвоздка в другом.Я проверял регистрацию устройств через браузер,скопировал ссылку из статьи,прописал токен и id устроиства,все отлично.В БД все записывается.Теперь набросал в Delphi приложение,опять же по статье.Все скомпилировалось и установилось без ошибок,но при запуске регистрация не проходит.Манифест правил,разрешения проставил.У меня уже есть приложение с пушами через kinvey,оно работает,пуши приходят.Но хотелось бы уйти от kinvey,собственно ради этого и затеял все.

 

UPD.Пока писал,приложение компилилось еще раз и о чудо,все заработало.Спасибо за помощь.

Изменено пользователем dante333
Kitty и alexbirukov понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо,теперь ошибок нет.Теперь загвоздка в другом.Я проверял регистрацию устройств через браузер,скопировал ссылку из статьи,прописал токен и id устроиства,все отлично.В БД все записывается.Теперь набросал в Delphi приложение,опять же по статье.Все скомпилировалось и установилось без ошибок,но при запуске регистрация не проходит.Манифест правил,разрешения проставил.У меня уже есть приложение с пушами через kinvey,оно работает,пуши приходят.Но хотелось бы уйти от kinvey,собственно ради этого и затеял все.

 

UPD.Пока писал,приложение компилилось еще раз и о чудо,все заработало.Спасибо за помощь.

Собственно, от кинвей и парсе на XE10 пришлось уйти, т.к. запустить их на iOS их на новой версии не вышло. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Подскажите, пожалуйста, в чем может быть проблема?

На строке:

APushService->AppProps[TPushService_TAppPropNames_GCMAppID] = FAndroidServerKey;

Ошибка: segmentation fault 11

 

TForm1 *Form1;
const String FAndroidServerKey = L"875940064719";

void __fastcall TForm1::FormShow(TObject *Sender)
{
  APushService = nullptr;
  AServiceConnection = nullptr;

  String ADeviceID = "";
  String ADeviceToken = "";
  #if defined(__ANDROID__)
  APushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_GCM);
  APushService->AppProps[TPushService_TAppPropNames_GCMAppID] = FAndroidServerKey;
  #endif
  #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
  APushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_APS);
  #endif

  if (APushService)
    {
		AServiceConnection = new TPushServiceConnection(APushService);
		AServiceConnection->OnChange = &OnServiceConnectionChange;
		AServiceConnection->OnReceiveNotification = &OnReceiveNotificationEvent;
		AServiceConnection->Active = true;

		ADeviceID  = APushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];
		ADeviceToken = APushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];

		if(ADeviceID != "" && ADeviceToken != "")
		  {
		   RegisterDevice(ADeviceID, ADeviceToken); //global.hpp
		  }
	}

}

Весь код:


    void __fastcall OnReceiveNotificationEvent(TObject *Sender, TPushServiceNotification* const ANotification);
    void __fastcall OnServiceConnectionChange(TObject *Sender, TPushService::TChanges AChange);


private:	// User declarations
     TPushService * APushService;
	 TPushServiceConnection * AServiceConnection;

//cpp
void __fastcall TForm1::FormShow(TObject *Sender)
{
  APushService = nullptr;
  AServiceConnection = nullptr;

  String ADeviceID = "";
  String ADeviceToken = "";
  #if defined(__ANDROID__)
  APushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_GCM);
  APushService->AppProps[TPushService_TAppPropNames_GCMAppID] = FAndroidServerKey;
  #endif
  #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
  APushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_APS);
  #endif

  if (APushService)
    {
		AServiceConnection = new TPushServiceConnection(APushService);
		AServiceConnection->OnChange = &OnServiceConnectionChange;
		AServiceConnection->OnReceiveNotification = &OnReceiveNotificationEvent;
		AServiceConnection->Active = true;

		ADeviceID  = APushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];
		ADeviceToken = APushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];

		if(ADeviceID != "" && ADeviceToken != "")
		  {
		   RegisterDevice(ADeviceID, ADeviceToken); //global.hpp
		  }
	}

}
//---------------------------------------------------------------------------

void __fastcall TForm1::OnServiceConnectionChange(TObject *Sender, TPushService::TChanges AChange)
{
	if (AChange.Contains(TPushService::TChange::DeviceToken) && (AServiceConnection))
    {
        String ADeviceID = "";
        String ADeviceToken = "";
		ADeviceID = APushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];
		ADeviceToken = APushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];

		if(ADeviceID != "" && ADeviceToken != "")
		  {
		   RegisterDevice(ADeviceID, ADeviceToken); //global.hpp
		  }

	}

}
//---------------------------------------------------------------------------

void __fastcall TForm1::OnReceiveNotificationEvent(TObject *Sender, TPushServiceNotification* const ANotification)
{
    //ShowMessage(ANotification->Json->ToString());

	String MessageText = "";
	//Получаем текст сообщения в зависимости ль платформы
	#if defined(__ANDROID__)
	MessageText = ANotification->DataObject->GetValue("message")->Value();
	#endif
	#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
	MessageText = ANotification->DataObject->GetValue("alert")->Value();
	#endif
	if(MessageText != "")
		ShowNotification(MessageText, 0);

}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

незнаю как на плюсах будет, в uses добавлены?

System.PushNotification
{$IFDEF ANDROID}, FMX.PushNotification.Android {$ENDIF}
{$IFDEF IOS}, FMX.PushNotification.iOS{$ENDIF}

 

Kitty понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
//h
#include <System.PushNotification.hpp>

//cpp
#if defined(__ANDROID__)
#include <FMX.PushNotification.Android.hpp>
#endif
#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
#include <FMX.PushNotification.IOS.hpp>
#endif

segmentation fault 11

и попадаем в файл System.PushNotification на строки

procedure TPushService.SetAppProp(const AName, AValue: string);
begin
  FAppProps.AddOrSetValue(AName, AValue);
end;

Что можно еще посоветовать?

Спасибо.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Какие uses-permission надо?


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

segmentation fault 11

Ничего не помогает, все настроено так как в статье... :)

Изменено пользователем Kitty

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А в опциях проекта в окне разрешений какие галочки должны стоять? У меня там все галочки сброшены.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, Равиль Зарипов (ZuBy) сказал:

READ_PHONE_STATE вроде нужно

Добавила. Видимо еще какая-то настройка мною упущена. APushService = 0х0...

 

 

null1.jpg

Изменено пользователем Kitty

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вроде тут похожая проблема:

APushService is always nil

только не поняла, а что же надо сделать?...

Мой манифест в общей папке проекта AndroidManifest.template.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="%package%"
        android:versionCode="%versionCode%"
        android:versionName="%versionName%"
        android:installLocation="%installLocation%">

    <!-- This is the platform API where NativeActivity was introduced. -->
    <uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
<%uses-permission%>

    <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
    <application android:persistent="%persistent%" 
        android:restoreAnyVersion="%restoreAnyVersion%" 
        android:label="%label%" 
        android:debuggable="%debuggable%" 
        android:largeHeap="%largeHeap%"
        android:icon="%icon%"
        android:theme="%theme%"
        android:hardwareAccelerated="%hardwareAccelerated%">

<%application-meta-data%>
		<%services%>
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                android:label="%activityLabel%"
                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="%libNameValue%" />
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
        </activity>
        <%activity%>
		<service android:name="com.embarcadero.gcm.notifications.GCMIntentService" /> 
        <%receivers%>
		
    </application>
</manifest>
<!-- END_INCLUDE(manifest) -->

А такой манифест AndroidManifest.xml в паке релиз:

<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="ua.com.mikros.Promo"
        android:versionCode="1"
        android:versionName="1.0.0"
        android:installLocation="auto">

    <!-- This is the platform API where NativeActivity was introduced. -->
    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <permission android:name="ua.com.mikros.Promo.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="ua.com.mikros.Promo.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />


    <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
    <application android:persistent="False" 
        android:restoreAnyVersion="False" 
        android:label="Promo" 
        android:debuggable="True" 
        android:largeHeap="False"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme"
        android:hardwareAccelerated="true">


		
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                android:label="Promo"
                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="Promo" />
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
        </activity>
        
		<service android:name="com.embarcadero.gcm.notifications.GCMIntentService" /> 
        <receiver android:name="com.embarcadero.rtl.notifications.NotificationAlarm" />
<receiver android:exported="true" android:name="com.embarcadero.gcm.notifications.GCMNotification" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="ua.com.mikros.Promo" />
</intent-filter>
</receiver>

		
    </application>
</manifest>
<!-- END_INCLUDE(manifest) -->

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, Kitty сказал:

Вроде тут похожая проблема:

APushService is always nil

только не поняла, а что же надо сделать?...

Мой манифест в общей папке проекта AndroidManifest.template.xml:


<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="%package%"
        android:versionCode="%versionCode%"
        android:versionName="%versionName%"
        android:installLocation="%installLocation%">

    <!-- This is the platform API where NativeActivity was introduced. -->
    <uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
<%uses-permission%>

    <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
    <application android:persistent="%persistent%" 
        android:restoreAnyVersion="%restoreAnyVersion%" 
        android:label="%label%" 
        android:debuggable="%debuggable%" 
        android:largeHeap="%largeHeap%"
        android:icon="%icon%"
        android:theme="%theme%"
        android:hardwareAccelerated="%hardwareAccelerated%">

<%application-meta-data%>
		<%services%>
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                android:label="%activityLabel%"
                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="%libNameValue%" />
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
        </activity>
        <%activity%>
		<service android:name="com.embarcadero.gcm.notifications.GCMIntentService" /> 
        <%receivers%>
		
    </application>
</manifest>
<!-- END_INCLUDE(manifest) -->

А такой манифест AndroidManifest.xml в паке релиз:


<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="ua.com.mikros.Promo"
        android:versionCode="1"
        android:versionName="1.0.0"
        android:installLocation="auto">

    <!-- This is the platform API where NativeActivity was introduced. -->
    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <permission android:name="ua.com.mikros.Promo.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="ua.com.mikros.Promo.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />


    <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
    <application android:persistent="False" 
        android:restoreAnyVersion="False" 
        android:label="Promo" 
        android:debuggable="True" 
        android:largeHeap="False"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme"
        android:hardwareAccelerated="true">


		
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                android:label="Promo"
                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="Promo" />
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
        </activity>
        
		<service android:name="com.embarcadero.gcm.notifications.GCMIntentService" /> 
        <receiver android:name="com.embarcadero.rtl.notifications.NotificationAlarm" />
<receiver android:exported="true" android:name="com.embarcadero.gcm.notifications.GCMNotification" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="ua.com.mikros.Promo" />
</intent-filter>
</receiver>

		
    </application>
</manifest>
<!-- END_INCLUDE(manifest) -->

 

В чем различия?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Проблема в том, что я не вижу проблему... :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Проблема с билдером решена и он может теперь работать с пушами. Источник: как исправить баг

У меня вопрос по статье. Вот в статье есть код:

const
  // Доменное имя сайта 
  DOMAIN: string = '193.106.248.115';

implementation


procedure RegisterDevice(DeviceID : string; DeviceToken : string);
var
  // Данные для передачи скрипту
  postdata: TStringList;
  // Подключение для передачи данных
  httpconnect : TIdHTTP;
begin

  try
    // Создаём подключение
    httpconnect := TIdHTTP.Create;
    // Указываем данные для отправки
    postdata := TStringList.Create;
    postdata.Add('action=register-device');
    postdata.Add('did=' + DeviceID);
    postdata.Add('token=' + DeviceToken);
    {$ifdef ANDROID}
      postdata.Add('platform=android');
    {$else}
      postdata.Add('platform=ios');
    {$endif}

    // Отправляем запрос
    httpconnect.Post(DOMAIN + 'push.php', postdata);
  finally
    // Отключаемся и освобождаем память
    httpconnect.Disconnect;
    httpconnect.DisposeOf;
  end;
end;

Два вопроса:

У меня, к примеру, весь PHP сервер скопирован в корень 193.106.248.115 в папку Push_Server.

1. Мне надо объявить константу так? ->

const
  // Доменное имя сайта
  DOMAIN: string = '193.106.248.115/Push_Server';

или как?

2. Не знаю паскаль. Почему нет освобождения памяти для postdata?

postdata := TStringList.Create;

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В паскале если сам создал, то и уничтожать надо самому

   IF Assigned( postdata  ) THEN BEGIN
      postdata.DisposeOf;
      postdata := Nil;
   END;

Kitty понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Скажите вот так будет правильно?

procedure RegisterDevice(DeviceID : string; DeviceToken : string);
var
  // Данные для передачи скрипту
  postdata: TStringList;
  // Подключение для передачи данных
  httpconnect : TIdHTTP;
begin

  try
    // Создаём подключение
    httpconnect := TIdHTTP.Create;
    // Указываем данные для отправки
    postdata := TStringList.Create;
    postdata.Add('action=register-device');
    postdata.Add('did=' + DeviceID);
    postdata.Add('token=' + DeviceToken);
    {$ifdef ANDROID}
      postdata.Add('platform=android');
    {$else}
      postdata.Add('platform=ios');
    {$endif}

    // Отправляем запрос
    httpconnect.Post(DOMAIN + 'push.php', postdata);
  finally
    // Отключаемся и освобождаем память
    httpconnect.Disconnect;
    httpconnect.DisposeOf;
    IF Assigned( postdata  ) THEN BEGIN
      postdata.DisposeOf;
      postdata := Nil;
   END; 

  end;
end;

Просто в С++ я использую при объявлении умный указатель unique_ptr и меня не волнует освобождение памяти т.к. этот указатель сам все делает и за всем следит когда освобождать правильно память.

И остаеться вопрос, как в моем случае правильно объявить

const
// Доменное имя сайта
DOMAIN: string = ?

Спасибо.

Изменено пользователем Kitty

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не используйте TIdHTTP, с ним будут проблемы. Post тоже не обязательно, вот простой работающий код :

Var AHTTPClient : THTTPClient;
	HTTPQuery : String;
begin
	HTTPQuery:=APIURL+'?DeviceID='+HDevicePushParams.DeviceID+'&DeviceToken='+HDevicePushParams.DeviceToken;
	AHTTPClient:=THTTPClient.Create;
	AHTTPClient.Get(HTTPQuery);
	AHTTPClient.Free;
end;
	

Вместо AHTTPClient.Get(HTTPQuery), можно использовать асинхронный запрос AHTTPClient.BeginGet(HTTPQuery), тогда приложение не будет записать при недоступности сервера или проблемах с связью.

Изменено пользователем Евгений Корепов

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я пытаюсь адаптировать статью этого топика. Т.е в статье присутствует .pas файл с нужным функционалом. Как этот файл будут выглядеть в окончательном виде с THTTPClient?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 09.04.2017 в 16:27, Kitty сказал:

const
  // Доменное имя сайта
  DOMAIN: string = '193.106.248.115/Push_Server';

Не знаю правильно ли указывать папку вместе с именем сайта, но обычно папки разделяют так

const
  // Доменное имя сайта
  DOMAIN = '193.106.248.115\Push_Server';

Изменено пользователем GASCHE

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Похожие публикации

    • Автор: Роман Фил
      Привет Всем уважаемые! 
      Пытаюсь сделать растягивание по содержимому компонента. Как это реализовано в мессенджерах типа WhatsApp если большой текст то растягивает (выделяется) по содержимому большое поле, если короткий то малое. 
        Text2.Text := Memo1.Lines.Strings[4];   text2.Height := canvas.TextHeight(Text2.Text); //по высоте строки меняется т.к. там и есть одна строка в TText просто переносится WordWrap визуально.   text2.Height:=canvas.TextWidth(text2.Text); //  - так чушь  Как это вообще реализовано кто нибудь сталкивался?

    • Автор: Роман Фил
      Привет ребят! Помогите кто знает, попытаюсь доходчиво объяснить - 
      имеется набор компонентов KernowSoftwareFMX - в нем использую TksTableView для вывода данных с Tmemo, в нем так же есть Image.
      В Tmemo с сервера грузится файл txt внутри которого строки с ссылками на изображения вида http://бла-бла/1.png
      Для загрузки использую FMX.Features.Bitmap.Helpers.pas - позволяет по прямой ссылке загружать изображение в TImage.
      что пытаюсь сделать?
      Нужно наполнять список TksTableView с Memo содержащий ссылки и в строках TksTableView - они же ListItem тоже самое что в ListView  и загружать в image каждой строки картинки по ссылкам memo.
       
      AItem.Image.Bitmap := Image4.MultiResBitmap.Bitmaps[1].LoadFromUrl(Memo1.Lines.Strings[i]); - так ругается [DCC Error] untMain.pas(92): E2010 Incompatible types: 'TBitmap' and 'procedure, untyped pointer or untyped parameter' AItem.Image.Bitmap := Image4.Bitmap.LoadFromUrl(Memo1.Lines.Strings[i]); - так тожн не работает Глюк в том что первым делом создаются строки . а потом грузятся по очереди картинки в Image4.
      Как заставить подгружать картинки в  TksTableView?
      Как ожидать хавершения загрузки каждой картинки в Image4 и после создавать AItem.Image.Bitmap?
       
       
       
    • Автор: Роман Фил
      Всем привет пытаюсь грузить файлы изображения с телефона Android на сервер методом post запроса. Для этого один из параметров запроса должен содержать полный путь к файлу. В ActionList есть стандартная опция TakePhotoFromLibraryAction - к с нее выдрать путь??? Куда он ей передается и передается ли вообще? я и справки толком не нахожу или я слепой?
       
      imgfile.Text:=TakePhotoFromLibraryAction1.????  
    • Автор: Rusland
      Приложение свернуто или закрыто.
      Отправляю один пуш, на телефоне в шторке появляется уведомление.
      Отправляю еще один, появляется второе уведомление и так далее. Сколько пушей, столько и уведомлений.
      Как сделать чтобы все уведомления собирались в одном уведомлении в шторке? (как делают telegram, whatsapp и т. п.)
    • Автор: Роман Фил
      Привет ребят, созрел такой вопрос который меня мучает ! Вобщем пытаюсь загрузить картинку по прямой слыке с сервера. Картинка не грузится, не сохраняется не отображается. 
      Конечная платформа - Андроид. Пишу на Delphi xe 10 seatle.
      Что я делаю? при нажатии на сам компонент TImage (созданный динамически), должна грузится картинка по адресу преждевременно записанное в hint (TImage) при создании вида (http://блаблабла.jpg)
      Раньше код ниже работал сейчас нет не пойму что не так. Почему стал ковырять? потому что форма встает колом при загрузке изображений.
       
      var s: string; fs: TFileStream; begin fs := TFileStream.Create(tpath.Combine(tpath.GetDownloadsPath, 'load.jpg'), fmCreate); NetHTTPClient1.Get((Sender as TImage).Hint, fs); fs.Free; (Sender as TImage).MultiResBitmap.Bitmaps[1].LoadFromFile (tpath.Combine(tpath.GetDownloadsPath, 'load.jpg')); подключал еще pas нашел на этом форуме FMX.Features.Bitmap.Helpers.pas
      (Sender as TImage).MultiResBitmap.Bitmaps[1].LoadFromUrl ((Sender as TImage).Hint); как проще сделать посоветуете чтоб и грузилось и форма не висла?
    • Автор: Astghik
      How to print text from Android (IOS) device ? (C++ Rad Studio 10.2)
      With USB printer and other types printers (WiFi, Bluetooth ....)
    • Автор: Rionn
      В этой ссылке показан пример работы в одной сети (написано курсивом). Не могу найти, чтобы PC работал по сети или по WiFi, а телефон по мобильным данным. Не подскажете?
  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу