Eu tenho o mesmo problema com um projeto no qual estou trabalhando, a solução no meu caso foi criar um campo anulável extra nas tabelas locais denominadas remote_id. Ao sincronizar registros do banco de dados local para o remoto, se remote_id for nulo, isso significa que essa linha nunca foi sincronizada e precisa retornar um ID exclusivo que corresponda ao ID da linha remota.
Local Table Remote Table
_id (used locally)
remote_id ------------- id
name ------------- name
No aplicativo cliente, vinculo tabelas pelo campo _id, remotamente uso o campo de identificação remota para buscar dados, fazer junções, etc.
exemplo localmente:
Local Client Table Local ClientType Table Local ClientType
_id
remote_id
_id -------------------- client_id
remote_id client_type_id -------------- _id
remote_id
name name name
exemplo remotamente:
Remote Client Table Remote ClientType Table Remote ClientType
id -------------------- client_id
client_type_id -------------- id
name name name
Esse cenário, e sem lógica no código, causaria falhas na integridade dos dados, pois a tabela client_type pode não corresponder ao ID real nas tabelas local ou remota; portanto, sempre que um remote_id é gerado, ele retorna um sinal para o aplicativo cliente pedindo para atualizar o campo _id local, isso dispara um gatilho criado anteriormente no sqlite, atualizando as tabelas afetadas.
http://www.sqlite.org/lang_createtrigger.html
1- remote_id é gerado no servidor
2- retorna um sinal para o cliente
3- o cliente atualiza seu campo _id e dispara um gatilho que atualiza as tabelas locais que se juntam ao _id local
Claro que também uso um campo last_updated para ajudar nas sincronizações e evitar sincronizações duplicadas.